From 175ada2249cd110ede45468b8c821706525695f8 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 11 Oct 2018 17:00:28 +0200 Subject: [PATCH 01/31] qmake: fix test for $ANDROID_NDK_ROOT there is no reason whatsoever to ignore the variable if it's set to an invalid value. also, it being empty would lead to a warning from qmake since a while. so instead check it for emptiness like every other variable, not for file existence. Change-Id: I1119f67520d2986811501cd3f223f8f4a87d067d Reviewed-by: Eskil Abrahamsen Blomfeldt --- mkspecs/common/android-base-head.conf | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mkspecs/common/android-base-head.conf b/mkspecs/common/android-base-head.conf index c7c27298b9..93e7ba3ed4 100644 --- a/mkspecs/common/android-base-head.conf +++ b/mkspecs/common/android-base-head.conf @@ -4,9 +4,7 @@ load(device_config) isEmpty(DEFAULT_ANDROID_NDK_ROOT): return() NDK_ROOT = $$(ANDROID_NDK_ROOT) -!exists($$NDK_ROOT) { - NDK_ROOT = $$DEFAULT_ANDROID_NDK_ROOT -} +isEmpty(NDK_ROOT): NDK_ROOT = $$DEFAULT_ANDROID_NDK_ROOT NDK_HOST = $$(ANDROID_NDK_HOST) isEmpty(NDK_HOST): NDK_HOST = $$DEFAULT_ANDROID_NDK_HOST From 659eff9f2dbefaead70ff091b5ddaf1efb7f8c8f Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 12 Oct 2018 14:37:13 +0200 Subject: [PATCH 02/31] qmake: prune dead assignments from android spec Change-Id: Ide2bbe7116c24c6b952db835c23ebf2859f18c5f Reviewed-by: BogDan Vatra --- mkspecs/common/android-base-head.conf | 4 ---- mkspecs/common/android-base-tail.conf | 1 - 2 files changed, 5 deletions(-) diff --git a/mkspecs/common/android-base-head.conf b/mkspecs/common/android-base-head.conf index 93e7ba3ed4..a43fc7f23e 100644 --- a/mkspecs/common/android-base-head.conf +++ b/mkspecs/common/android-base-head.conf @@ -67,10 +67,6 @@ CONFIG += $$ANDROID_PLATFORM QMAKE_CFLAGS = -D__ANDROID_API__=$$replace(ANDROID_PLATFORM, "android-", "") ANDROID_PLATFORM_ROOT_PATH = $$NDK_ROOT/platforms/$$ANDROID_PLATFORM/arch-$$ANDROID_ARCHITECTURE/ -ANDROID_PLATFORM_PATH = $$ANDROID_PLATFORM_ROOT_PATH/usr - -equals(ANDROID_TARGET_ARCH, x86_64)|equals(ANDROID_TARGET_ARCH, mips64): \ - QMAKE_ANDROID_PLATFORM_LIBDIR = $${QMAKE_ANDROID_PLATFORM_LIBDIR}64 CROSS_COMPILE = $$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX- diff --git a/mkspecs/common/android-base-tail.conf b/mkspecs/common/android-base-tail.conf index e239fa01c5..57f009f78f 100644 --- a/mkspecs/common/android-base-tail.conf +++ b/mkspecs/common/android-base-tail.conf @@ -69,7 +69,6 @@ QMAKE_LIBDIR_OPENGL = QMAKE_LINK_SHLIB = $$QMAKE_LINK QMAKE_LFLAGS = --sysroot=$$ANDROID_PLATFORM_ROOT_PATH -QMAKE_RPATHLINK = $$QMAKE_ANDROID_PLATFORM_LIBDIR QMAKE_LFLAGS_APP = -Wl,--no-undefined -Wl,-z,noexecstack -shared QMAKE_LFLAGS_SHLIB = -Wl,--no-undefined -Wl,-z,noexecstack -shared QMAKE_LFLAGS_PLUGIN = $$QMAKE_LFLAGS_SHLIB From 7e27afd88fbc28f767a51e39dda780290f65a7fb Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 11 Oct 2018 14:26:24 +0200 Subject: [PATCH 03/31] configure: log -I and -L before doing first library check ... for debugging purposes. this needs to work in every configure run even though the options (currently) come from qtbase's global scope. this is accomplished by automatically injecting the test type dependencies declared in the 'builtins' scope (where they generally make no sense whatsoever, because there are no tests there) into other scopes (the first one that has a test of the particular type, specifically). we do that *after* the scope's own test type deps, so it can do its custom stuff first (it can explicitly activate the required features if it depends on some global stuff). Change-Id: I67317da1b55804d39458bdbcf13d39a3e57a13bf Reviewed-by: Joerg Bornemann Reviewed-by: Oswald Buddenhagen --- mkspecs/features/data/configure.json | 10 ++++++++++ mkspecs/features/qt_configure.prf | 26 ++++++++++++++++++++------ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/mkspecs/features/data/configure.json b/mkspecs/features/data/configure.json index 167c502e82..faa89231a0 100644 --- a/mkspecs/features/data/configure.json +++ b/mkspecs/features/data/configure.json @@ -17,5 +17,15 @@ "list-features": "void", "list-libraries": "void" } + }, + + "testTypeDependencies": { + "library": [ "library-paths" ] + }, + + "features": { + "library-paths": { + "output": [ "libraryPaths" ] + } } } diff --git a/mkspecs/features/qt_configure.prf b/mkspecs/features/qt_configure.prf index 81b820978a..2cc6b49d3c 100644 --- a/mkspecs/features/qt_configure.prf +++ b/mkspecs/features/qt_configure.prf @@ -1156,7 +1156,7 @@ defineTest(qtConfSetupTestTypeDeps) { } } -defineTest(qtConfEnsureTestTypeDeps) { +defineTest(qtConfEnsureTestTypeDepsOne) { depsn = $${currentConfig}.testTypeDependencies.$${1}._KEYS_ !isEmpty($$depsn) { for (dep, $$depsn) { @@ -1170,12 +1170,18 @@ defineTest(qtConfEnsureTestTypeDeps) { fwdsn = $${currentConfig}.testTypeForwards.$${1} !isEmpty($$fwdsn) { for (fwd, $$fwdsn): \ - qtConfEnsureTestTypeDeps($$fwd) + qtConfEnsureTestTypeDepsOne($$fwd) $$fwdsn = export($$fwdsn) } } +defineTest(qtConfEnsureTestTypeDeps) { + qtConfEnsureTestTypeDepsOne($$1) + currentConfig = config.builtins + qtConfEnsureTestTypeDepsOne($$1) +} + defineTest(qtRunSingleTest) { tpfx = $${currentConfig}.tests.$${1} defined($${tpfx}.result, var): \ @@ -1660,6 +1666,11 @@ defineTest(qtConfCheckErrors) { # output generation # +defineTest(qtConfOutput_libraryPaths) { + qtLog("Global lib dirs: [$$val_escape(EXTRA_LIBDIR)] [$$val_escape(QMAKE_DEFAULT_LIBDIRS)]") + qtLog("Global inc dirs: [$$val_escape(EXTRA_INCLUDEPATH)] [$$val_escape(QMAKE_DEFAULT_INCDIRS)]") +} + # qtConfOutputVar(modifier, output, name, value) defineTest(qtConfOutputVar) { modifier = $$1 @@ -2028,6 +2039,9 @@ for(ever) { } configsToProcess = $$subconfigs $$configsToProcess } +# 'builtins' is used for command line parsing and test type dependency +# injection, but its features must not be processed regularly. +allModuleConfigs = $$member(allConfigs, 1, -1) QMAKE_SAVED_ARGS = $$QMAKE_EXTRA_ARGS QMAKE_REDO_CONFIG = false @@ -2036,7 +2050,7 @@ qtConfCheckErrors() !isEmpty(config.input.list-features) { all_ft = - for (currentConfig, allConfigs) { + for (currentConfig, allModuleConfigs) { for (k, $${currentConfig}.features._KEYS_) { pp = $$eval($${currentConfig}.features.$${k}.purpose) !isEmpty(pp) { @@ -2056,7 +2070,7 @@ qtConfCheckErrors() !isEmpty(config.input.list-libraries) { logn() - for (currentConfig, allConfigs) { + for (currentConfig, allModuleConfigs) { !isEmpty($${currentConfig}.exports._KEYS_) { !isEmpty($${currentConfig}.module): \ logn($$eval($${currentConfig}.module):) @@ -2093,7 +2107,7 @@ qtLog("Command line: $$qtSystemQuote($$QMAKE_SAVED_ARGS)") $$QMAKE_REDO_CONFIG: \ qtLog("config.opt: $$qtSystemQuote($$QMAKE_EXTRA_REDO_ARGS)") -for (currentConfig, allConfigs) { +for (currentConfig, allModuleConfigs) { qtConfSetModuleName() qtConfSetupModuleOutputs() # do early checks, mainly to validate the command line @@ -2137,7 +2151,7 @@ CONFIG += qt_conf_tests_allowed logn() logn("Running configuration tests...") -for (currentConfig, allConfigs) { +for (currentConfig, allModuleConfigs) { tdir = $$eval($${currentConfig}.testDir) isEmpty(tdir): tdir = config.tests QMAKE_CONFIG_TESTS_DIR = $$absolute_path($$tdir, $$eval($${currentConfig}.dir)) From bec8b75b8a2a3574053036fa6ce0992176c304f5 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 12 Oct 2018 15:34:36 +0200 Subject: [PATCH 04/31] configure: make config.status work for in-source builds on unix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ib2a62e71a88f46836c10b0d9c47da5ad1f98d413 Reviewed-by: Tor Arne Vestbø Reviewed-by: Oswald Buddenhagen --- configure.pri | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.pri b/configure.pri index 64ed6b9ed8..e04a7a24cd 100644 --- a/configure.pri +++ b/configure.pri @@ -1303,6 +1303,7 @@ defineTest(createConfigStatus) { cont = \ "$$system_quote($$system_path($$cfg)$$ext) -redo %*" } else { + !contains(cfg, .*/.*): cfg = ./$$cfg cont = \ "$${LITERAL_HASH}!/bin/sh" \ "exec $$system_quote($$cfg) -redo \"$@\"" From 6bea0398eadb08c69727dd2ec8919aa4e5f98b07 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 12 Oct 2018 15:51:38 +0200 Subject: [PATCH 05/31] configure: fix bogus message about not needing to install qt when building additional modules against an already installed qtbase, $$[QT_INSTALL_PREFIX/get] is obviously the same as $$[QT_INSTALL_PREFIX], so we would misdiagnose a non-prefix build. instead, use the same condition as qt_build_config.prf (we cannot just rely on what it sets, because in qtbase configure context it's evaluated before we set up the paths). Fixes: QTBUG-60541 Change-Id: I37be30e0e682ece76ed460a66f1984ee0fe2ed71 Reviewed-by: Thiago Macieira Reviewed-by: Oswald Buddenhagen --- mkspecs/features/qt_configure.prf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkspecs/features/qt_configure.prf b/mkspecs/features/qt_configure.prf index 2cc6b49d3c..65ee7df50b 100644 --- a/mkspecs/features/qt_configure.prf +++ b/mkspecs/features/qt_configure.prf @@ -2215,7 +2215,7 @@ qtConfPrintReport() logn() logn("Qt is now configured for building. Just run '$$QMAKE_MAKE_NAME'.") pfx = $$[QT_INSTALL_PREFIX] -equals(pfx, $$[QT_INSTALL_PREFIX/get]) { +exists($$pfx/.qmake.cache) { logn("Once everything is built, Qt is installed.") logn("You should NOT run '$$QMAKE_MAKE_NAME install'.") logn("Note that this build cannot be deployed to other machines or devices.") From 4e6a3c7def9b634ccb79a5ba3010d8df0d6fdae3 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 15 Oct 2018 11:02:12 +0200 Subject: [PATCH 06/31] configure: fix license determination failure message we don't check for licheck at this stage any more. amends 60e56f167. Change-Id: I4f8d57100796dce99bd605835b25a954a6359d30 Reviewed-by: Kai Koehne --- configure.pri | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/configure.pri b/configure.pri index e04a7a24cd..b3b3e27c44 100644 --- a/configure.pri +++ b/configure.pri @@ -106,8 +106,7 @@ defineReplace(qtConfFunc_licenseCheck) { } } else { !$$hasCommercial: \ - qtConfFatalError("No license files and no licheck executables found." \ - "Cannot proceed. Try re-installing Qt.") + qtConfFatalError("No license files. Cannot proceed. Try re-installing Qt.") commercial = yes } } From ac4dd6e8f6a03bc65cdcfe3749ba2096d5a72727 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 19 Oct 2018 19:23:59 +0200 Subject: [PATCH 07/31] wasm: fix location and language of comment Change-Id: I7c9c65d037f808371a778e51d0877ed579ae8b26 Reviewed-by: Lorn Potter --- mkspecs/wasm-emscripten/qmake.conf | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mkspecs/wasm-emscripten/qmake.conf b/mkspecs/wasm-emscripten/qmake.conf index c3b67310c8..0b72fcf0a8 100644 --- a/mkspecs/wasm-emscripten/qmake.conf +++ b/mkspecs/wasm-emscripten/qmake.conf @@ -28,6 +28,8 @@ EMCC_COMMON_LFLAGS = \ -s \"BINARYEN_METHOD=\'native-wasm\'\" \ -s \"BINARYEN_TRAP_MODE=\'clamp\'\" +# The -s arguments can also be used with release builds, +# but are here in debug for clarity. EMCC_COMMON_LFLAGS_DEBUG = \ $$EMCC_COMMON_LFLAGS \ -s ASSERTIONS=2 \ @@ -38,9 +40,6 @@ EMCC_COMMON_LFLAGS_DEBUG = \ # -s SOCKET_DEBUG \ #print out socket,network data transfer -s GL_DEBUG=1 -# the -s arguments can also be used with release builds -# but here in debug for clarity - QMAKE_COMPILER += emscripten QMAKE_CC = emcc From eea08d376ac5cb35ff03be630923f21f7fa3aecd Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 19 Oct 2018 19:24:34 +0200 Subject: [PATCH 08/31] wasm: remove seemingly pointless -s flags these libraries are handled by the configure system. i presume this to be an artifact of an early version. Change-Id: Ieee0554163a9fe296097d09e60a70719beee97b4 Reviewed-by: Lorn Potter --- mkspecs/wasm-emscripten/qmake.conf | 8 -------- 1 file changed, 8 deletions(-) diff --git a/mkspecs/wasm-emscripten/qmake.conf b/mkspecs/wasm-emscripten/qmake.conf index 0b72fcf0a8..e8ad5e18e7 100644 --- a/mkspecs/wasm-emscripten/qmake.conf +++ b/mkspecs/wasm-emscripten/qmake.conf @@ -12,11 +12,6 @@ EMTERP_FLAGS = \ -s ASSERTIONS=1 \ --profiling-funcs -EMCC_COMMON_CFLAGS = \ - -s USE_LIBPNG=1 \ - -s USE_FREETYPE=1 \ - -s USE_ZLIB=1 - EMCC_COMMON_LFLAGS = \ -s WASM=1 \ -s FULL_ES2=1 \ @@ -45,9 +40,6 @@ QMAKE_COMPILER += emscripten QMAKE_CC = emcc QMAKE_CXX = em++ -QMAKE_CFLAGS += $$EMCC_COMMON_CFLAGS -QMAKE_CXXFLAGS += $$EMCC_COMMON_CFLAGS - # Practical debugging setup: # "-g4" preserves function names for stack traces # "-Os" produces reasonably sized binaries From f5f46aaf421b2acbec3569a553973ccda223062c Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 19 Oct 2018 19:26:20 +0200 Subject: [PATCH 09/31] wasm: fix qmake variable names for optimization flags Change-Id: I43c0a94312504948c0db390994656d5f655c8d4c Reviewed-by: Lorn Potter --- mkspecs/wasm-emscripten/qmake.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mkspecs/wasm-emscripten/qmake.conf b/mkspecs/wasm-emscripten/qmake.conf index e8ad5e18e7..7090fa65dc 100644 --- a/mkspecs/wasm-emscripten/qmake.conf +++ b/mkspecs/wasm-emscripten/qmake.conf @@ -54,8 +54,8 @@ QMAKE_CXXFLAGS_RELEASE += -O3 QMAKE_CFLAGS_RELEASE -= -O2 QMAKE_CFLAGS_RELEASE += -O3 QMAKE_LFLAGS_RELEASE += -O3 -MAKE_CFLAGS_OPTIMIZE += -O3 -MAKE_CFLAGS_OPTIMIZE_FULL += -Oz +QMAKE_CFLAGS_OPTIMIZE += -O3 +QMAKE_CFLAGS_OPTIMIZE_FULL += -Oz QMAKE_LINK = $$QMAKE_CXX QMAKE_LINK_SHLIB = $$QMAKE_CXX From 54dabdd1e831491359e85fae444ab3ec700a0d2b Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 29 Oct 2018 17:04:38 +0100 Subject: [PATCH 10/31] wasm: fix qpa plugin build system integration fix the plugin name (it was missing the leading 'q') and the name used in configure (the latter making it unnecessary to mess with it in the mkspec). the qt.prf override which forced linkage of the plugin is also removed due to being completely redundant. Change-Id: I94687a34a295c36754e36a298af902b656ba2ecc Reviewed-by: Kyle Edwards Reviewed-by: Lorn Potter --- mkspecs/features/wasm/qt.prf | 12 ------------ mkspecs/wasm-emscripten/qmake.conf | 3 --- src/gui/configure.pri | 2 +- src/plugins/platforms/wasm/wasm.pro | 2 +- 4 files changed, 2 insertions(+), 17 deletions(-) delete mode 100644 mkspecs/features/wasm/qt.prf diff --git a/mkspecs/features/wasm/qt.prf b/mkspecs/features/wasm/qt.prf deleted file mode 100644 index 9b9b58d3de..0000000000 --- a/mkspecs/features/wasm/qt.prf +++ /dev/null @@ -1,12 +0,0 @@ - -qt_depends = $$resolve_depends(QT, "QT.") -equals(TEMPLATE, app):contains(qt_depends, gui(-private)?) { - LIBS *= -L$$[QT_INSTALL_PLUGINS/get]/platforms - - lib_name = wasm - lib_path_and_base = $$[QT_INSTALL_PLUGINS/get]/platforms/lib$${lib_name}$$qtPlatformTargetSuffix() - LIBS += -l$${lib_name}$$qtPlatformTargetSuffix() $$fromfile($${lib_path_and_base}.prl, QMAKE_PRL_LIBS) -} - -load(qt) - diff --git a/mkspecs/wasm-emscripten/qmake.conf b/mkspecs/wasm-emscripten/qmake.conf index 7090fa65dc..2539770b51 100644 --- a/mkspecs/wasm-emscripten/qmake.conf +++ b/mkspecs/wasm-emscripten/qmake.conf @@ -75,7 +75,4 @@ QMAKE_EXTENSION_STATICLIB = a # llvm bitcode QMAKE_AR = emar cqs QMAKE_DISTCLEAN += *.html *.js *.wasm -QT_QPA_DEFAULT_PLATFORM = wasm - -QTPLUGIN.platforms = wasm load(qt_config) diff --git a/src/gui/configure.pri b/src/gui/configure.pri index 2971fd136e..e21489ec28 100644 --- a/src/gui/configure.pri +++ b/src/gui/configure.pri @@ -55,7 +55,7 @@ defineTest(qtConfTest_qpaDefaultPlatform) { else: qnx: name = qnx else: integrity: name = integrityfb else: haiku: name = haiku - else: wasm: name = webassembly + else: wasm: name = wasm else: name = xcb $${1}.value = $$name diff --git a/src/plugins/platforms/wasm/wasm.pro b/src/plugins/platforms/wasm/wasm.pro index f1205702ef..eaaba53aa2 100644 --- a/src/plugins/platforms/wasm/wasm.pro +++ b/src/plugins/platforms/wasm/wasm.pro @@ -1,4 +1,4 @@ -TARGET = wasm +TARGET = qwasm CONFIG += static plugin QT += \ core-private gui-private \ From b1d6f64a94daef5ef3ca122246827818d1f12bba Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 29 Oct 2018 17:11:17 +0100 Subject: [PATCH 11/31] integrity: don't mess with QTPLUGIN.platforms this is an exclusively user-controllable variable. the mkspec may provide a default via QT_QPA_DEFAULT_PLATFORM when it deviates from the platform default known to configure, and these specs actually already make use of that. Change-Id: I7531063d4c404ebed7b2cc1647c61626db30daef Reviewed-by: Kyle Edwards Reviewed-by: Laszlo Agocs --- mkspecs/integrity-armv7-imx6/qmake.conf | 1 - mkspecs/integrity-armv7/qmake.conf | 2 -- mkspecs/integrity-armv8-rcar/qmake.conf | 1 - mkspecs/integrity-x86/qmake.conf | 2 -- 4 files changed, 6 deletions(-) diff --git a/mkspecs/integrity-armv7-imx6/qmake.conf b/mkspecs/integrity-armv7-imx6/qmake.conf index 3bf2abd844..eed6d41d35 100644 --- a/mkspecs/integrity-armv7-imx6/qmake.conf +++ b/mkspecs/integrity-armv7-imx6/qmake.conf @@ -6,7 +6,6 @@ include(../common/ghs-integrity-armv7.conf) DEFINES += QT_STATICPLUGIN -QTPLUGIN.platforms += qeglfs qeglfs-viv-integration QT_QPA_DEFAULT_PLATFORM = eglfs QMAKE_LIBS_EGL += -lEGL -lGAL -lVSC -lGLSLC -lGLESv2 -lfbdev -livfs diff --git a/mkspecs/integrity-armv7/qmake.conf b/mkspecs/integrity-armv7/qmake.conf index 7a2ffaba14..002c8b544e 100644 --- a/mkspecs/integrity-armv7/qmake.conf +++ b/mkspecs/integrity-armv7/qmake.conf @@ -5,5 +5,3 @@ include(../common/ghs-integrity-armv7.conf) DEFINES += QT_STATICPLUGIN - -QTPLUGIN.platforms += integrityfb diff --git a/mkspecs/integrity-armv8-rcar/qmake.conf b/mkspecs/integrity-armv8-rcar/qmake.conf index 46091f6a91..2dbe924086 100644 --- a/mkspecs/integrity-armv8-rcar/qmake.conf +++ b/mkspecs/integrity-armv8-rcar/qmake.conf @@ -11,7 +11,6 @@ DEFINES += INTEGRITY # parameter types as Symbian. The parameter types are defined in eglplatform.h. DEFINES += __WINSCW__ -QTPLUGIN.platforms += qeglfs QT_QPA_DEFAULT_PLATFORM = eglfs QMAKE_LIBS_EGL += -lEGL -lIMGegl -lsrv_um -lsrv_init -lpvrWSEGL_WM -lncg_usr.a -lmmgr_usr -lwm_usr -lprr_usr diff --git a/mkspecs/integrity-x86/qmake.conf b/mkspecs/integrity-x86/qmake.conf index 13d4a6c082..9e3569d15c 100644 --- a/mkspecs/integrity-x86/qmake.conf +++ b/mkspecs/integrity-x86/qmake.conf @@ -6,5 +6,3 @@ include(../common/ghs-integrity-x86.conf) QMAKE_CFLAGS += -cpu=Corei DEFINES += QT_STATICPLUGIN - -QTPLUGIN.platforms += integrityfb From 364337a27fce1fdc85f2ddece60bd3412060b79b Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Thu, 15 Nov 2018 10:55:23 +0100 Subject: [PATCH 12/31] Remove duplicated documentation from package_manifest.prf Descriptions for WINRT_MANIFEST's subkeys are in the documentation. Having a copy in the prf file is superfluous and is likely to run out of sync at some point. Change-Id: Icea49854981990139305f6dc4e73d1b9dcb01dd5 Reviewed-by: Oliver Wolff Reviewed-by: Oswald Buddenhagen --- mkspecs/features/winrt/package_manifest.prf | 29 +-------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/mkspecs/features/winrt/package_manifest.prf b/mkspecs/features/winrt/package_manifest.prf index d850254dcf..143b884dbf 100644 --- a/mkspecs/features/winrt/package_manifest.prf +++ b/mkspecs/features/winrt/package_manifest.prf @@ -5,34 +5,7 @@ # Afterwards, they can override the default template by assigning their template to WINRT_MANIFEST. # # All subkeys in WINRT_MANIFEST will be replaced if defined/found, so new variables can be easily -# added. The following keys have default values and are present in the default templates: -# WINRT_MANIFEST: The name of the input manifest file. Defaults to a file defined by the mkspec. -# WINRT_MANIFEST.target: The name of the target (.exe). Defaults to TARGET. -# WINRT_MANIFEST.identity: The unique ID of the app. Defaults to reusing the existing generated manifest's UUID, or generates a new UUID if none is present. -# WINRT_MANIFEST.name: The name of the package as displayed to the user. Defaults to TARGET. -# WINRT_MANIFEST.architecture: The target architecture. Defaults to VCPROJ_ARCH. -# WINRT_MANIFEST.version: The version number of the package. Defaults to "1.0.0.0". -# WINRT_MANIFEST.publisher: Display name of the publisher. Defaults to "Default publisher display name". -# WINRT_MANIFEST.publisher_id: The publisher's distinguished name (default: CN=MyCN). -# WINRT_MANIFEST.phone_product_id: The GUID of the product. Defaults to the value of WINRT_MANIFEST.identity. (Windows Phone only) -# WINRT_MANIFEST.phone_publisher_id: The GUID of the publisher. Defaults to an invalid GUID. (Windows Phone only) -# WINRT_MANIFEST.description: Package description. Defaults to "Default package description". -# WINRT_MANIFEST.background: Tile background color. Defaults to "green". -# WINRT_MANIFEST.foreground: Tile foreground (text) color (Windows 8/RT only). Defaults to "light". -# WINRT_MANIFEST.logo_store: Logo image file for Windows Store. Default provided by the mkspec. -# WINRT_MANIFEST.logo_small: Small logo image file. Default provided by the mkspec. -# WINRT_MANIFEST.logo_medium: Medium logo image file. Default provided by the mkspec. -# WINRT_MANIFEST.logo_large: Large logo image file. Default provided by the mkspec. -# WINRT_MANIFEST.splash_screen: Splash screen image file. Default provided by the mkspec. -# WINRT_MANIFEST.rotation_preference: Orientation specification. Default is empty. (portrait, landscape, landscapeFlipped) -# WINRT_MANIFEST.iconic_tile_icon: Image file for the "iconic" tile template icon. Default provided by the mkspec. -# WINRT_MANIFEST.iconic_tile_small: Image file for the small "iconic" tile template logo. Default provided by the mkspec. -# WINRT_MANIFEST.default_language: Specifies the default language of the application -# WINRT_MANIFEST.capabilities: Specifies capabilities to add to the capability list. -# WINRT_MANIFEST.capabilities_device: Specifies device capabilities to add to the capability list. (location, webcam...) -# WINRT_MANIFEST.dependencies: Specifies dependencies required by the package. -# WINRT_MANIFEST.minVersion: Specifies the minimum required Windows version to run the package. Defaults to %UCRTVersion% -# WINRT_MANIFEST.maxVersionTested: Specifies the maximum Windows version the package has been tested against. Defaults to WINRT_MANIFEST.minVersion +# added. # The manifest is generated for each build pass for normal apps, and only once for vcapps. # - Normal apps have their package root directory in the same place as the target (one for each build pass). From e71b640f3cde7e748f962240489888325accbfeb Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Wed, 21 Nov 2018 15:19:50 +0100 Subject: [PATCH 13/31] Fix crash when painting with pattern brush to print device on macOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CGContextRelease was called twice, both manual and from the destructor of QMacCGContext. Change-Id: Icba7dcda37af7e1f7c72937b3dd2d2cc4ea22c63 Fixes: QTBUG-71934 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qpaintengine_mac.mm | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac.mm b/src/plugins/platforms/cocoa/qpaintengine_mac.mm index ce7f92f2c7..5c880b1cad 100644 --- a/src/plugins/platforms/cocoa/qpaintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qpaintengine_mac.mm @@ -313,7 +313,6 @@ static void qt_mac_draw_pattern(void *info, CGContextRef c) } pat->image = qt_mac_create_imagemask(pm, pm.rect()); CGImageRelease(swatch); - CGContextRelease(pm_ctx); w *= QMACPATTERN_MASK_MULTIPLIER; h *= QMACPATTERN_MASK_MULTIPLIER; #endif From c02d579c567a9e0413801aad87d3ecc9710ed2b2 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Wed, 21 Nov 2018 14:26:58 +0100 Subject: [PATCH 14/31] Remove usage of win32-msvc2012 qmake scope We don't support MSVC 2012 anymore. Change-Id: I454ba0f8e893f5910a17e473ab7cf70a1c581e81 Reviewed-by: Oliver Wolff --- tests/auto/corelib/kernel/qmetatype/qmetatype.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/corelib/kernel/qmetatype/qmetatype.pro b/tests/auto/corelib/kernel/qmetatype/qmetatype.pro index d70befecfd..56b8c071c3 100644 --- a/tests/auto/corelib/kernel/qmetatype/qmetatype.pro +++ b/tests/auto/corelib/kernel/qmetatype/qmetatype.pro @@ -10,7 +10,7 @@ msvc|winrt { # Prevents "fatal error C1128: number of sections exceeded object file format limit". QMAKE_CXXFLAGS += /bigobj # Reduce compile time - win32-msvc2012|winrt { + winrt { QMAKE_CXXFLAGS_RELEASE -= -O2 QMAKE_CFLAGS_RELEASE -= -O2 } From eef9b4f0d5c3582364e327eca302f9499dffeea3 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Wed, 21 Nov 2018 14:18:28 +0100 Subject: [PATCH 15/31] Use msvc qmake scope where appropriate Use 'msvc' instead of 'win32-msvc' or even 'win32-mscv*'. Change-Id: I21dc7748a4019119066aea0a88a29a61827f9429 Reviewed-by: Oliver Wolff Reviewed-by: Thiago Macieira Reviewed-by: Edward Welbourne --- src/winmain/winmain.pro | 8 ++++---- tests/auto/corelib/plugin/qlibrary/lib/lib.pro | 2 +- tests/auto/corelib/plugin/qlibrary/lib2/lib2.pro | 2 +- tests/auto/corelib/plugin/qpluginloader/lib/lib.pro | 2 +- tests/auto/corelib/tools/qdatetime/qdatetime.pro | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/winmain/winmain.pro b/src/winmain/winmain.pro index 4140ae48de..61e9f29d23 100644 --- a/src/winmain/winmain.pro +++ b/src/winmain/winmain.pro @@ -12,10 +12,10 @@ DEFINES += QT_NO_FOREACH qtConfig(debug_and_release): CONFIG += build_all -win32-msvc*:QMAKE_CFLAGS_DEBUG -= -Zi -win32-msvc*:QMAKE_CXXFLAGS_DEBUG -= -Zi -win32-msvc*:QMAKE_CFLAGS_DEBUG *= -Z7 -win32-msvc*:QMAKE_CXXFLAGS_DEBUG *= -Z7 +msvc: QMAKE_CFLAGS_DEBUG -= -Zi +msvc: QMAKE_CXXFLAGS_DEBUG -= -Zi +msvc: QMAKE_CFLAGS_DEBUG *= -Z7 +msvc: QMAKE_CXXFLAGS_DEBUG *= -Z7 mingw: DEFINES += QT_NEEDS_QMAIN winrt { diff --git a/tests/auto/corelib/plugin/qlibrary/lib/lib.pro b/tests/auto/corelib/plugin/qlibrary/lib/lib.pro index 3e15861021..c44cd46597 100644 --- a/tests/auto/corelib/plugin/qlibrary/lib/lib.pro +++ b/tests/auto/corelib/plugin/qlibrary/lib/lib.pro @@ -6,7 +6,7 @@ TARGET = mylib DESTDIR = ../ QT = core -win32-msvc: DEFINES += WIN32_MSVC +msvc: DEFINES += WIN32_MSVC # This project is testdata for tst_qlibrary target.path = $$[QT_INSTALL_TESTS]/tst_qlibrary diff --git a/tests/auto/corelib/plugin/qlibrary/lib2/lib2.pro b/tests/auto/corelib/plugin/qlibrary/lib2/lib2.pro index bd73227b3d..bfda0e0194 100644 --- a/tests/auto/corelib/plugin/qlibrary/lib2/lib2.pro +++ b/tests/auto/corelib/plugin/qlibrary/lib2/lib2.pro @@ -7,7 +7,7 @@ DESTDIR = ../ VERSION = 2 QT = core -win32-msvc: DEFINES += WIN32_MSVC +msvc: DEFINES += WIN32_MSVC # Force a copy of the library to have an extension that is non-standard. # We want to test if we can load a shared library with *any* filename... diff --git a/tests/auto/corelib/plugin/qpluginloader/lib/lib.pro b/tests/auto/corelib/plugin/qpluginloader/lib/lib.pro index 44b71e6e99..9fc76a4201 100644 --- a/tests/auto/corelib/plugin/qpluginloader/lib/lib.pro +++ b/tests/auto/corelib/plugin/qpluginloader/lib/lib.pro @@ -7,7 +7,7 @@ DESTDIR = ../bin winrt:include(../winrt.pri) QT = core -win32-msvc: DEFINES += WIN32_MSVC +msvc: DEFINES += WIN32_MSVC # This is testdata for the tst_qpluginloader test. target.path = $$[QT_INSTALL_TESTS]/tst_qpluginloader/bin diff --git a/tests/auto/corelib/tools/qdatetime/qdatetime.pro b/tests/auto/corelib/tools/qdatetime/qdatetime.pro index ba36621cf1..742eb47075 100644 --- a/tests/auto/corelib/tools/qdatetime/qdatetime.pro +++ b/tests/auto/corelib/tools/qdatetime/qdatetime.pro @@ -5,7 +5,7 @@ SOURCES = tst_qdatetime.cpp # For some reason using optimization here triggers a compiler issue, which causes an exception # However, the code is correct -win32-msvc|win32-msvc9x { +msvc { !build_pass:message ( "Compiler issue, removing -O1 flag" ) QMAKE_CFLAGS_RELEASE -= -O1 QMAKE_CXXFLAGS_RELEASE -= -O1 From a90694d1a60f30ec2abffbfa9e8c7a336c45e736 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Thu, 8 Nov 2018 13:09:25 +0100 Subject: [PATCH 16/31] syncqt: Do not clean header directory before "-minimal" run It is possible that "syncqt -minimal" is run after a module's initial run (for example if a host tool relies on a module, but cannot use it directly and thus adds minimal_syncqt to its .pro file). In this case, the old directory content should not be wiped. Fixes: QTBUG-59319 Change-Id: I83767eff0ef74bcefae5efa9b18b7ab3724138e5 Reviewed-by: Oswald Buddenhagen --- bin/syncqt.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/syncqt.pl b/bin/syncqt.pl index 77ce90c164..972717efcf 100755 --- a/bin/syncqt.pl +++ b/bin/syncqt.pl @@ -941,7 +941,7 @@ foreach my $lib (@modules_to_sync) { my %master_contents = (); #remove the old files - if($remove_stale) { + if ($remove_stale && !$minimal) { my %injections = (); for my $p (keys %inject_headers) { next unless ($p =~ /^\Q$dir\E(\/|$)/); From 14984bd59affd3d7f14bf8f67b58b7a87957ead6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 21 Nov 2018 15:47:18 +0100 Subject: [PATCH 17/31] macOS: Don't assume platform input context is our own A plugin (such as the Qt virtual keyboard) may provide a platform input context. Change-Id: I349ac6c4b96a3536bcde0d44a785cb7bb989fcc6 Fixes: QTBUG-68328 Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qnsview_complextext.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/cocoa/qnsview_complextext.mm b/src/plugins/platforms/cocoa/qnsview_complextext.mm index d357082d33..6ff9b26ca4 100644 --- a/src/plugins/platforms/cocoa/qnsview_complextext.mm +++ b/src/plugins/platforms/cocoa/qnsview_complextext.mm @@ -307,8 +307,8 @@ { Q_UNUSED(textInputContextKeyboardSelectionDidChangeNotification) if (([NSApp keyWindow] == self.window) && self.window.firstResponder == self) { - QCocoaInputContext *ic = qobject_cast(QCocoaIntegration::instance()->inputContext()); - ic->updateLocale(); + if (QCocoaInputContext *ic = qobject_cast(QCocoaIntegration::instance()->inputContext())) + ic->updateLocale(); } } From 7c93f1cf5d31cb1031fa52a0a610916e4f996457 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 9 Nov 2018 18:03:18 +0100 Subject: [PATCH 18/31] Remove macOS specific path that causes reverse vertical advance This special case of macOS appears to be outdated and now causes a bug. Change-Id: Ie9c074bb69eda7abfe3d123f807b517334cc2958 Fixes: QTBUG-69803 Reviewed-by: Eskil Abrahamsen Blomfeldt Reviewed-by: Konstantin Ritt --- src/gui/text/qharfbuzzng.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/gui/text/qharfbuzzng.cpp b/src/gui/text/qharfbuzzng.cpp index 36bd81c76b..21f880e7be 100644 --- a/src/gui/text/qharfbuzzng.cpp +++ b/src/gui/text/qharfbuzzng.cpp @@ -686,11 +686,7 @@ _hb_qt_font_create(QFontEngine *fe) const int x_ppem = (fe->fontDef.pixelSize * fe->fontDef.stretch) / 100; hb_font_set_funcs(font, hb_qt_get_font_funcs(), (void *)fe, NULL); -#ifdef Q_OS_MAC - hb_font_set_scale(font, QFixed(x_ppem).value(), QFixed(y_ppem).value()); -#else hb_font_set_scale(font, QFixed(x_ppem).value(), -QFixed(y_ppem).value()); -#endif hb_font_set_ppem(font, x_ppem, y_ppem); return font; From cbac5a1a6edfd0d7a1e351bbe50bab118d1155e5 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Tue, 13 Nov 2018 10:42:14 +0100 Subject: [PATCH 19/31] QLocalSocket (windows) - remove broken setErrorString MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We report two types of errors - those found by our code and errors coming from the OS. setErrorString(), despite its name, does not just set a string, but extracts a windows error code via GetLastError() and then calls _q_winError(). This is wrong: some arbitrary error code (or no error) can be reported when it was actually an error found by Qt. Worse yet, string operations (allocations etc.) can potentially clear the real error code. So remove setErrorString(), set errors explicitly if it's the application code error or use _q_WinError directly. Task-number: QTBUG-71744 Change-Id: I67277d84006c4ad365f5636caf850e1f3ba4e1dc Reviewed-by: Edward Welbourne Reviewed-by: Mårten Nordheim Reviewed-by: Timur Pocheptsov --- src/network/socket/qlocalsocket_p.h | 1 - src/network/socket/qlocalsocket_win.cpp | 16 ++++++---------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/network/socket/qlocalsocket_p.h b/src/network/socket/qlocalsocket_p.h index 8b72da397f..d93b53be0c 100644 --- a/src/network/socket/qlocalsocket_p.h +++ b/src/network/socket/qlocalsocket_p.h @@ -131,7 +131,6 @@ public: #elif defined(Q_OS_WIN) ~QLocalSocketPrivate(); void destroyPipeHandles(); - void setErrorString(const QString &function); void _q_canWrite(); void _q_pipeClosed(); void _q_winError(ulong windowsError, const QString &function); diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp index 8e20f9efbe..d6ee76043f 100644 --- a/src/network/socket/qlocalsocket_win.cpp +++ b/src/network/socket/qlocalsocket_win.cpp @@ -50,12 +50,6 @@ void QLocalSocketPrivate::init() q->connect(pipeReader, SIGNAL(winError(ulong,QString)), SLOT(_q_winError(ulong,QString))); } -void QLocalSocketPrivate::setErrorString(const QString &function) -{ - DWORD windowsError = GetLastError(); - _q_winError(windowsError, function); -} - void QLocalSocketPrivate::_q_winError(ulong windowsError, const QString &function) { Q_Q(QLocalSocket); @@ -127,7 +121,8 @@ void QLocalSocket::connectToServer(OpenMode openMode) { Q_D(QLocalSocket); if (state() == ConnectedState || state() == ConnectingState) { - setErrorString(tr("Trying to connect while connection is in progress")); + d->error = OperationError; + d->errorString = tr("Trying to connect while connection is in progress"); emit error(QLocalSocket::OperationError); return; } @@ -137,8 +132,8 @@ void QLocalSocket::connectToServer(OpenMode openMode) d->state = ConnectingState; emit stateChanged(d->state); if (d->serverName.isEmpty()) { - d->error = QLocalSocket::ServerNotFoundError; - setErrorString(QLocalSocket::tr("%1: Invalid name").arg(QLatin1String("QLocalSocket::connectToServer"))); + d->error = ServerNotFoundError; + d->errorString = tr("%1: Invalid name").arg(QLatin1String("QLocalSocket::connectToServer")); d->state = UnconnectedState; emit error(d->error); emit stateChanged(d->state); @@ -177,7 +172,8 @@ void QLocalSocket::connectToServer(OpenMode openMode) } if (localSocket == INVALID_HANDLE_VALUE) { - d->setErrorString(QLatin1String("QLocalSocket::connectToServer")); + const DWORD winError = GetLastError(); + d->_q_winError(winError, QLatin1String("QLocalSocket::connectToServer")); d->fullServerName = QString(); return; } From 4538dd7ec4efcce5760f87dc1751b142b8f35479 Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Mon, 12 Nov 2018 13:17:40 +0100 Subject: [PATCH 20/31] Remove need for glXGetProcAddressARB We do already require glXGetProcAddress in line 241. Fixes: QTBUG-71488 Change-Id: Id0f3bc256a71097241b99d2dcba927c1165e980e Reviewed-by: Gatis Paeglis --- .../xcb_glx/qglxintegration.cpp | 43 +------------------ 1 file changed, 1 insertion(+), 42 deletions(-) diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp index 2ffb5d2629..ddb8f45188 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp @@ -38,9 +38,6 @@ ****************************************************************************/ #include -#if QT_CONFIG(library) -#include -#endif #include "qxcbwindow.h" #include "qxcbscreen.h" @@ -61,10 +58,6 @@ #include "qxcbglintegration.h" -#if !defined(QT_STATIC) && QT_CONFIG(dlopen) -#include -#endif - QT_BEGIN_NAMESPACE typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); @@ -627,41 +620,7 @@ void QGLXContext::swapBuffers(QPlatformSurface *surface) QFunctionPointer QGLXContext::getProcAddress(const char *procName) { -#ifdef QT_STATIC - return glXGetProcAddressARB(reinterpret_cast(procName)); -#else - typedef void *(*qt_glXGetProcAddressARB)(const GLubyte *); - static qt_glXGetProcAddressARB glXGetProcAddressARB = 0; - static bool resolved = false; - - if (resolved && !glXGetProcAddressARB) - return 0; - if (!glXGetProcAddressARB) { - QList glxExt = QByteArray(glXGetClientString(m_display, GLX_EXTENSIONS)).split(' '); - if (glxExt.contains("GLX_ARB_get_proc_address")) { -#if QT_CONFIG(dlopen) - void *handle = dlopen(NULL, RTLD_LAZY); - if (handle) { - glXGetProcAddressARB = (qt_glXGetProcAddressARB) dlsym(handle, "glXGetProcAddressARB"); - dlclose(handle); - } - if (!glXGetProcAddressARB) -#endif - { -#if QT_CONFIG(library) - QLibrary lib(QLatin1String("GL")); - if (!lib.load()) - lib.setFileNameAndVersion(QLatin1String("GL"), 1); - glXGetProcAddressARB = (qt_glXGetProcAddressARB) lib.resolve("glXGetProcAddressARB"); -#endif - } - } - resolved = true; - } - if (!glXGetProcAddressARB) - return 0; - return (void (*)())glXGetProcAddressARB(reinterpret_cast(procName)); -#endif + return glXGetProcAddress(reinterpret_cast(procName)); } QSurfaceFormat QGLXContext::format() const From d0fadae79fb63aa4acc036571ecfe9e937fcc56b Mon Sep 17 00:00:00 2001 From: Dmitry Shachnev Date: Thu, 15 Nov 2018 11:34:36 +0300 Subject: [PATCH 21/31] qnetworkinterface_unix: Use qstrncpy instead of strlcpy strlcpy is not available on some UNIX platforms, such as GNU/kFreeBSD. qstrncpy is available everywhere and has similar semantics (in addition it fills the rest of buffer size with NULL bytes, but that does not cause extra work as our buffer sizes are small). Change-Id: I76c5905eba248fd9fbc1f63f05e88e0617f8407a Reviewed-by: Edward Welbourne Reviewed-by: Thiago Macieira --- src/network/kernel/qnetworkinterface_unix.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/network/kernel/qnetworkinterface_unix.cpp b/src/network/kernel/qnetworkinterface_unix.cpp index d69fc47667..8f290e5107 100644 --- a/src/network/kernel/qnetworkinterface_unix.cpp +++ b/src/network/kernel/qnetworkinterface_unix.cpp @@ -38,6 +38,7 @@ ** ****************************************************************************/ +#include "qbytearray.h" #include "qset.h" #include "qnetworkinterface.h" #include "qnetworkinterface_p.h" @@ -500,7 +501,7 @@ static QList createInterfaces(ifaddrs *rawList) iface->flags = convertFlags(ptr->ifa_flags); iface->hardwareAddress = iface->makeHwAddress(sdl->sdl_alen, (uchar*)LLADDR(sdl)); - strlcpy(mediareq.ifm_name, ptr->ifa_name, sizeof(mediareq.ifm_name)); + qstrncpy(mediareq.ifm_name, ptr->ifa_name, sizeof(mediareq.ifm_name)); iface->type = probeIfType(openSocket(socket), sdl->sdl_type, &mediareq); iface->mtu = getMtu(socket, &req); } @@ -524,7 +525,7 @@ static void getAddressExtraInfo(QNetworkAddressEntry *entry, struct sockaddr *sa return; } - strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + qstrncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); // get flags ifr.ifr_addr = *reinterpret_cast(sa); From 794140fb86b470821e3a298a0ba9c8dbbee202b9 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Sat, 17 Nov 2018 14:58:15 +0100 Subject: [PATCH 22/31] QGraphicsProxyWidget: Don't crash within setWidget() when a child proxy has no assigned widget QGraphicsProxyWidget::setWidget() is checking if the newly assigned widget is already assigned to a child proxy widget without checking if the child has a widget assigned at all which lead to a nullptr reference if it is not the case. Therefore check if the assigned widget is a valid pointer. Fixes: QTBUG-15442 Change-Id: I006877f99895ca01975bdcad071cfcf90bea22ad Reviewed-by: Friedemann Kleint Reviewed-by: Richard Moe Gustavsen --- src/widgets/graphicsview/qgraphicsproxywidget.cpp | 8 ++++---- .../tst_qgraphicsproxywidget.cpp | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/widgets/graphicsview/qgraphicsproxywidget.cpp b/src/widgets/graphicsview/qgraphicsproxywidget.cpp index 177dbc4871..513cf9d361 100644 --- a/src/widgets/graphicsview/qgraphicsproxywidget.cpp +++ b/src/widgets/graphicsview/qgraphicsproxywidget.cpp @@ -607,20 +607,20 @@ void QGraphicsProxyWidgetPrivate::setWidget_helper(QWidget *newWidget, bool auto for (QGraphicsItem *child : childItems) { if (child->d_ptr->isProxyWidget()) { QGraphicsProxyWidget *childProxy = static_cast(child); - QWidget * parent = childProxy->widget(); - while (parent->parentWidget() != 0) { + QWidget *parent = childProxy->widget(); + while (parent && parent->parentWidget()) { if (parent == widget) break; parent = parent->parentWidget(); } if (!childProxy->widget() || parent != widget) continue; - childProxy->setWidget(0); + childProxy->setWidget(nullptr); delete childProxy; } } - widget = 0; + widget = nullptr; #ifndef QT_NO_CURSOR q->unsetCursor(); #endif diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp index 49afc5f369..4a301337ef 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp @@ -140,6 +140,7 @@ private slots: void palettePropagation(); void fontPropagation(); void dontCrashWhenDie(); + void dontCrashNoParent(); void createProxyForChildWidget(); #ifndef QT_NO_CONTEXTMENU void actionsContextMenu(); @@ -2964,6 +2965,20 @@ void tst_QGraphicsProxyWidget::dontCrashWhenDie() qDeleteAll(QApplication::topLevelWidgets()); } +void tst_QGraphicsProxyWidget::dontCrashNoParent() // QTBUG-15442 +{ + QGraphicsProxyWidget *parent(new QGraphicsProxyWidget); + QGraphicsProxyWidget *child(new QGraphicsProxyWidget); + QScopedPointer label0(new QLabel); + QScopedPointer label1(new QLabel); + + child->setParentItem(parent); + // Set the first label as the proxied widget. + parent->setWidget(label0.data()); + // If we attempt to change the proxied widget we get a crash. + parent->setWidget(label1.data()); +} + void tst_QGraphicsProxyWidget::createProxyForChildWidget() { QGraphicsScene scene; From 5f49788e3348406f1399e4e911a765f850f5788f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 16 Nov 2018 18:37:01 +0100 Subject: [PATCH 23/31] macOS: Allow raising and lowering child windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ic598d200e2f774ced489a37c33b7a02767db4402 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoawindow.mm | 42 +++++++++++---------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 4dc3ea4bd6..df1ad82592 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -897,34 +897,36 @@ void QCocoaWindow::raise() qCDebug(lcQpaWindow) << "QCocoaWindow::raise" << window(); // ### handle spaces (see Qt 4 raise_sys in qwidget_mac.mm) - if (!isContentView()) - return; - - if (m_view.window.visible) { - { - // Clean up autoreleased temp objects from orderFront immediately. - // Failure to do so has been observed to cause leaks also beyond any outer - // autorelease pool (for example around a complete QWindow - // construct-show-raise-hide-delete cyle), counter to expected autoreleasepool - // behavior. - QMacAutoReleasePool pool; - [m_view.window orderFront:m_view.window]; - } - static bool raiseProcess = qt_mac_resolveOption(true, "QT_MAC_SET_RAISE_PROCESS"); - if (raiseProcess) { - [NSApp activateIgnoringOtherApps:YES]; + if (isContentView()) { + if (m_view.window.visible) { + { + // Clean up auto-released temp objects from orderFront immediately. + // Failure to do so has been observed to cause leaks also beyond any outer + // autorelease pool (for example around a complete QWindow + // construct-show-raise-hide-delete cycle), counter to expected autoreleasepool + // behavior. + QMacAutoReleasePool pool; + [m_view.window orderFront:m_view.window]; + } + static bool raiseProcess = qt_mac_resolveOption(true, "QT_MAC_SET_RAISE_PROCESS"); + if (raiseProcess) + [NSApp activateIgnoringOtherApps:YES]; } + } else { + [m_view.superview addSubview:m_view positioned:NSWindowAbove relativeTo:nil]; } } void QCocoaWindow::lower() { qCDebug(lcQpaWindow) << "QCocoaWindow::lower" << window(); - if (!isContentView()) - return; - if (m_view.window.visible) - [m_view.window orderBack:m_view.window]; + if (isContentView()) { + if (m_view.window.visible) + [m_view.window orderBack:m_view.window]; + } else { + [m_view.superview addSubview:m_view positioned:NSWindowBelow relativeTo:nil]; + } } bool QCocoaWindow::isExposed() const From 1931aedcf827f837ce81a58a8f8f0e55d8212df6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 16 Nov 2018 18:41:11 +0100 Subject: [PATCH 24/31] macOS: Track changes to our NSView's superview and window properties As a start, we just log the changes, but going forward we can use this to report parent changes to QPA or get rid of old QNSWindows. Change-Id: Id3625fb0b7608d85240f58bdecc70a5892075da3 Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qnsview.mm | 73 +++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 6 deletions(-) diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 03c5001270..7f826942f3 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -68,6 +68,8 @@ // Private interface @interface QT_MANGLE_NAMESPACE(QNSView) () - (BOOL)isTransparentForUserInput; +@property (assign) NSView* previousSuperview; +@property (assign) NSWindow* previousWindow; @end @interface QT_MANGLE_NAMESPACE(QNSView) (Drawing) @@ -153,6 +155,9 @@ self.focusRingType = NSFocusRingTypeNone; self.cursor = nil; + self.previousSuperview = nil; + self.previousWindow = nil; + [self initDrawing]; [self registerDragTypes]; @@ -195,8 +200,40 @@ return description; } +// ----------------------------- Re-parenting --------------------------------- + +- (void)removeFromSuperview +{ + QMacAutoReleasePool pool; + [super removeFromSuperview]; +} + +- (void)viewWillMoveToSuperview:(NSView *)newSuperview +{ + Q_ASSERT(!self.previousSuperview); + self.previousSuperview = self.superview; + + if (newSuperview == self.superview) + qCDebug(lcQpaWindow) << "Re-ordering" << self << "inside" << self.superview; + else + qCDebug(lcQpaWindow) << "Re-parenting" << self << "from" << self.superview << "to" << newSuperview; +} + - (void)viewDidMoveToSuperview { + auto cleanup = qScopeGuard([&] { self.previousSuperview = nil; }); + + if (self.superview == self.previousSuperview) { + qCDebug(lcQpaWindow) << "Done re-ordering" << self << "new index:" + << [self.superview.subviews indexOfObject:self]; + return; + } + + qCDebug(lcQpaWindow) << "Done re-parenting" << self << "into" << self.superview; + + // Note: at this point the view's window property hasn't been updated to match the window + // of the new superview. We have to wait for viewDidMoveToWindow for that to be reflected. + if (!m_platformWindow) return; @@ -210,6 +247,36 @@ } } +- (void)viewWillMoveToWindow:(NSWindow *)newWindow +{ + Q_ASSERT(!self.previousWindow); + self.previousWindow = self.window; + + // This callback is documented to be called also when a view is just moved between + // subviews in the same NSWindow, so we're not necessarily moving between NSWindows. + if (newWindow == self.window) + return; + + qCDebug(lcQpaWindow) << "Moving" << self << "from" << self.window << "to" << newWindow; + + // Note: at this point the superview has already been updated, so we know which view inside + // the new window the view will be a child of. +} + +- (void)viewDidMoveToWindow +{ + auto cleanup = qScopeGuard([&] { self.previousWindow = nil; }); + + // This callback is documented to be called also when a view is just moved between + // subviews in the same NSWindow, so we're not necessarily moving between NSWindows. + if (self.window == self.previousWindow) + return; + + qCDebug(lcQpaWindow) << "Done moving" << self << "to" << self.window; +} + +// ---------------------------------------------------------------------------- + - (QWindow *)topLevelWindow { if (!m_platformWindow) @@ -239,12 +306,6 @@ // viewDidUnhide so no reason to override it here. } -- (void)removeFromSuperview -{ - QMacAutoReleasePool pool; - [super removeFromSuperview]; -} - - (BOOL)isTransparentForUserInput { return m_platformWindow->window() && From 52bd707f0d6a585c2f5da9565834eb91f1d3dbc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 16 Nov 2018 20:37:11 +0100 Subject: [PATCH 25/31] Improve logging of QWindowContainer operations By explicitly identifying the fake window created for the window container. Change-Id: Id67a6e22588d04e68f5ede09bc078bb387c12e0b Reviewed-by: Richard Moe Gustavsen --- src/widgets/kernel/qwindowcontainer.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/widgets/kernel/qwindowcontainer.cpp b/src/widgets/kernel/qwindowcontainer.cpp index 81916bba90..d2680e5280 100644 --- a/src/widgets/kernel/qwindowcontainer.cpp +++ b/src/widgets/kernel/qwindowcontainer.cpp @@ -227,6 +227,12 @@ QWindowContainer::QWindowContainer(QWindow *embeddedWindow, QWidget *parent, Qt: embeddedWindow->setSurfaceType(QSurface::RasterGLSurface); d->window = embeddedWindow; + + QString windowName = d->window->objectName(); + if (windowName.isEmpty()) + windowName = QString::fromUtf8(d->window->metaObject()->className()); + d->fakeParent.setObjectName(windowName + "ContainerFakeParent"); + d->window->setParent(&d->fakeParent); setAcceptDrops(true); From 736dfc3c63f7d7844d11fe4abd6bcfb1befad3cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Sat, 17 Nov 2018 01:26:25 +0100 Subject: [PATCH 26/31] Remove unused inRepaint member of QWidgetPrivate The code that used it was removed in 55fa3c189f889 6 years ago. Change-Id: I76e42f147342feb1bda9bc2c5aa882af62757812 Reviewed-by: Richard Moe Gustavsen --- src/widgets/kernel/qwidget.cpp | 6 +----- src/widgets/kernel/qwidget_p.h | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index da0d530990..e59fbb8963 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -1775,7 +1775,6 @@ void QWidgetPrivate::createTLExtra() x->posIncludesFrame = 0; x->sizeAdjusted = false; x->inTopLevelResize = false; - x->inRepaint = false; x->embedded = 0; x->window = 0; x->shareContext = 0; @@ -11033,11 +11032,8 @@ void QWidgetPrivate::repaint(T r) return; QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData(); - if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) { - tlwExtra->inRepaint = true; + if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) tlwExtra->backingStoreTracker->markDirty(r, q, QWidgetBackingStore::UpdateNow); - tlwExtra->inRepaint = false; - } } /*! diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index c2fc27a9ad..be45c4c868 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -190,7 +190,6 @@ struct QTLWExtra { uint posIncludesFrame : 1; uint sizeAdjusted : 1; uint inTopLevelResize : 1; - uint inRepaint : 1; uint embedded : 1; // *************************** Platform specific values (bit fields first) ********** From bc1678c618342774be285f24c1e2995c0a0e1600 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Thu, 22 Nov 2018 13:22:34 +0100 Subject: [PATCH 27/31] macOS accessibility: fix crash for NSAccessibilityVisibleCharacterRangeAttribute MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VoiceOver or other tools may query this property even when there is no text interface. Make sure not to crash by verifying that the interface is supported. Found while using AccessibilityInspector to verify other changes. Change-Id: If7ee21b7616f091b71e86bab03a871ddbabe9200 Reviewed-by: Jan Arve Sæther --- src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm index 03dc895ffb..a1176da33f 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm @@ -345,8 +345,9 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of return [NSValue valueWithRange: NSMakeRange(0, 0)]; } else if ([attribute isEqualToString:NSAccessibilityVisibleCharacterRangeAttribute]) { // FIXME This is not correct and may impact performance for big texts - return [NSValue valueWithRange: NSMakeRange(0, iface->textInterface()->characterCount())]; - + if (QAccessibleTextInterface *text = iface->textInterface()) + return [NSValue valueWithRange: NSMakeRange(0, text->characterCount())]; + return [NSValue valueWithRange: NSMakeRange(0, iface->text(QAccessible::Name).length())]; } else if ([attribute isEqualToString:NSAccessibilityInsertionPointLineNumberAttribute]) { if (QAccessibleTextInterface *text = iface->textInterface()) { int line = 0; // true for all single line edits From 76dafc9b94ebe08577eee1d929fe7fa0330189ed Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 21 Nov 2018 09:24:18 +0100 Subject: [PATCH 28/31] Add translator's comment to the copyright note State the policy that so far only exists in the localization wiki and is currently not followed by all translators. Task-number: QTBUG-57697 Change-Id: I2aa9f1bbd244b53e48e59f625520a7f86d2df347 Reviewed-by: Vitaly Fanaskov Reviewed-by: Lars Knoll --- src/widgets/dialogs/qmessagebox.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/widgets/dialogs/qmessagebox.cpp b/src/widgets/dialogs/qmessagebox.cpp index 32190151bc..ffbbe82856 100644 --- a/src/widgets/dialogs/qmessagebox.cpp +++ b/src/widgets/dialogs/qmessagebox.cpp @@ -1832,8 +1832,9 @@ void QMessageBox::aboutQt(QWidget *parent, const QString &title) "

About Qt

" "

This program uses Qt version %1.

" ).arg(QLatin1String(QT_VERSION_STR)); - QString translatedTextAboutQtText; - translatedTextAboutQtText = QMessageBox::tr( + //: Leave this text untranslated or include a verbatim copy of it below + //: and note that it is the authoritative version in case of doubt. + const QString translatedTextAboutQtText = QMessageBox::tr( "

Qt is a C++ toolkit for cross-platform application " "development.

" "

Qt provides single-source portability across all major desktop " From 36f3eeaf3ec12126956d151a026379ab0385ab72 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Thu, 22 Nov 2018 18:32:50 +0100 Subject: [PATCH 29/31] Fix build errors in OpenSSL 1.1 backend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SSL_CTX_set_ciphers is new in 1.1.1. Task-number: QTBUG-71983 Change-Id: If0ae9f95dcc867c62ed0d3a6a60c22c7f5e1cc9f Reviewed-by: Mårten Nordheim --- src/network/ssl/qsslsocket_openssl_symbols.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index 781b3d6640..fd58e9548e 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -161,7 +161,9 @@ DEFINEFUNC(void, OPENSSL_sk_free, OPENSSL_STACK *a, a, return, DUMMYARG) DEFINEFUNC2(void *, OPENSSL_sk_value, OPENSSL_STACK *a, a, int b, b, return nullptr, return) DEFINEFUNC(int, SSL_session_reused, SSL *a, a, return 0, return) DEFINEFUNC2(unsigned long, SSL_CTX_set_options, SSL_CTX *ctx, ctx, unsigned long op, op, return 0, return) +#ifdef TLS1_3_VERSION DEFINEFUNC2(int, SSL_CTX_set_ciphersuites, SSL_CTX *ctx, ctx, const char *str, str, return 0, return) +#endif DEFINEFUNC3(size_t, SSL_get_client_random, SSL *a, a, unsigned char *out, out, size_t outlen, outlen, return 0, return) DEFINEFUNC3(size_t, SSL_SESSION_get_master_key, const SSL_SESSION *ses, ses, unsigned char *out, out, size_t outlen, outlen, return 0, return) DEFINEFUNC6(int, CRYPTO_get_ex_new_index, int class_index, class_index, long argl, argl, void *argp, argp, CRYPTO_EX_new *new_func, new_func, CRYPTO_EX_dup *dup_func, dup_func, CRYPTO_EX_free *free_func, free_func, return -1, return) From 70d131af33c8b411f430d0699b4294b5976db8e3 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 23 Nov 2018 13:23:28 +0100 Subject: [PATCH 30/31] Windows: Fix embedded application not getting focus after clicking outside Amend the check introduced by bde6a049494f40cd71004d6926899f115af0c3e6 to not apply to embedded windows and plugin applications. Fixes: QTBUG-71991 Task-number: QTBUG-7081 Change-Id: I80b3dc0fa20ee3447a4bc4bbb41e66d4d90ab726 Reviewed-by: Shawn Rutledge --- src/widgets/kernel/qwidget.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index e59fbb8963..bcfae46155 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -6592,20 +6592,25 @@ QWidget *QWidgetPrivate::deepestFocusProxy() const return focusProxy; } +static inline bool isEmbedded(const QWindow *w) +{ + const auto platformWindow = w->handle(); + return platformWindow && platformWindow->isEmbedded(); +} + void QWidgetPrivate::setFocus_sys() { Q_Q(QWidget); // Embedded native widget may have taken the focus; get it back to toplevel // if that is the case (QTBUG-25852) - const QWidget *topLevel = q->window(); - // Do not activate in case the popup menu opens another application (QTBUG-70810). - if (QGuiApplication::applicationState() == Qt::ApplicationActive - && topLevel->windowType() != Qt::Popup) { - if (QWindow *nativeWindow = q->window()->windowHandle()) { - if (nativeWindow != QGuiApplication::focusWindow() - && q->testAttribute(Qt::WA_WState_Created)) { - nativeWindow->requestActivate(); - } + // Do not activate in case the popup menu opens another application (QTBUG-70810) + // unless the application is embedded (QTBUG-71991). + if (QWindow *nativeWindow = q->testAttribute(Qt::WA_WState_Created) ? q->window()->windowHandle() : nullptr) { + if (nativeWindow->type() != Qt::Popup && nativeWindow != QGuiApplication::focusWindow() + && (QGuiApplication::applicationState() == Qt::ApplicationActive + || QCoreApplication::testAttribute(Qt::AA_PluginApplication) + || isEmbedded(nativeWindow))) { + nativeWindow->requestActivate(); } } } From ba13c6c08f30a4c2f188f69deeaf4ca6a020d7a1 Mon Sep 17 00:00:00 2001 From: Vitaly Fanaskov Date: Thu, 22 Nov 2018 14:39:51 +0100 Subject: [PATCH 31/31] Fix calculation of text margin if line edit contains side widgets The previous implementation leads to infinite chain of showing/hidden line edit under circumstances described in QTBUG-54676. We basically got the situation when size hint were calculated differently depending on the line edit visibility state. In this case toolbar layout have to show/hide extension button and line edit a lot of times and can never leave this "loop" (please note, that the chain is much more complicated in reality): Resize toolbar -> Set layout geometry -> Size is OK to display line edit -> Set layout geometry -> Hide extension button -> Set layout geometry (wrong size is calculated here, so "run out of space") -> Hide line edit -> Set layout geometry -> Show extension button -> Set layout geometry - > Size is OK to display line edit ... And we're in the "loop" Clear button is hidden if there is no text in a line edit. In the previous implementation, the button was always visible, only opacity was changing in order to "hide" the button. It resulted to incorrect size hints (regular and minimum). In the current implementation the button is really hidden/shown, and size hints calculated correctly. Also updated unit test for line edit. Remove code duplication in functions for calculation text margin Fixes: QTBUG-54676 Change-Id: I4549c9ea98e10b750ba855a07037f6392276358b Reviewed-by: Shawn Rutledge --- src/widgets/widgets/qlineedit.cpp | 5 +- src/widgets/widgets/qlineedit_p.cpp | 98 +++++++++++++------ src/widgets/widgets/qlineedit_p.h | 15 ++- .../widgets/qlineedit/tst_qlineedit.cpp | 3 +- .../widgets/widgets/qtoolbar/tst_qtoolbar.cpp | 79 +++++++++++++++ 5 files changed, 169 insertions(+), 31 deletions(-) diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp index 242a4405ca..2ae2e16c89 100644 --- a/src/widgets/widgets/qlineedit.cpp +++ b/src/widgets/widgets/qlineedit.cpp @@ -488,7 +488,10 @@ void QLineEdit::setClearButtonEnabled(bool enable) QAction *clearAction = new QAction(d->clearButtonIcon(), QString(), this); clearAction->setEnabled(!isReadOnly()); clearAction->setObjectName(QLatin1String(clearButtonActionNameC)); - d->addAction(clearAction, 0, QLineEdit::TrailingPosition, QLineEditPrivate::SideWidgetClearButton | QLineEditPrivate::SideWidgetFadeInWithText); + + int flags = QLineEditPrivate::SideWidgetClearButton | QLineEditPrivate::SideWidgetFadeInWithText; + auto widgetAction = d->addAction(clearAction, nullptr, QLineEdit::TrailingPosition, flags); + widgetAction->setVisible(!text().isEmpty()); } else { QAction *clearAction = findChild(QLatin1String(clearButtonActionNameC)); Q_ASSERT(clearAction); diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp index df8d534afa..6dcb2dd693 100644 --- a/src/widgets/widgets/qlineedit_p.cpp +++ b/src/widgets/widgets/qlineedit_p.cpp @@ -392,9 +392,47 @@ void QLineEditIconButton::setOpacity(qreal value) } #if QT_CONFIG(animation) +bool QLineEditIconButton::shouldHideWithText() const +{ + return m_hideWithText; +} + +void QLineEditIconButton::setHideWithText(bool hide) +{ + m_hideWithText = hide; +} + +void QLineEditIconButton::onAnimationFinished() +{ + if (shouldHideWithText() && isVisible() && !m_wasHidden) { + hide(); + + // Invalidate previous geometry to take into account new size of side widgets + if (auto le = lineEditPrivate()) + le->updateGeometry_helper(true); + } +} + +void QLineEditIconButton::animateShow(bool visible) +{ + m_wasHidden = visible; + + if (shouldHideWithText() && !isVisible()) { + show(); + + // Invalidate previous geometry to take into account new size of side widgets + if (auto le = lineEditPrivate()) + le->updateGeometry_helper(true); + } + + startOpacityAnimation(visible ? 1.0 : 0.0); +} + void QLineEditIconButton::startOpacityAnimation(qreal endValue) { QPropertyAnimation *animation = new QPropertyAnimation(this, QByteArrayLiteral("opacity")); + connect(animation, &QPropertyAnimation::finished, this, &QLineEditIconButton::onAnimationFinished); + animation->setDuration(160); animation->setEndValue(endValue); animation->start(QAbstractAnimation::DeleteWhenStopped); @@ -409,6 +447,16 @@ void QLineEditIconButton::updateCursor() } #endif // QT_CONFIG(toolbutton) +#if QT_CONFIG(animation) && QT_CONFIG(toolbutton) +static void displayWidgets(const QLineEditPrivate::SideWidgetEntryList &widgets, bool display) +{ + for (const auto &e : widgets) { + if (e.flags & QLineEditPrivate::SideWidgetFadeInWithText) + static_cast(e.widget)->animateShow(display); + } +} +#endif + void QLineEditPrivate::_q_textChanged(const QString &text) { if (hasSideWidgets()) { @@ -416,15 +464,9 @@ void QLineEditPrivate::_q_textChanged(const QString &text) if (!newTextSize || !lastTextSize) { lastTextSize = newTextSize; #if QT_CONFIG(animation) && QT_CONFIG(toolbutton) - const bool fadeIn = newTextSize > 0; - for (const SideWidgetEntry &e : leadingSideWidgets) { - if (e.flags & SideWidgetFadeInWithText) - static_cast(e.widget)->animateShow(fadeIn); - } - for (const SideWidgetEntry &e : trailingSideWidgets) { - if (e.flags & SideWidgetFadeInWithText) - static_cast(e.widget)->animateShow(fadeIn); - } + const bool display = newTextSize > 0; + displayWidgets(leadingSideWidgets, display); + displayWidgets(trailingSideWidgets, display); #endif } } @@ -541,8 +583,15 @@ QWidget *QLineEditPrivate::addAction(QAction *newAction, QAction *before, QLineE QLineEditIconButton *toolButton = new QLineEditIconButton(q); toolButton->setIcon(newAction->icon()); toolButton->setOpacity(lastTextSize > 0 || !(flags & SideWidgetFadeInWithText) ? 1 : 0); - if (flags & SideWidgetClearButton) + if (flags & SideWidgetClearButton) { QObject::connect(toolButton, SIGNAL(clicked()), q, SLOT(_q_clearButtonClicked())); + +#if QT_CONFIG(animation) + // The clear button is handled only by this widget. The button should be really + // shown/hidden in order to calculate size hints correctly. + toolButton->setHideWithText(true); +#endif + } toolButton->setDefaultAction(newAction); w = toolButton; #else @@ -606,33 +655,26 @@ void QLineEditPrivate::removeAction(QAction *action) #endif // QT_CONFIG(action) } -static bool isSideWidgetVisible(const QLineEditPrivate::SideWidgetEntry &e) +static int effectiveTextMargin(int defaultMargin, const QLineEditPrivate::SideWidgetEntryList &widgets, + const QLineEditPrivate::SideWidgetParameters ¶meters) { - return e.widget->isVisible(); + if (widgets.empty()) + return defaultMargin; + + return defaultMargin + (parameters.margin + parameters.widgetWidth) * + int(std::count_if(widgets.begin(), widgets.end(), + [](const QLineEditPrivate::SideWidgetEntry &e) { + return e.widget->isVisibleTo(e.widget->parentWidget()); })); } int QLineEditPrivate::effectiveLeftTextMargin() const { - int result = leftTextMargin; - if (!leftSideWidgetList().empty()) { - const SideWidgetParameters p = sideWidgetParameters(); - result += (p.margin + p.widgetWidth) - * int(std::count_if(leftSideWidgetList().begin(), leftSideWidgetList().end(), - isSideWidgetVisible)); - } - return result; + return effectiveTextMargin(leftTextMargin, leftSideWidgetList(), sideWidgetParameters()); } int QLineEditPrivate::effectiveRightTextMargin() const { - int result = rightTextMargin; - if (!rightSideWidgetList().empty()) { - const SideWidgetParameters p = sideWidgetParameters(); - result += (p.margin + p.widgetWidth) - * int(std::count_if(rightSideWidgetList().begin(), rightSideWidgetList().end(), - isSideWidgetVisible)); - } - return result; + return effectiveTextMargin(rightTextMargin, rightSideWidgetList(), sideWidgetParameters()); } diff --git a/src/widgets/widgets/qlineedit_p.h b/src/widgets/widgets/qlineedit_p.h index 7cd91dfc29..12a2f1ddfd 100644 --- a/src/widgets/widgets/qlineedit_p.h +++ b/src/widgets/widgets/qlineedit_p.h @@ -90,7 +90,10 @@ public: qreal opacity() const { return m_opacity; } void setOpacity(qreal value); #if QT_CONFIG(animation) - void animateShow(bool visible) { startOpacityAnimation(visible ? 1.0 : 0.0); } + void animateShow(bool visible); + + bool shouldHideWithText() const; + void setHideWithText(bool hide); #endif protected: @@ -100,6 +103,10 @@ protected: private slots: void updateCursor(); +#if QT_CONFIG(animation) + void onAnimationFinished(); +#endif + private: #if QT_CONFIG(animation) void startOpacityAnimation(qreal endValue); @@ -107,6 +114,12 @@ private: QLineEditPrivate *lineEditPrivate() const; qreal m_opacity; + +#if QT_CONFIG(animation) + bool m_hideWithText = false; + bool m_wasHidden = false; +#endif + }; #endif // QT_CONFIG(toolbutton) diff --git a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp index 448e2030bc..95799905de 100644 --- a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp +++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp @@ -4451,10 +4451,11 @@ void tst_QLineEdit::clearButtonVisibleAfterSettingText_QTBUG_45518() QTRY_VERIFY(clearButton->opacity() > 0); QTRY_COMPARE(clearButton->cursor().shape(), Qt::ArrowCursor); - QTest::mouseClick(clearButton, Qt::LeftButton, 0, clearButton->rect().center()); + QTest::mouseClick(clearButton, Qt::LeftButton, nullptr, clearButton->rect().center()); QTRY_COMPARE(edit.text(), QString()); QTRY_COMPARE(clearButton->opacity(), qreal(0)); + QVERIFY(clearButton->isHidden()); QTRY_COMPARE(clearButton->cursor().shape(), clearButton->parentWidget()->cursor().shape()); edit.setClearButtonEnabled(false); diff --git a/tests/auto/widgets/widgets/qtoolbar/tst_qtoolbar.cpp b/tests/auto/widgets/widgets/qtoolbar/tst_qtoolbar.cpp index 301801ed2e..d6c165642e 100644 --- a/tests/auto/widgets/widgets/qtoolbar/tst_qtoolbar.cpp +++ b/tests/auto/widgets/widgets/qtoolbar/tst_qtoolbar.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include QT_FORWARD_DECLARE_CLASS(QAction) @@ -80,6 +81,8 @@ private slots: void task191727_layout(); void task197996_visibility(); + + void extraCpuConsumption(); // QTBUG-54676 }; @@ -1098,5 +1101,81 @@ void tst_QToolBar::task197996_visibility() QTRY_VERIFY(toolBar->widgetForAction(pAction)->isVisible()); } +class ShowHideEventCounter : public QObject +{ +public: + using QObject::QObject; + + bool eventFilter(QObject *watched, QEvent *event) override + { + if (qobject_cast(watched) && !event->spontaneous()) { + if (event->type() == QEvent::Show) + ++m_showEventsCount; + + if (event->type() == QEvent::Hide) + ++m_hideEventsCount; + } + + return QObject::eventFilter(watched, event); + } + + uint showEventsCount() const { return m_showEventsCount; } + uint hideEventsCount() const { return m_hideEventsCount; } + +private: + uint m_showEventsCount = 0; + uint m_hideEventsCount = 0; +}; + +void tst_QToolBar::extraCpuConsumption() +{ + QMainWindow mainWindow; + + auto tb = new QToolBar(&mainWindow); + tb->setMovable(false); + + auto extensions = tb->findChildren(); + QVERIFY(!extensions.isEmpty()); + + auto extensionButton = extensions.at(0); + QVERIFY(extensionButton); + + tb->addWidget(new QLabel("Lorem ipsum dolor sit amet")); + + auto le = new QLineEdit; + le->setClearButtonEnabled(true); + le->setText("Lorem ipsum"); + tb->addWidget(le); + + mainWindow.addToolBar(tb); + mainWindow.show(); + QVERIFY(QTest::qWaitForWindowActive(&mainWindow)); + + auto eventCounter = new ShowHideEventCounter(&mainWindow); + le->installEventFilter(eventCounter); + + auto defaultSize = mainWindow.size(); + + // Line edit should be hidden now and extension button should be displayed + for (double p = 0.7; extensionButton->isHidden() || qFuzzyCompare(p, 0.); p -= 0.01) { + mainWindow.resize(int(defaultSize.width() * p), defaultSize.height()); + } + QVERIFY(!extensionButton->isHidden()); + + // Line edit should be visible, but smaller + for (double p = 0.75; !extensionButton->isHidden() || qFuzzyCompare(p, 1.); p += 0.01) { + mainWindow.resize(int(defaultSize.width() * p), defaultSize.height()); + } + QVERIFY(extensionButton->isHidden()); + + // Dispatch all pending events + qApp->sendPostedEvents(); + qApp->processEvents(); + + QCOMPARE(eventCounter->showEventsCount(), eventCounter->hideEventsCount()); + QCOMPARE(eventCounter->showEventsCount(), uint(1)); + QCOMPARE(eventCounter->hideEventsCount(), uint(1)); +} + QTEST_MAIN(tst_QToolBar) #include "tst_qtoolbar.moc"