Merge remote-tracking branch 'origin/5.13' into dev

Conflicts:
	src/gui/util/qshaderformat.cpp
	src/gui/util/qshaderformat_p.h
	src/widgets/graphicsview/qgraphicsitem_p.h

Change-Id: Idafd88eb9a0a15b4af29f6143d009c1ec8ceecca
This commit is contained in:
Liang Qi 2019-04-24 09:52:30 +02:00
commit dc37318684
87 changed files with 1258 additions and 448 deletions

View File

@ -1111,7 +1111,7 @@ foreach my $lib (@modules_to_sync) {
elsif (!$shadow) {
$pri_install_pfiles.= "$pri_install_iheader ";;
}
$pri_injections .= fixPaths($iheader, $out_basedir)
$pri_injections .= fixPaths($iheader, $build_basedir)
.":".($no_stamp ? "^" : "").fixPaths($oheader, "$out_basedir/include/$lib")
.$injection." " if ($shadow);
}

View File

@ -139,8 +139,8 @@ Build options:
-coverage {trace-pc-guard}
Add code coverage instrumentation (Clang only)
-c++std <edition> .... Select C++ standard <edition> [c++1z/c++14/c++11]
(Not supported with MSVC)
-c++std <edition> .... Select C++ standard <edition> [c++2a/c++17/c++14/c++11]
(Not supported with MSVC 2015)
-sse2 ................ Use SSE2 instructions [auto]
-sse3/-ssse3/-sse4.1/-sse4.2/-avx/-avx2/-avx512

View File

@ -319,7 +319,7 @@
}
},
"c++1z": {
"label": "C++1z support",
"label": "C++17 support",
"type": "compile",
"test": {
"head": [
@ -339,6 +339,20 @@
"qmake": "CONFIG += c++11 c++14 c++1z"
}
},
"c++2a": {
"label": "C++2a support",
"type": "compile",
"test": {
"head": [
"#if __cplusplus > 201703L",
"// Compiler claims to support experimental C++2a, trust it",
"#else",
"# error __cplusplus must be > 201703L (the value for C++17)",
"#endif"
],
"qmake": "CONFIG += c++11 c++14 c++1z c++2a"
}
},
"precompile_header": {
"label": "precompiled header support",
"type": "compile",
@ -907,10 +921,16 @@
"output": [ "publicFeature", "publicQtConfig" ]
},
"c++1z": {
"label": "C++1z",
"label": "C++17",
"condition": "features.c++14 && tests.c++1z",
"output": [ "publicFeature", "publicQtConfig" ]
},
"c++2a": {
"label": "C++2a",
"autoDetect": false,
"condition": "features.c++1z && tests.c++2a",
"output": [ "publicFeature", "publicQtConfig" ]
},
"c89": {
"label": "C89"
},
@ -1413,7 +1433,7 @@ Configure with '-qreal float' to create a build that is binary-compatible with 5
{
"message": "Using C++ standard",
"type": "firstAvailableFeature",
"args": "c++1z c++14 c++11"
"args": "c++2a c++1z c++14 c++11"
},
{
"type": "feature",

View File

@ -14,21 +14,26 @@ defineTest(qtConfCommandline_qmakeArgs) {
}
defineTest(qtConfCommandline_cxxstd) {
msvc: \
qtConfAddError("Command line option -c++std is not supported with MSVC compilers.")
arg = $${1}
val = $${2}
isEmpty(val): val = $$qtConfGetNextCommandlineArg()
!contains(val, "^-.*"):!isEmpty(val) {
contains(val, "(c\+\+)?11") {
qtConfCommandlineSetInput("c++14", "no")
qtConfCommandlineSetInput("c++1z", "no")
qtConfCommandlineSetInput("c++2a", "no")
} else: contains(val, "(c\+\+)?(14|1y)") {
qtConfCommandlineSetInput("c++14", "yes")
qtConfCommandlineSetInput("c++1z", "no")
} else: contains(val, "(c\+\+)?(1z)") {
qtConfCommandlineSetInput("c++2a", "no")
} else: contains(val, "(c\+\+)?(17|1z)") {
qtConfCommandlineSetInput("c++14", "yes")
qtConfCommandlineSetInput("c++1z", "yes")
qtConfCommandlineSetInput("c++2a", "no")
} else: contains(val, "(c\+\+)?(2a)") {
qtConfCommandlineSetInput("c++14", "yes")
qtConfCommandlineSetInput("c++1z", "yes")
qtConfCommandlineSetInput("c++2a", "yes")
} else {
qtConfAddError("Invalid argument $$val to command line parameter $$arg")
}

82
dist/changes-5.12.3 vendored Normal file
View File

@ -0,0 +1,82 @@
Qt 5.12.3 is a bug-fix release. It maintains both forward and backward
compatibility (source and binary) with Qt 5.12.0 through 5.12.2.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
https://doc.qt.io/qt-5/index.html
The Qt version 5.12 series is binary compatible with the 5.11.x series.
Applications compiled for 5.11 will continue to run with 5.12.
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* Third-Party Code *
****************************************************************************
- Changed classification of the wintab license from Public Domain to
Custom.
****************************************************************************
* QtCore *
****************************************************************************
- Event system:
* [QTBUG-72438] Fixed a possible race condition on Windows that would
cause an interrupted event loop to be stuck until more events were
posted.
- Logging system:
* [QTBUG-74359] Fixed the compilation of qCDebug("", ...) when debug
output was disabled.
- QCollator:
* [QTBUG-74209] Fixed a bug that caused QCompare to incorrect return a
sorting order on Windows if the Win32 API failed.
- QDateTime / QTimeZone:
* [QTBUG-74614] Fixed handling of timezones that contain no DST
transitions.
- QProcess:
* [QTBUG-73778] Fixed a crash when calling closeWriteChannel() on Windows.
****************************************************************************
* QtSql *
****************************************************************************
- When cross-compiling pg_config, mysql_config are not looked up in PATH
anymore. Pass -psql_config path/to/pg_config or -mysql_config
path/to/mysql_config to explicitly enable PSQL or MySQL in this setup.
****************************************************************************
* Platform Specific Changes *
****************************************************************************
- Android:
* Text fields with ImhNoPredictiveText set are no longer working around
keyboards that disregard this setting. To enforce the workaround, the
environment variable
QT_ANDROID_ENABLE_WORKAROUND_TO_DISABLE_PREDICTIVE_TEXT should be set.
* [QTBUG-74029] Added entries in the AndroidManifest.xml for specific
portrait and landscape splash screens. If one is present for the current
orientation, it will be preferred over the generic one.
- Linux:
* [QTBUG-74526] Changed the way we use the statx() system call to use a
fallback mechanism provided by the GNU C library. This should allow Qt
applications that are compiled with glibc >= 2.28 to run even on kernels
older than 4.11.
- Windows:
* [QTBUG-74062] Fixed QToolTip pop-ups and QComboBox animation pop-ups
being off by a few pixels on Windows 10.

View File

@ -35,9 +35,11 @@ QMAKE_CXXFLAGS_DISABLE_LTCG = $$QMAKE_CFLAGS_DISABLE_LTCG
QMAKE_CXXFLAGS_CXX11 = -std=c++11
QMAKE_CXXFLAGS_CXX14 = -std=c++1y
QMAKE_CXXFLAGS_CXX1Z = -std=c++1z
QMAKE_CXXFLAGS_CXX2A = -std=c++2a
QMAKE_CXXFLAGS_GNUCXX11 = -std=gnu++11
QMAKE_CXXFLAGS_GNUCXX14 = -std=gnu++1y
QMAKE_CXXFLAGS_GNUCXX1Z = -std=gnu++1z
QMAKE_CXXFLAGS_GNUCXX2A = -std=gnu++2a
QMAKE_LFLAGS_CXX11 =
QMAKE_LFLAGS_CXX14 =

View File

@ -32,9 +32,11 @@ QMAKE_CFLAGS_GNUC11 = -std=gnu11
QMAKE_CXXFLAGS_CXX11 = -std=c++11
QMAKE_CXXFLAGS_CXX14 = -std=c++1y
QMAKE_CXXFLAGS_CXX1Z = -std=c++1z
QMAKE_CXXFLAGS_CXX2A = -std=c++2a
QMAKE_CXXFLAGS_GNUCXX11 = -std=gnu++11
QMAKE_CXXFLAGS_GNUCXX14 = -std=gnu++1y
QMAKE_CXXFLAGS_GNUCXX1Z = -std=gnu++1z
QMAKE_CXXFLAGS_GNUCXX2A = -std=gnu++2a
QMAKE_LFLAGS_CXX11 =
QMAKE_LFLAGS_CXX14 =
QMAKE_LFLAGS_CXX1Z =

View File

@ -116,6 +116,8 @@ greaterThan(QMAKE_MSC_VER, 1910) {
greaterThan(QMAKE_MSC_VER, 1919) {
# Visual Studio 2019 (16.0) / Visual C++ 19.20 and up
MSVC_VER = 16.0
QMAKE_CXXFLAGS_CXX2A = -std:c++latest
}
!isEmpty(COMPAT_MKSPEC):!$$COMPAT_MKSPEC: CONFIG += $$COMPAT_MKSPEC

View File

@ -26,20 +26,29 @@ contains(CMAKE_INSTALL_LIBS_DIR, ^(/usr)?/lib(64)?.*): CMAKE_USR_MOVE_WORKAROUND
CMAKE_OUT_DIR = $$MODULE_BASE_OUTDIR/lib/cmake
# Core, Network, an external module named Foo
CMAKE_MODULE_NAME = $$cmakeModuleName($${MODULE})
# QtCore, QtNetwork, still Foo
CMAKE_INCLUDE_NAME = $$eval(QT.$${MODULE}.name)
# TARGET here is the one changed at the end of qt_module.prf,
# which already contains the Qt5 prefix and QT_LIBINFIX suffix :
# Qt5Core_suffix, Qt5Network_suffix, Foo_suffix
# (or QtCore_suffix, Foo_suffix on macos with -framework)
CMAKE_QT_STEM = $${TARGET}
!generated_privates {
isEmpty(SYNCQT.INJECTED_PRIVATE_HEADER_FILES):isEmpty(SYNCQT.PRIVATE_HEADER_FILES): \
CMAKE_NO_PRIVATE_INCLUDES = true
}
split_incpath {
CMAKE_ADD_SOURCE_INCLUDE_DIRS = true
CMAKE_SOURCE_INCLUDES = \
$$cmakeTargetPaths($$QT_MODULE_INCLUDE_BASE $$QT_MODULE_INCLUDE_BASE/Qt$${CMAKE_MODULE_NAME})
$$cmakeTargetPaths($$QT_MODULE_INCLUDE_BASE $$QT_MODULE_INCLUDE_BASE/$${CMAKE_INCLUDE_NAME})
CMAKE_SOURCE_PRIVATE_INCLUDES = \
$$cmakeTargetPaths($$QT_MODULE_INCLUDE_BASE/Qt$${CMAKE_MODULE_NAME}/$$eval(QT.$${MODULE}.VERSION) \
$$QT_MODULE_INCLUDE_BASE/Qt$${CMAKE_MODULE_NAME}/$$eval(QT.$${MODULE}.VERSION)/Qt$${CMAKE_MODULE_NAME})
$$cmakeTargetPaths($$QT_MODULE_INCLUDE_BASE/$${CMAKE_INCLUDE_NAME}/$$eval(QT.$${MODULE}.VERSION) \
$$QT_MODULE_INCLUDE_BASE/$${CMAKE_INCLUDE_NAME}/$$eval(QT.$${MODULE}.VERSION)/$${CMAKE_INCLUDE_NAME})
cmake_extra_source_includes.input = $$PWD/data/cmake/ExtraSourceIncludes.cmake.in
cmake_extra_source_includes.output = $$CMAKE_OUT_DIR/Qt5$${CMAKE_MODULE_NAME}/ExtraSourceIncludes.cmake
@ -200,10 +209,6 @@ CMAKE_QT5_MODULE_DEPS = $$join(lib_deps, ";")
CMAKE_INTERFACE_MODULE_DEPS = $$join(aux_mod_deps, ";")
CMAKE_INTERFACE_QT5_MODULE_DEPS = $$join(aux_lib_deps, ";")
# TARGET here is the one changed at the end of qt_module.prf,
# which already contains the Qt5 prefix and QT_LIBINFIX suffix
CMAKE_QT_STEM = $${TARGET}
mac {
!isEmpty(CMAKE_STATIC_TYPE) {
CMAKE_LIB_FILE_LOCATION_DEBUG = lib$${CMAKE_QT_STEM}_debug.a
@ -213,8 +218,8 @@ mac {
CMAKE_PRL_FILE_LOCATION_RELEASE = lib$${CMAKE_QT_STEM}.prl
} else {
qt_framework {
CMAKE_LIB_FILE_LOCATION_DEBUG = Qt$${CMAKE_MODULE_NAME}$${QT_LIBINFIX}.framework/Qt$${CMAKE_MODULE_NAME}$${QT_LIBINFIX}
CMAKE_LIB_FILE_LOCATION_RELEASE = Qt$${CMAKE_MODULE_NAME}$${QT_LIBINFIX}.framework/Qt$${CMAKE_MODULE_NAME}$${QT_LIBINFIX}
CMAKE_LIB_FILE_LOCATION_DEBUG = $${CMAKE_QT_STEM}.framework/$${CMAKE_QT_STEM}
CMAKE_LIB_FILE_LOCATION_RELEASE = $${CMAKE_QT_STEM}.framework/$${CMAKE_QT_STEM}
CMAKE_BUILD_IS_FRAMEWORK = "true"
} else {
CMAKE_LIB_FILE_LOCATION_DEBUG = lib$${CMAKE_QT_STEM}_debug.$$eval(QT.$${MODULE}.VERSION).dylib

View File

@ -157,13 +157,13 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
!!IF !no_module_headers
!!IF !isEmpty(CMAKE_BUILD_IS_FRAMEWORK)
set(_Qt5$${CMAKE_MODULE_NAME}_OWN_INCLUDE_DIRS
\"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}Qt$${CMAKE_MODULE_NAME}.framework\"
\"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}Qt$${CMAKE_MODULE_NAME}.framework/Headers\"
\"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}$${CMAKE_QT_STEM}.framework\"
\"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}$${CMAKE_QT_STEM}.framework/Headers\"
)
!!IF isEmpty(CMAKE_NO_PRIVATE_INCLUDES)
set(Qt5$${CMAKE_MODULE_NAME}_PRIVATE_INCLUDE_DIRS
\"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}Qt$${CMAKE_MODULE_NAME}.framework/Versions/$$section(VERSION, ., 0, 0)/Headers/$$VERSION/\"
\"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}Qt$${CMAKE_MODULE_NAME}.framework/Versions/$$section(VERSION, ., 0, 0)/Headers/$$VERSION/$${MODULE_INCNAME}\"
\"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}$${CMAKE_QT_STEM}.framework/Versions/$$section(VERSION, ., 0, 0)/Headers/$$VERSION/\"
\"${_qt5$${CMAKE_MODULE_NAME}_install_prefix}/$${CMAKE_LIB_DIR}$${CMAKE_QT_STEM}.framework/Versions/$$section(VERSION, ., 0, 0)/Headers/$$VERSION/$${MODULE_INCNAME}\"
)
!!ELSE
set(Qt5$${CMAKE_MODULE_NAME}_PRIVATE_INCLUDE_DIRS \"\")
@ -180,7 +180,7 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
set(Qt5$${CMAKE_MODULE_NAME}_PRIVATE_INCLUDE_DIRS \"\")
!!ENDIF
!!ELSE
set(_Qt5$${CMAKE_MODULE_NAME}_OWN_INCLUDE_DIRS \"$$CMAKE_INCLUDE_DIR\" \"$${CMAKE_INCLUDE_DIR}Qt$${CMAKE_MODULE_NAME}\")
set(_Qt5$${CMAKE_MODULE_NAME}_OWN_INCLUDE_DIRS \"$$CMAKE_INCLUDE_DIR\" \"$${CMAKE_INCLUDE_DIR}$${CMAKE_INCLUDE_NAME}\")
!!IF isEmpty(CMAKE_NO_PRIVATE_INCLUDES)
set(Qt5$${CMAKE_MODULE_NAME}_PRIVATE_INCLUDE_DIRS
\"$${CMAKE_INCLUDE_DIR}$${MODULE_INCNAME}/$$VERSION\"

View File

@ -121,15 +121,16 @@ breakpad {
c++17: CONFIG += c++1z
!c++11:!c++14:!c++1z {
!c++11:!c++14:!c++1z:!c++2a {
# Qt requires C++11 since 5.7, check if we need to force a compiler option
QT_COMPILER_STDCXX_no_L = $$replace(QT_COMPILER_STDCXX, "L$", "")
!greaterThan(QT_COMPILER_STDCXX_no_L, 199711): CONFIG += c++11
}
c++11|c++14|c++1z {
c++11|c++14|c++1z|c++2a {
# Disable special compiler flags for host builds
!host_build|!cross_compile {
c++1z: cxxstd = CXX1Z
c++2a: cxxstd = CXX2A
else: c++1z: cxxstd = CXX1Z
else: c++14: cxxstd = CXX14
else: cxxstd = CXX11
} else {

View File

@ -145,12 +145,14 @@ import_plugins:qtConfig(static) {
# the plugin path. Unknown plugins must rely on the default link path.
plug_type = $$eval(QT_PLUGIN.$${plug}.TYPE)
!isEmpty(plug_type) {
plug_name = $$QMAKE_PREFIX_STATICLIB$${plug}$$qtPlatformTargetSuffix().$$QMAKE_EXTENSION_STATICLIB
plug_path = $$eval(QT_PLUGIN.$${plug}.PATH)
isEmpty(plug_path): \
plug_path = $$[QT_INSTALL_PLUGINS/get]
LIBS += -L$$plug_path/$$plug_type
LIBS += $$plug_path/$$plug_type/$$plug_name
} else {
LIBS += -l$${plug}$$qtPlatformTargetSuffix()
}
LIBS += -l$${plug}$$qtPlatformTargetSuffix()
}
}
@ -195,8 +197,6 @@ for(ever) {
qtProcessModuleFlags(DEFINES, QT.$${QTLIB}.DEFINES)
MODULE_INCLUDES -= $$QMAKE_DEFAULT_INCDIRS
MODULE_LIBS_ADD = $$MODULE_LIBS
MODULE_LIBS_ADD -= $$QMAKE_DEFAULT_LIBDIRS
# Frameworks shouldn't need include paths, but much code does not use
# module-qualified #includes, so by default we add paths which point
@ -209,23 +209,17 @@ for(ever) {
!isEmpty(MODULE_MODULE) {
contains(MODULE_CONFIG, lib_bundle) {
framework = $$MODULE_MODULE
# Linking frameworks by absolute path does not work.
LIBS$$var_sfx += -framework $$framework
} else {
!isEmpty(MODULE_LIBS_ADD): \
LIBS$$var_sfx += -L$$MODULE_LIBS_ADD
lib = $$MODULE_MODULE$$qtPlatformTargetSuffix()
LIBS$$var_sfx += -l$$lib
contains(MODULE_CONFIG, staticlib): \
PRE_TARGETDEPS *= $$MODULE_LIBS/$${QMAKE_PREFIX_STATICLIB}$${lib}.$${QMAKE_EXTENSION_STATICLIB}
!isEmpty(QMAKE_LSB) {
!isEmpty(MODULE_LIBS_ADD): \
QMAKE_LFLAGS *= --lsb-libpath=$$MODULE_LIBS_ADD
QMAKE_LFLAGS *= --lsb-shared-libs=$$lib
QMAKE_LIBDIR *= /opt/lsb/lib
win32|contains(MODULE_CONFIG, staticlib) {
lib = $$MODULE_LIBS/$$QMAKE_PREFIX_STATICLIB$${lib}.$$QMAKE_EXTENSION_STATICLIB
PRE_TARGETDEPS += $$lib
} else {
lib = $$MODULE_LIBS/$$QMAKE_PREFIX_SHLIB$${lib}.$$QMAKE_EXTENSION_SHLIB
}
LIBS$$var_sfx += $$lib
}
}
QMAKE_USE$$var_sfx += $$MODULE_USES
@ -295,7 +289,8 @@ contains(all_qt_module_deps, qml): \
for (key, IMPORTS._KEYS_) {
PATH = $$eval(IMPORTS.$${key}.path)
PLUGIN = $$eval(IMPORTS.$${key}.plugin)
!isEmpty(PATH):!isEmpty(PLUGIN): LIBS *= -L$$PATH -l$${PLUGIN}$$qtPlatformTargetSuffix()
!isEmpty(PATH):!isEmpty(PLUGIN): \
LIBS += $$PATH/$$QMAKE_PREFIX_STATICLIB$${PLUGIN}$$qtPlatformTargetSuffix().$$QMAKE_EXTENSION_STATICLIB
}
# create qml_plugin_import.cpp

View File

@ -17,6 +17,7 @@ DEFINES *= QT_NO_NARROWING_CONVERSIONS_IN_CONNECT
qtConfig(c++11): CONFIG += c++11 strict_c++
qtConfig(c++14): CONFIG += c++14
qtConfig(c++1z): CONFIG += c++1z
qtConfig(c++2a): CONFIG += c++2a
qtConfig(c99): CONFIG += c99
qtConfig(c11): CONFIG += c11
qtConfig(stack-protector-strong): CONFIG += stack_protector_strong

View File

@ -526,6 +526,17 @@ defineTest(qtConfSetupLibraries) {
}
}
defineReplace(qtGccSysrootifiedPath) {
return($$replace(1, ^=, $$[QT_SYSROOT]))
}
defineReplace(qtGccSysrootifiedPaths) {
sysrootified =
for (path, 1): \
sysrootified += $$qtGccSysrootifiedPath($$path)
return($$sysrootified)
}
# libs-var, libs, in-paths, out-paths-var
defineTest(qtConfResolveLibs) {
ret = true
@ -542,6 +553,7 @@ defineTest(qtConfResolveLibs) {
out += $$l
} else: contains(l, "^-L.*") {
lp = $$replace(l, "^-L", )
gcc: lp = $$qtGccSysrootifiedPath($$lp)
!exists($$lp/.) {
qtLog("Library path $$val_escape(lp) is invalid.")
ret = false
@ -615,6 +627,7 @@ defineTest(qtConfResolveAllLibs) {
# libs-var, in-paths, libs
defineTest(qtConfResolvePathLibs) {
ret = true
gcc: 2 = $$qtGccSysrootifiedPaths($$2)
for (libdir, 2) {
!exists($$libdir/.) {
qtLog("Library path $$val_escape(libdir) is invalid.")
@ -665,6 +678,7 @@ defineReplace(qtConfGetTestIncludes) {
# includes-var, in-paths, test-object-var
defineTest(qtConfResolvePathIncs) {
ret = true
gcc: 2 = $$qtGccSysrootifiedPaths($$2)
for (incdir, 2) {
!exists($$incdir/.) {
qtLog("Include path $$val_escape(incdir) is invalid.")

View File

@ -23,7 +23,7 @@ load(qt_build_paths)
QMAKE_SYNCQT += -module $$mod
QMAKE_SYNCQT += \
-version $$VERSION -outdir $$system_quote($$MODULE_BASE_OUTDIR) \
-builddir $$system_quote($$shadowed($$MODULE_BASE_INDIR)) $$MODULE_SYNCQT_DIR
-builddir $$system_quote($$REAL_MODULE_BASE_OUTDIR) $$MODULE_SYNCQT_DIR
!silent: message($$QMAKE_SYNCQT)
system($$QMAKE_SYNCQT)|error("Failed to run: $$QMAKE_SYNCQT")

View File

@ -1,13 +1,21 @@
QT_FOR_CONFIG += gui
defineTest(prependOpenGlLib) {
path = $$QT.core.libs/$$QMAKE_PREFIX_STATICLIB$$1
ext = .$$QMAKE_EXTENSION_STATICLIB
QMAKE_LIBS_OPENGL_ES2 = $${path}$${ext} $$QMAKE_LIBS_OPENGL_ES2
QMAKE_LIBS_OPENGL_ES2_DEBUG = $${path}d$${ext} $$QMAKE_LIBS_OPENGL_ES2_DEBUG
export(QMAKE_LIBS_OPENGL_ES2)
export(QMAKE_LIBS_OPENGL_ES2_DEBUG)
}
qtConfig(opengles2) {
# Depending on the configuration we use libQtANGLE or libEGL and libGLESv2
qtConfig(combined-angle-lib) {
QMAKE_LIBS_OPENGL_ES2 = -l$${LIBQTANGLE_NAME} $$QMAKE_LIBS_OPENGL_ES2
QMAKE_LIBS_OPENGL_ES2_DEBUG = -l$${LIBQTANGLE_NAME}d $$QMAKE_LIBS_OPENGL_ES2_DEBUG
prependOpenGlLib($$LIBQTANGLE_NAME)
} else {
QMAKE_LIBS_OPENGL_ES2 = -l$${LIBEGL_NAME} -l$${LIBGLESV2_NAME} $$QMAKE_LIBS_OPENGL_ES2
QMAKE_LIBS_OPENGL_ES2_DEBUG = -l$${LIBEGL_NAME}d -l$${LIBGLESV2_NAME}d $$QMAKE_LIBS_OPENGL_ES2_DEBUG
prependOpenGlLib($$LIBGLESV2_NAME)
prependOpenGlLib($$LIBEGL_NAME)
}
# For Desktop, use the ANGLE library location passed on from configure.
INCLUDEPATH += $$QMAKE_INCDIR_OPENGL_ES2

View File

@ -6,10 +6,9 @@ contains(TEMPLATE, ".*app") {
qt:for(entryLib, $$list($$unique(QMAKE_LIBS_QT_ENTRY))) {
isEqual(entryLib, -lqtmain) {
!contains(QMAKE_DEFAULT_LIBDIRS, $$QT.core.libs): \
QMAKE_LIBS += -L$$QT.core.libs
CONFIG(debug, debug|release): QMAKE_LIBS += $${entryLib}$${QT_LIBINFIX}d
else: QMAKE_LIBS += $${entryLib}$${QT_LIBINFIX}
lib = $$QT.core.libs/$${QMAKE_PREFIX_STATICLIB}qtmain$$QT_LIBINFIX$$qtPlatformTargetSuffix().$$QMAKE_EXTENSION_STATICLIB
PRE_TARGETDEPS += $$lib
QMAKE_LIBS += $$lib
} else {
QMAKE_LIBS += $${entryLib}
}

View File

@ -13,7 +13,6 @@ load(qt_config)
QMAKE_LIBS_THREAD += -lrt
QMAKE_LSB = 1
QMAKE_CC = lsbcc
QMAKE_CXX = lsbc++

View File

@ -1271,6 +1271,41 @@
\snippet code/doc_src_qmake-manual.pro 36
\c INSTALLS has a \c{.CONFIG} member that can take several values:
\table
\header
\li Value
\li Description
\row
\li no_check_exists
\li If not set, qmake looks to see if the files to install actually
exist. If these files don't exist, qmake doesnt create the
install rule. Use this config value if you need to install
files that are generated as part of your build process, like
HTML files created by qdoc.
\row
\li nostrip
\li If set, the typical Unix strip functionality is turned off and
the debug information will remain in the binary.
\row
\li executable
\li On Unix, this sets the executable flag.
\row
\li no_build
\li When you do a \c{make install}, and you don't have a build of
the project yet, the project is first built, and then installed.
If you don't want this behavior, set this config value to ensure
that the build target is not added as a dependency to the install
target.
\row
\li no_default_install
\li A project has a top-level project target where, when you do a
\c{make install}, everything is installed. But, if you have an
install target with this config value set, it's not installed by
default. You then have to explicitly say \c{make install_<file>}.
\endtable
For more information, see \l{Installing Files}.
This variable is also used to specify which additional files will be
@ -1580,6 +1615,14 @@
The value of this variable is typically handled by qmake or \l{#QMAKESPEC}{qmake.conf}
and rarely needs to be modified.
\target QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO
\section1 QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO
Specifies the C compiler flags for release builds where
\c{force_debug_info} is set in \c{CONFIG}.
The value of this variable is typically handled by
qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified.
\target QMAKE_CFLAGS_SHLIB
\section1 QMAKE_CFLAGS_SHLIB
@ -1648,6 +1691,14 @@
The value of this variable is typically handled by
qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified.
\target QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO
\section1 QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO
Specifies the C++ compiler flags for release builds where
\c{force_debug_info} is set in \c{CONFIG}.
The value of this variable is typically handled by
qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified.
\target QMAKE_CXXFLAGS_SHLIB
\section1 QMAKE_CXXFLAGS_SHLIB
@ -2028,6 +2079,12 @@
The value of this variable is typically handled by
qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified.
\section1 QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO
Specifies the linker flags for release builds where \c{force_debug_info} is
set in \c{CONFIG}. The value of this variable is typically handled by
qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified.
\section1 QMAKE_LFLAGS_APP
Specifies the linker flags for building applications.
@ -4813,6 +4870,7 @@
\li Unix
\list
\li GCC 3.4 and above
\li clang
\endlist
\endlist

View File

@ -143,6 +143,7 @@ const char _InterfaceIdentifierFileName[] = "InterfaceIdentifierFileName";
const char _IntermediateDirectory[] = "IntermediateDirectory";
const char _KeyContainer[] = "KeyContainer";
const char _KeyFile[] = "KeyFile";
const char _LanguageStandard[] = "LanguageStandard";
const char _LargeAddressAware[] = "LargeAddressAware";
const char _LinkDLL[] = "LinkDLL";
const char _LinkErrorReporting[] = "LinkErrorReporting";
@ -1478,6 +1479,7 @@ void VCXProjectWriter::write(XmlOutput &xml, const VCCLCompilerTool &tool)
<< attrTagT(_IntrinsicFunctions, tool.EnableIntrinsicFunctions)
<< attrTagT(_MinimalRebuild, tool.MinimalRebuild)
<< attrTagT(_MultiProcessorCompilation, tool.MultiProcessorCompilation)
<< attrTagS(_LanguageStandard, tool.LanguageStandard)
<< attrTagS(_ObjectFileName, tool.ObjectFile)
<< attrTagT(_OmitDefaultLibName, tool.OmitDefaultLibName)
<< attrTagT(_OmitFramePointers, tool.OmitFramePointers)

View File

@ -1147,6 +1147,14 @@ bool VCCLCompilerTool::parseOption(const char* option)
ShowIncludes = _True;
break;
}
if (strlen(option) > 8 && second == 't' && third == 'd') {
const QString version = option + 8;
static const QStringList knownVersions = { "14", "17", "latest" };
if (knownVersions.contains(version)) {
LanguageStandard = "stdcpp" + version;
break;
}
}
found = false; break;
case 'u':
if (!second)

View File

@ -526,6 +526,7 @@ public:
triState ImproveFloatingPointConsistency;
inlineExpansionOption InlineFunctionExpansion;
triState KeepComments;
QString LanguageStandard;
triState MinimalRebuild;
QString ObjectFile;
triState OmitDefaultLibName;

View File

@ -364,6 +364,23 @@ Display *Display::GetDisplayFromDevice(Device *device, const AttributeMap &attri
return display;
}
//static
void Display::CleanupDisplays()
{
// ~Display takes care of removing the entry from the according map
{
ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap();
while (!displays->empty())
delete displays->begin()->second;
}
{
DevicePlatformDisplayMap *displays = GetDevicePlatformDisplayMap();
while (!displays->empty())
delete displays->begin()->second;
}
}
Display::Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice)
: mImplementation(nullptr),
mDisplayId(displayId),

View File

@ -65,6 +65,7 @@ class Display final : angle::NonCopyable
static Display *GetDisplayFromDevice(Device *device, const AttributeMap &attribMap);
static Display *GetDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay,
const AttributeMap &attribMap);
static void CleanupDisplays();
static const ClientExtensions &GetClientExtensions();
static const std::string &GetClientExtensionString();

View File

@ -13,6 +13,7 @@
#include "common/tls.h"
#include "libANGLE/Thread.h"
#include "libANGLE/Display.h"
namespace gl
{
@ -140,6 +141,7 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD reason, LPVOID)
return static_cast<BOOL>(egl::DeallocateCurrentThread());
case DLL_PROCESS_DETACH:
egl::Display::CleanupDisplays();
return static_cast<BOOL>(egl::TerminateProcess());
}

View File

@ -0,0 +1,78 @@
From d8ca4f6d0d8fffd8319f340685e03751049678ae Mon Sep 17 00:00:00 2001
From: Oliver Wolff <oliver.wolff@qt.io>
Date: Tue, 16 Apr 2019 10:19:27 +0200
Subject: [PATCH] ANGLE: clean up displays on dll unload
If the displays are not cleaned up on dll unloading, profilers might
report memory leaks.
Change-Id: I04cbc3c2448bfb450f7d840e216827f86856e963
---
src/3rdparty/angle/src/libANGLE/Display.cpp | 17 +++++++++++++++++
src/3rdparty/angle/src/libANGLE/Display.h | 1 +
.../angle/src/libGLESv2/global_state.cpp | 2 ++
3 files changed, 20 insertions(+)
diff --git a/src/3rdparty/angle/src/libANGLE/Display.cpp b/src/3rdparty/angle/src/libANGLE/Display.cpp
index 735b472787..0bb0bb05b1 100644
--- a/src/3rdparty/angle/src/libANGLE/Display.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Display.cpp
@@ -364,6 +364,23 @@ Display *Display::GetDisplayFromDevice(Device *device, const AttributeMap &attri
return display;
}
+//static
+void Display::CleanupDisplays()
+{
+ // ~Display takes care of removing the entry from the according map
+ {
+ ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap();
+ while (!displays->empty())
+ delete displays->begin()->second;
+ }
+
+ {
+ DevicePlatformDisplayMap *displays = GetDevicePlatformDisplayMap();
+ while (!displays->empty())
+ delete displays->begin()->second;
+ }
+}
+
Display::Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice)
: mImplementation(nullptr),
mDisplayId(displayId),
diff --git a/src/3rdparty/angle/src/libANGLE/Display.h b/src/3rdparty/angle/src/libANGLE/Display.h
index aa1d1c3b37..2a1c386d75 100644
--- a/src/3rdparty/angle/src/libANGLE/Display.h
+++ b/src/3rdparty/angle/src/libANGLE/Display.h
@@ -65,6 +65,7 @@ class Display final : angle::NonCopyable
static Display *GetDisplayFromDevice(Device *device, const AttributeMap &attribMap);
static Display *GetDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay,
const AttributeMap &attribMap);
+ static void CleanupDisplays();
static const ClientExtensions &GetClientExtensions();
static const std::string &GetClientExtensionString();
diff --git a/src/3rdparty/angle/src/libGLESv2/global_state.cpp b/src/3rdparty/angle/src/libGLESv2/global_state.cpp
index c5f3dfe4e1..26045bf5b2 100644
--- a/src/3rdparty/angle/src/libGLESv2/global_state.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/global_state.cpp
@@ -13,6 +13,7 @@
#include "common/tls.h"
#include "libANGLE/Thread.h"
+#include "libANGLE/Display.h"
namespace gl
{
@@ -140,6 +141,7 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD reason, LPVOID)
return static_cast<BOOL>(egl::DeallocateCurrentThread());
case DLL_PROCESS_DETACH:
+ egl::Display::CleanupDisplays();
return static_cast<BOOL>(egl::TerminateProcess());
}
--
2.20.1.windows.1

View File

@ -61,6 +61,9 @@
#endif
#if defined(__cplusplus)
#ifdef Q_CC_MINGW
# include <unistd.h> // Define _POSIX_THREAD_SAFE_FUNCTIONS to obtain localtime_r()
#endif
#include <time.h>
QT_BEGIN_NAMESPACE

View File

@ -310,9 +310,18 @@ static QString readSymLink(const QFileSystemEntry &link)
const wchar_t* PathBuffer = &rdb->SymbolicLinkReparseBuffer.PathBuffer[offset];
result = QString::fromWCharArray(PathBuffer, length);
}
// cut-off "//?/" and "/??/"
if (result.size() > 4 && result.at(0) == QLatin1Char('\\') && result.at(2) == QLatin1Char('?') && result.at(3) == QLatin1Char('\\'))
// cut-off "\\?\" and "\??\"
if (result.size() > 4
&& result.at(0) == QLatin1Char('\\')
&& result.at(2) == QLatin1Char('?')
&& result.at(3) == QLatin1Char('\\')) {
result = result.mid(4);
// cut off UNC in addition when the link points at a UNC share
// in which case we need to prepend another backslash to get \\server\share
if (result.leftRef(3) == QLatin1String("UNC")) {
result.replace(0, 3, QLatin1Char('\\'));
}
}
}
free(rdb);
CloseHandle(handle);

View File

@ -3619,7 +3619,7 @@ QModelIndex QAbstractTableModel::sibling(int row, int column, const QModelIndex
bool QAbstractTableModel::hasChildren(const QModelIndex &parent) const
{
if (parent.model() == this || !parent.isValid())
if (!parent.isValid())
return rowCount(parent) > 0 && columnCount(parent) > 0;
return false;
}

View File

@ -515,7 +515,7 @@ struct Q_CORE_EXPORT QMetaObject
Qt::ConnectionType type = Qt::AutoConnection, decltype(function()) *ret = nullptr)
{
return invokeMethodImpl(context,
new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(function),
new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(std::move(function)),
type,
ret);
}
@ -527,7 +527,7 @@ struct Q_CORE_EXPORT QMetaObject
invokeMethod(QObject *context, Func function, typename std::result_of<Func()>::type *ret)
{
return invokeMethodImpl(context,
new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(function),
new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(std::move(function)),
Qt::AutoConnection,
ret);
}

View File

@ -58,6 +58,9 @@
#endif
#include <cmath>
#ifdef Q_CC_MINGW
# include <unistd.h> // Define _POSIX_THREAD_SAFE_FUNCTIONS to obtain localtime_r()
#endif
#include <time.h>
#ifdef Q_OS_WIN
# include <qt_windows.h>

View File

@ -335,7 +335,7 @@ public:
inline bool operator>(const QDateTime &other) const { return other < *this; }
inline bool operator>=(const QDateTime &other) const { return !(*this < other); }
#if QT_DEPRECATED_SINCE(5, 2)
#if QT_DEPRECATED_SINCE(5, 2) // ### Qt 6: remove
QT_DEPRECATED void setUtcOffset(int seconds);
QT_DEPRECATED int utcOffset() const;
#endif // QT_DEPRECATED_SINCE

View File

@ -2482,6 +2482,17 @@ QString QLocale::toString(double i, char f, int prec) const
Returns a QLocale object initialized to the "C" locale.
This locale is based on en_US but with various quirks of its own, such as
simplified number formatting and its own date formatting. It implements the
POSIX standards that describe the behavior of standard library functions of
the "C" programming language.
Among other things, this means its collation order is based on the ASCII
values of letters, so that (for case-sensitive sorting) all upper-case
letters sort before any lower-case one (rather than each letter's upper- and
lower-case forms sorting adjacent to one another, before the next letter's
two forms).
\sa system()
*/

View File

@ -104,7 +104,7 @@
This enumerated type is used to specify a language.
\value AnyLanguage
\value C The "C" locale is identical in behavior to English/UnitedStates.
\value C A simplified English locale; see QLocale::c()
\value Abkhazian
\value Afan Obsolete, please use Oromo

View File

@ -46,6 +46,8 @@
#include "qwindow.h"
#include "qplatformwindow.h"
#include <private/qwindow_p.h>
QT_BEGIN_NAMESPACE
/*!
@ -199,12 +201,18 @@ void QOffscreenSurface::create()
if (QThread::currentThread() != qGuiApp->thread())
qWarning("Attempting to create QWindow-based QOffscreenSurface outside the gui thread. Expect failures.");
d->offscreenWindow = new QWindow(d->screen);
// Make the window frameless to prevent Windows from enlarging it, should it
// violate the minimum title bar width on the platform.
d->offscreenWindow->setFlags(d->offscreenWindow->flags()
| Qt::CustomizeWindowHint | Qt::FramelessWindowHint);
d->offscreenWindow->setObjectName(QLatin1String("QOffscreenSurface"));
// Remove this window from the global list since we do not want it to be destroyed when closing the app.
// The QOffscreenSurface has to be usable even after exiting the event loop.
QGuiApplicationPrivate::window_list.removeOne(d->offscreenWindow);
d->offscreenWindow->setSurfaceType(QWindow::OpenGLSurface);
d->offscreenWindow->setFormat(d->requestedFormat);
// Prevent QPlatformWindow::initialGeometry() and platforms from setting a default geometry.
qt_window_private(d->offscreenWindow)->setAutomaticPositionAndResizeEnabled(false);
d->offscreenWindow->setGeometry(0, 0, d->size.width(), d->size.height());
d->offscreenWindow->create();
}

View File

@ -366,40 +366,35 @@ void qt_mac_scale_region(QRegion *region, qreal scaleFactor)
// ---------------------- QMacCGContext ----------------------
QMacCGContext::QMacCGContext(QPaintDevice *paintDevice) : context(0)
QMacCGContext::QMacCGContext(QPaintDevice *paintDevice)
{
// In Qt 5, QWidget and QPixmap (and QImage) paint devices are all QImages under the hood.
QImage *image = 0;
if (paintDevice->devType() == QInternal::Image) {
image = static_cast<QImage *>(paintDevice);
} else if (paintDevice->devType() == QInternal::Pixmap) {
const QPixmap *pm = static_cast<const QPixmap*>(paintDevice);
QPlatformPixmap *data = const_cast<QPixmap *>(pm)->data_ptr().data();
if (data && data->classId() == QPlatformPixmap::RasterClass) {
image = data->buffer();
} else {
qDebug("QMacCGContext: Unsupported pixmap class");
}
} else if (paintDevice->devType() == QInternal::Widget) {
// TODO test: image = static_cast<QImage *>(static_cast<const QWidget *>(paintDevice)->backingStore()->paintDevice());
qDebug("QMacCGContext: not implemented: Widget class");
}
if (!image)
return; // Context type not supported.
QCFType<CGColorSpaceRef> colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
context = CGBitmapContextCreate(image->bits(), image->width(), image->height(), 8,
image->bytesPerLine(), colorSpace, qt_mac_bitmapInfoForImage(*image));
CGContextTranslateCTM(context, 0, image->height());
const qreal devicePixelRatio = paintDevice->devicePixelRatioF();
CGContextScaleCTM(context, devicePixelRatio, devicePixelRatio);
CGContextScaleCTM(context, 1, -1);
initialize(paintDevice);
}
QMacCGContext::QMacCGContext(QPainter *painter) : context(0)
void QMacCGContext::initialize(QPaintDevice *paintDevice)
{
// Find the underlying QImage of the paint device
switch (int deviceType = paintDevice->devType()) {
case QInternal::Pixmap: {
auto *platformPixmap = static_cast<QPixmap*>(paintDevice)->handle();
if (platformPixmap && platformPixmap->classId() == QPlatformPixmap::RasterClass)
initialize(platformPixmap->buffer());
else
qWarning() << "QMacCGContext: Unsupported pixmap class" << platformPixmap->classId();
break;
}
case QInternal::Image:
initialize(static_cast<const QImage *>(paintDevice));
break;
case QInternal::Widget:
qWarning() << "QMacCGContext: not implemented: Widget class";
break;
default:
qWarning() << "QMacCGContext:: Unsupported paint device type" << deviceType;
}
}
QMacCGContext::QMacCGContext(QPainter *painter)
{
QPaintEngine *paintEngine = painter->paintEngine();
@ -414,51 +409,68 @@ QMacCGContext::QMacCGContext(QPainter *painter) : context(0)
return;
}
int devType = painter->device()->devType();
if (paintEngine->type() == QPaintEngine::Raster
&& (devType == QInternal::Widget ||
devType == QInternal::Pixmap ||
devType == QInternal::Image)) {
const QImage *image = static_cast<const QImage *>(paintEngine->paintDevice());
QCFType<CGColorSpaceRef> colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
context = CGBitmapContextCreate((void *)image->bits(), image->width(), image->height(), 8,
image->bytesPerLine(), colorSpace, qt_mac_bitmapInfoForImage(*image));
// Invert y axis
CGContextTranslateCTM(context, 0, image->height());
CGContextScaleCTM(context, 1, -1);
const qreal devicePixelRatio = image->devicePixelRatio();
if (devType == QInternal::Widget) {
// Set the clip rect which is an intersection of the system clip
// and the painter clip. To make matters more interesting these
// are in device pixels and device-independent pixels, respectively.
QRegion clip = painter->paintEngine()->systemClip(); // get system clip in device pixels
QTransform native = painter->deviceTransform(); // get device transform. dx/dy is in device pixels
if (painter->hasClipping()) {
QRegion r = painter->clipRegion(); // get painter clip, which is in device-independent pixels
qt_mac_scale_region(&r, devicePixelRatio); // scale painter clip to device pixels
r.translate(native.dx(), native.dy());
if (clip.isEmpty())
clip = r;
else
clip &= r;
}
qt_mac_clip_cg(context, clip, 0); // clip in device pixels
// Scale the context so that painting happens in device-independent pixels
CGContextScaleCTM(context, devicePixelRatio, devicePixelRatio);
CGContextTranslateCTM(context, native.dx() / devicePixelRatio, native.dy() / devicePixelRatio);
} else {
// Scale to paint in device-independent pixels
CGContextScaleCTM(context, devicePixelRatio, devicePixelRatio);
}
} else {
qDebug() << "QMacCGContext:: Unsupported painter devtype type" << devType;
if (paintEngine->type() != QPaintEngine::Raster) {
qWarning() << "QMacCGContext:: Unsupported paint engine type" << paintEngine->type();
return;
}
// The raster paint engine always operates on a QImage
Q_ASSERT(paintEngine->paintDevice()->devType() == QInternal::Image);
// On behalf of one of these supported painter devices
switch (int painterDeviceType = painter->device()->devType()) {
case QInternal::Pixmap:
case QInternal::Image:
case QInternal::Widget:
break;
default:
qWarning() << "QMacCGContext:: Unsupported paint device type" << painterDeviceType;
return;
}
// Applying the clip is so entangled with the rest of the context setup
// that for simplicity we just pass in the painter.
initialize(static_cast<const QImage *>(paintEngine->paintDevice()), painter);
}
void QMacCGContext::initialize(const QImage *image, QPainter *painter)
{
QCFType<CGColorSpaceRef> colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
context = CGBitmapContextCreate((void *)image->bits(), image->width(), image->height(), 8,
image->bytesPerLine(), colorSpace, qt_mac_bitmapInfoForImage(*image));
// Invert y axis
CGContextTranslateCTM(context, 0, image->height());
CGContextScaleCTM(context, 1, -1);
const qreal devicePixelRatio = image->devicePixelRatio();
if (painter && painter->device()->devType() == QInternal::Widget) {
// Set the clip rect which is an intersection of the system clip and the painter clip
QRegion clip = painter->paintEngine()->systemClip();
QTransform deviceTransform = painter->deviceTransform();
if (painter->hasClipping()) {
// To make matters more interesting the painter clip is in device-independent pixels,
// so we need to scale it to match the device-pixels of the system clip.
QRegion painterClip = painter->clipRegion();
qt_mac_scale_region(&painterClip, devicePixelRatio);
painterClip.translate(deviceTransform.dx(), deviceTransform.dy());
if (clip.isEmpty())
clip = painterClip;
else
clip &= painterClip;
}
qt_mac_clip_cg(context, clip, 0);
CGContextTranslateCTM(context, deviceTransform.dx(), deviceTransform.dy());
}
// Scale the context so that painting happens in device-independent pixels
CGContextScaleCTM(context, devicePixelRatio, devicePixelRatio);
}
QT_END_NAMESPACE

View File

@ -51,6 +51,8 @@
// We mean it.
//
#include <QtCore/private/qcore_mac_p.h>
#include <QtGui/private/qtguiglobal_p.h>
#include <QtGui/qregion.h>
#include <QtGui/qpalette.h>
@ -89,38 +91,16 @@ Q_GUI_EXPORT QBrush qt_mac_toQBrush(CGColorRef color);
class Q_GUI_EXPORT QMacCGContext
{
public:
inline QMacCGContext() { context = 0; }
QMacCGContext() = default;
QMacCGContext(QPaintDevice *pdev);
QMacCGContext(QPainter *p);
inline QMacCGContext(CGContextRef cg, bool takeOwnership = false) {
context = cg;
if (!takeOwnership)
CGContextRetain(context);
}
inline QMacCGContext(const QMacCGContext &copy) : context(0) { *this = copy; }
inline ~QMacCGContext() {
if (context)
CGContextRelease(context);
}
inline bool isNull() const { return context; }
inline operator CGContextRef() { return context; }
inline QMacCGContext &operator=(const QMacCGContext &copy) {
if (context)
CGContextRelease(context);
context = copy.context;
CGContextRetain(context);
return *this;
}
inline QMacCGContext &operator=(CGContextRef cg) {
if (context)
CGContextRelease(context);
context = cg;
CGContextRetain(context); //we do not take ownership
return *this;
}
operator CGContextRef() { return context; }
private:
CGContextRef context;
void initialize(QPaintDevice *paintDevice);
void initialize(const QImage *, QPainter *painter = nullptr);
QCFType<CGContextRef> context;
};
QT_END_NAMESPACE

View File

@ -43,6 +43,7 @@ QT_BEGIN_NAMESPACE
QShaderFormat::QShaderFormat() noexcept
: m_api(NoApi)
, m_shaderType(Fragment)
{
}
@ -106,6 +107,9 @@ bool QShaderFormat::supports(const QShaderFormat &other) const noexcept
if (m_version < other.m_version)
return false;
if (m_shaderType != other.m_shaderType)
return false;
const auto containsAllExtensionsFromOther = std::includes(m_extensions.constBegin(),
m_extensions.constEnd(),
other.m_extensions.constBegin(),
@ -119,12 +123,23 @@ bool QShaderFormat::supports(const QShaderFormat &other) const noexcept
return true;
}
QShaderFormat::ShaderType QShaderFormat::shaderType() const Q_DECL_NOTHROW
{
return m_shaderType;
}
void QShaderFormat::setShaderType(QShaderFormat::ShaderType shaderType) Q_DECL_NOTHROW
{
m_shaderType = shaderType;
}
bool operator==(const QShaderFormat &lhs, const QShaderFormat &rhs) noexcept
{
return lhs.api() == rhs.api()
&& lhs.version() == rhs.version()
&& lhs.extensions() == rhs.extensions()
&& lhs.vendor() == rhs.vendor();
&& lhs.vendor() == rhs.vendor()
&& lhs.shaderType() == rhs.shaderType();
}
QT_END_NAMESPACE

View File

@ -69,6 +69,15 @@ public:
OpenGLES
};
enum ShaderType : int {
Vertex = 0,
TessellationControl,
TessellationEvaluation,
Geometry,
Fragment,
Compute
};
Q_GUI_EXPORT QShaderFormat() noexcept;
Q_GUI_EXPORT Api api() const noexcept;
@ -86,11 +95,15 @@ public:
Q_GUI_EXPORT bool isValid() const noexcept;
Q_GUI_EXPORT bool supports(const QShaderFormat &other) const noexcept;
Q_GUI_EXPORT ShaderType shaderType() const Q_DECL_NOTHROW;
Q_GUI_EXPORT void setShaderType(ShaderType shaderType) Q_DECL_NOTHROW;
private:
Api m_api;
QVersionNumber m_version;
QStringList m_extensions;
QString m_vendor;
ShaderType m_shaderType;
};
Q_GUI_EXPORT bool operator==(const QShaderFormat &lhs, const QShaderFormat &rhs) noexcept;

View File

@ -40,6 +40,7 @@
#include "qshadergenerator_p.h"
#include "qshaderlanguage_p.h"
#include <QRegularExpression>
QT_BEGIN_NAMESPACE
@ -56,7 +57,10 @@ namespace
case QShaderLanguage::Const:
return "const";
case QShaderLanguage::Input:
return "varying";
if (format.shaderType() == QShaderFormat::Vertex)
return "attribute";
else
return "varying";
case QShaderLanguage::Output:
return ""; // Although fragment shaders for <=2 only have fixed outputs
case QShaderLanguage::Uniform:
@ -314,12 +318,22 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers)
[enabledLayers] (const QString &s) { return enabledLayers.contains(s); });
};
QVector<QString> globalInputVariables;
const QRegularExpression globalInputExtractRegExp(QStringLiteral("^.*\\s+(\\w+).*;$"));
const QVector<QShaderNode> nodes = graph.nodes();
for (const QShaderNode &node : nodes) {
if (intersectsEnabledLayers(node.layers())) {
const QByteArrayList headerSnippets = node.rule(format).headerSnippets;
for (const QByteArray &snippet : headerSnippets) {
code << replaceParameters(snippet, node, format);
// If node is an input, record the variable name into the globalInputVariables vector
if (node.type() == QShaderNode::Input) {
const QRegularExpressionMatch match = globalInputExtractRegExp.match(QString::fromUtf8(code.last()));
if (match.hasMatch())
globalInputVariables.push_back(match.captured(1));
}
}
}
}
@ -328,6 +342,14 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers)
code << QByteArrayLiteral("void main()");
code << QByteArrayLiteral("{");
// Table to store temporary variables that should be replaced by global
// variables. This avoids having vec3 v56 = vertexPosition; when we could
// just use vertexPosition directly.
// The added benefit is when having arrays, we don't try to create
// mat4 v38 = skinningPalelette[100] which would be invalid
QHash<QString, QString> localReferencesToGlobalInputs;
const QRegularExpression localToGlobalRegExp(QStringLiteral("^.*\\s+(\\w+)\\s*=\\s*(\\w+).*;$"));
for (const QShaderGraph::Statement &statement : graph.createStatements(enabledLayers)) {
const QShaderNode node = statement.node;
QByteArray line = node.rule(format).substitution;
@ -338,6 +360,9 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers)
const bool isInput = port.direction == QShaderNodePort::Input;
const int portIndex = statement.portIndex(portDirection, portName);
Q_ASSERT(portIndex >= 0);
const int variableIndex = isInput ? statement.inputs.at(portIndex)
: statement.outputs.at(portIndex);
if (variableIndex < 0)
@ -345,15 +370,51 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers)
const auto placeholder = QByteArray(QByteArrayLiteral("$") + portName.toUtf8());
const auto variable = QByteArray(QByteArrayLiteral("v") + QByteArray::number(variableIndex));
line.replace(placeholder, variable);
}
code << QByteArrayLiteral(" ") + replaceParameters(line, node, format);
const QByteArray substitutionedLine = replaceParameters(line, node, format);
// Record name of temporary variable that possibly references a global input
// We will replace the temporary variables by the matching global variables later
bool isAGlobalInputVariable = false;
if (node.type() == QShaderNode::Input) {
const QRegularExpressionMatch match = localToGlobalRegExp.match(QString::fromUtf8(substitutionedLine));
if (match.hasMatch()) {
const QString globalVariable = match.captured(2);
if (globalInputVariables.contains(globalVariable)) {
const QString localVariable = match.captured(1);
// TO DO: Clean globalVariable (remove brackets ...)
localReferencesToGlobalInputs.insert(localVariable, globalVariable);
isAGlobalInputVariable = true;
}
}
}
// Only insert content for lines aren't inputs or have not matching
// globalVariables for now
if (!isAGlobalInputVariable)
code << QByteArrayLiteral(" ") + substitutionedLine;
}
code << QByteArrayLiteral("}");
code << QByteArray();
return code.join('\n');
// Replace occurrences of local variables which reference a global variable
// by the global variables directly
auto it = localReferencesToGlobalInputs.cbegin();
const auto end = localReferencesToGlobalInputs.cend();
QString codeString = QString::fromUtf8(code.join('\n'));
while (it != end) {
const QRegularExpression r(QStringLiteral("\\b(%1)([\\b|\\.|;|\\)|\\[|\\s|\\*|\\+|\\/|\\-|,])").arg(it.key()),
QRegularExpression::MultilineOption);
codeString.replace(r, QStringLiteral("%1\\2").arg(it.value()));
++it;
}
return codeString.toUtf8();
}
QT_END_NAMESPACE

View File

@ -251,6 +251,17 @@ void QShaderNodesLoader::load(const QJsonObject &prototypesObject)
break;
}
// We default out to a Fragment ShaderType if nothing is specified
// as that was the initial behavior we introduced
const QString shaderType = formatObject.value(QStringLiteral("shaderType")).toString();
format.setShaderType(shaderType == QStringLiteral("Fragment") ? QShaderFormat::Fragment
: shaderType == QStringLiteral("Vertex") ? QShaderFormat::Vertex
: shaderType == QStringLiteral("TessellationControl") ? QShaderFormat::TessellationControl
: shaderType == QStringLiteral("TessellationEvaluation") ? QShaderFormat::TessellationEvaluation
: shaderType == QStringLiteral("Geometry") ? QShaderFormat::Geometry
: shaderType == QStringLiteral("Compute") ? QShaderFormat::Compute
: QShaderFormat::Fragment);
const QByteArray substitution = substitutionValue.toString().toUtf8();
const QJsonValue snippetsValue = ruleObject.value(QStringLiteral("headerSnippets"));

View File

@ -385,8 +385,8 @@ QHostAddress QNetmask::address(QAbstractSocket::NetworkLayerProtocol protocol) c
\value LocalHost The IPv4 localhost address. Equivalent to QHostAddress("127.0.0.1").
\value LocalHostIPv6 The IPv6 localhost address. Equivalent to QHostAddress("::1").
\value Broadcast The IPv4 broadcast address. Equivalent to QHostAddress("255.255.255.255").
\value AnyIPv4 The IPv4 any-address. Equivalent to QHostAddress("0.0.0.0"). A socket bound with this address will listen only on IPv4 interaces.
\value AnyIPv6 The IPv6 any-address. Equivalent to QHostAddress("::"). A socket bound with this address will listen only on IPv6 interaces.
\value AnyIPv4 The IPv4 any-address. Equivalent to QHostAddress("0.0.0.0"). A socket bound with this address will listen only on IPv4 interfaces.
\value AnyIPv6 The IPv6 any-address. Equivalent to QHostAddress("::"). A socket bound with this address will listen only on IPv6 interfaces.
\value Any The dual stack any-address. A socket bound with this address will listen on both IPv4 and IPv6 interfaces.
*/

View File

@ -268,7 +268,7 @@ EGLConfig QEglConfigChooser::chooseConfig()
configureAttributes.append(EGL_OPENGL_ES_BIT);
break;
}
// fall through
Q_FALLTHROUGH();
default:
needsES2Plus = true;
break;

View File

@ -134,7 +134,7 @@ QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatform
void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLContext *share)
{
m_format = q_glFormatFromConfig(m_eglDisplay, m_eglConfig);
m_format = q_glFormatFromConfig(m_eglDisplay, m_eglConfig, format);
// m_format now has the renderableType() resolved (it cannot be Default anymore)
// but does not yet contain version, profile, options.
m_shareContext = share ? static_cast<QEGLPlatformContext *>(share)->m_eglContext : 0;
@ -248,6 +248,12 @@ void QEGLPlatformContext::adopt(const QVariant &nativeHandle, QPlatformOpenGLCon
value = 0;
eglQueryContext(m_eglDisplay, context, EGL_CONTEXT_CLIENT_TYPE, &value);
if (value == EGL_OPENGL_API || value == EGL_OPENGL_ES_API) {
// if EGL config supports both OpenGL and OpenGL ES render type,
// q_glFormatFromConfig() with the default "referenceFormat" parameter
// will always figure it out as OpenGL render type.
// We can override it to match user's real render type.
if (value == EGL_OPENGL_ES_API)
m_format.setRenderableType(QSurfaceFormat::OpenGLES);
m_api = value;
eglBindAPI(m_api);
} else {

View File

@ -6,7 +6,7 @@ CONFIG += static internal_module
DEFINES += QT_NO_CAST_FROM_ASCII
QMAKE_USE_PRIVATE += xlib
QMAKE_USE += xlib
HEADERS += qglxconvenience_p.h
SOURCES += qglxconvenience.cpp

View File

@ -96,8 +96,8 @@ void QTsLibMouseHandler::readMouseData()
int x = sample.x;
int y = sample.y;
// work around missing coordinates on mouse release
if (sample.pressure == 0 && sample.x == 0 && sample.y == 0) {
// coordinates on release events can contain arbitrary values, just ignore them
if (sample.pressure == 0) {
x = m_x;
y = m_y;
}

View File

@ -59,6 +59,7 @@ enum OutputConfiguration {
OutputConfigOff,
OutputConfigPreferred,
OutputConfigCurrent,
OutputConfigSkip,
OutputConfigMode,
OutputConfigModeline
};
@ -191,6 +192,8 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources,
configuration = OutputConfigPreferred;
} else if (mode == "current") {
configuration = OutputConfigCurrent;
} else if (mode == "skip") {
configuration = OutputConfigSkip;
} else if (sscanf(mode.constData(), "%dx%d@%d", &configurationSize.rwidth(), &configurationSize.rheight(),
&configurationRefresh) == 3)
{
@ -229,6 +232,11 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources,
return nullptr;
}
if (configuration == OutputConfigSkip) {
qCDebug(qLcKmsDebug) << "Skipping output" << connectorName;
return nullptr;
}
// Get the current mode on the current crtc
drmModeModeInfo crtc_mode;
memset(&crtc_mode, 0, sizeof crtc_mode);

View File

@ -188,14 +188,15 @@ static inline QRect toBottomLeftRect(const QRect &topLeftRect, int windowHeight)
topLeftRect.width(), topLeftRect.height());
}
static void clippedBlit(const QPlatformTextureList *textures, int idx, const QRect &targetWindowRect,
static void clippedBlit(const QPlatformTextureList *textures, int idx, const QRect &sourceWindowRect,
const QRect &targetWindowRect,
QOpenGLTextureBlitter *blitter, QMatrix4x4 *rotationMatrix)
{
const QRect clipRect = textures->clipRect(idx);
if (clipRect.isEmpty())
return;
const QRect rectInWindow = textures->geometry(idx);
const QRect rectInWindow = textures->geometry(idx).translated(sourceWindowRect.topLeft());
const QRect clippedRectInWindow = rectInWindow & clipRect.translated(rectInWindow.topLeft());
const QRect srcRect = toBottomLeftRect(clipRect, rectInWindow.height());
@ -218,7 +219,7 @@ void QOpenGLCompositor::render(QOpenGLCompositorWindow *window)
const QRect targetWindowRect(QPoint(0, 0), m_targetWindow->geometry().size());
float currentOpacity = 1.0f;
BlendStateBinder blend;
const QRect sourceWindowRect = window->sourceWindow()->geometry();
for (int i = 0; i < textures->count(); ++i) {
uint textureId = textures->textureId(i);
const float opacity = window->sourceWindow()->opacity();
@ -243,16 +244,16 @@ void QOpenGLCompositor::render(QOpenGLCompositorWindow *window)
target = m_rotationMatrix * target;
m_blitter.blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft);
} else if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) {
// Texture from an FBO belonging to a QOpenGLWidget
// Texture from an FBO belonging to a QOpenGLWidget or QQuickWidget
blend.set(false);
clippedBlit(textures, i, targetWindowRect, &m_blitter, m_rotation ? &m_rotationMatrix : nullptr);
clippedBlit(textures, i, sourceWindowRect, targetWindowRect, &m_blitter, m_rotation ? &m_rotationMatrix : nullptr);
}
}
for (int i = 0; i < textures->count(); ++i) {
if (textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) {
blend.set(true);
clippedBlit(textures, i, targetWindowRect, &m_blitter, m_rotation ? &m_rotationMatrix : nullptr);
clippedBlit(textures, i, sourceWindowRect, targetWindowRect, &m_blitter, m_rotation ? &m_rotationMatrix : nullptr);
}
}

View File

@ -300,7 +300,7 @@ void QGenericEngine::doRequestUpdate()
if (interface.flags() & QNetworkInterface::IsLoopBack)
continue;
#ifndef Q_OS_WINRT
#ifndef Q_OS_WIN
// ignore WLAN interface handled in separate engine
if (qGetInterfaceType(interface.name()) == QNetworkConfiguration::BearerWLAN)
continue;

View File

@ -93,6 +93,7 @@ private:
QRegion dirtyRegion; // In unscaled coordinates
QImage *asImage();
qreal devicePixelRatio() const { return m_devicePixelRatio; }
private:
qreal m_devicePixelRatio;

View File

@ -460,12 +460,29 @@ void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion &region,
NSView *backingStoreView = static_cast<QCocoaWindow *>(window()->handle())->view();
NSView *flushedView = static_cast<QCocoaWindow *>(flushedWindow->handle())->view();
// If the backingstore is just flushed, without being painted to first, then we may
// end in a situation where the backingstore is flushed to a layer with a different
// scale factor than the one it was created for in beginPaint. This is the client's
// fault in not picking up the change in scale factor of the window and re-painting
// the backingstore accordingly. To smoothing things out, we warn about this situation,
// and change the layer's contentsScale to match the scale of the back buffer, so that
// we at least cover the whole layer. This is necessary since we set the view's
// contents placement policy to NSViewLayerContentsPlacementTopLeft, which means
// AppKit will not do any scaling on our behalf.
if (m_buffers.back()->devicePixelRatio() != flushedView.layer.contentsScale) {
qCWarning(lcQpaBackingStore) << "Back buffer dpr of" << m_buffers.back()->devicePixelRatio()
<< "doesn't match" << flushedView.layer << "contents scale of" << flushedView.layer.contentsScale
<< "- updating layer to match.";
flushedView.layer.contentsScale = m_buffers.back()->devicePixelRatio();
}
id backBufferSurface = (__bridge id)m_buffers.back()->surface();
if (flushedView.layer.contents == backBufferSurface) {
// We've managed to paint to the back buffer again before Core Animation had time
// to flush the transaction and persist the layer changes to the window server.
// The layer already knows about the back buffer, and we don't need to re-apply
// it to pick up the surface changes, so bail out early.
// to flush the transaction and persist the layer changes to the window server, or
// we've been asked to flush without painting anything. The layer already knows about
// the back buffer, and we don't need to re-apply it to pick up any possible surface
// changes, so bail out early.
qCInfo(lcQpaBackingStore).nospace() << "Skipping flush of " << flushedView
<< ", layer already reflects back buffer";
return;

View File

@ -154,6 +154,7 @@
<< "due to being" << ([self layerExplicitlyRequested] ? "explicitly requested"
: [self shouldUseMetalLayer] ? "needed by surface type" : "enabled by macOS");
[super setLayer:layer];
layer.delegate = self;
}
- (NSViewLayerContentsRedrawPolicy)layerContentsRedrawPolicy

View File

@ -199,6 +199,10 @@ QPlatformWindow *QEglFSIntegration::createPlatformWindow(QWindow *window) const
QEglFSWindow *w = qt_egl_device_integration()->createWindow(window);
w->create();
const auto showWithoutActivating = window->property("_q_showWithoutActivating");
if (showWithoutActivating.isValid() && showWithoutActivating.toBool())
return w;
// Activate only the window for the primary screen to make input work
if (window->type() != Qt::ToolTip && window->screen() == QGuiApplication::primaryScreen())
w->requestActivateWindow();

View File

@ -167,6 +167,9 @@ void QEglFSWindow::create()
void QEglFSWindow::destroy()
{
if (!m_flags.testFlag(Created))
return; // already destroyed
#ifndef QT_NO_OPENGL
QOpenGLCompositor::instance()->removeWindow(this);
#endif

View File

@ -55,6 +55,9 @@ public:
: QEglFSWindow(w),
m_integration(integration)
{ }
~QEglFSKmsGbmWindow() { destroy(); }
void resetSurface() override;
void invalidateSurface() override;

View File

@ -117,6 +117,8 @@ public:
, m_framePending(false)
{ }
~QEglFSKmsEglDeviceWindow() { destroy(); }
void invalidateSurface() override;
void resetSurface() override;
void flip();

View File

@ -205,6 +205,9 @@ public:
: QEglFSWindow(w)
, m_integration(integration)
{}
~QEglFSKmsVsp2Window() { destroy(); }
void resetSurface() override;
void invalidateSurface() override;
const QEglFSKmsVsp2Integration *m_integration;

View File

@ -41,6 +41,7 @@
#include <QtCore/qurl.h>
#include <QtCore/qmimedata.h>
#include "qwindowsmime.h"
QT_BEGIN_NAMESPACE
@ -48,8 +49,9 @@ QT_BEGIN_NAMESPACE
\class QWindowsDropDataObject
\brief QWindowsOleDataObject subclass specialized for handling Drag&Drop.
Only allows "text/uri-list" data to be exported as CF_HDROP, to allow dropped
files to be attached to Office applications (instead of adding an URL link).
Prevents "text/uri-list" data for local files from being exported as text
or URLs, to allow dropped files to be attached to Office applications
(instead of creating local hyperlinks).
\internal
\ingroup qt-lighthouse-win
@ -80,14 +82,22 @@ QWindowsDropDataObject::QueryGetData(LPFORMATETC pformatetc)
return QWindowsOleDataObject::QueryGetData(pformatetc);
}
// If the data is text/uri-list for local files, tell we can only export it as CF_HDROP.
// If the data is "text/uri-list" only, and all URIs are for local files,
// we prevent it from being exported as text or URLs, to make target applications
// like MS Office attach or open the files instead of creating local hyperlinks.
bool QWindowsDropDataObject::shouldIgnore(LPFORMATETC pformatetc) const
{
QMimeData *dropData = mimeData();
if (dropData && dropData->hasFormat(QStringLiteral("text/uri-list")) && (pformatetc->cfFormat != CF_HDROP)) {
QList<QUrl> urls = dropData->urls();
return std::any_of(urls.cbegin(), urls.cend(), [] (const QUrl &u) { return u.isLocalFile(); });
if (dropData && dropData->formats().size() == 1 && dropData->hasUrls()) {
QString formatName = QWindowsMimeConverter::clipboardFormatName(pformatetc->cfFormat);
if (pformatetc->cfFormat == CF_UNICODETEXT
|| pformatetc->cfFormat == CF_TEXT
|| formatName == QStringLiteral("UniformResourceLocator")
|| formatName == QStringLiteral("UniformResourceLocatorW")) {
QList<QUrl> urls = dropData->urls();
return std::all_of(urls.cbegin(), urls.cend(), [] (const QUrl &u) { return u.isLocalFile(); });
}
}
return false;

View File

@ -879,21 +879,16 @@ bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window, con
#if defined(WM_APPCOMMAND)
const int cmd = GET_APPCOMMAND_LPARAM(msg.lParam);
// QTBUG-57198, do not send mouse-synthesized commands as key events in addition
bool skipPressRelease = false;
switch (GET_DEVICE_LPARAM(msg.lParam)) {
case FAPPCOMMAND_MOUSE:
return false;
case FAPPCOMMAND_KEY:
// QTBUG-62838, swallow WM_KEYDOWN, WM_KEYUP for commands that are
// reflected in VK(s) like VK_MEDIA_NEXT_TRACK. Don't do that for
// APPCOMMAND_BROWSER_HOME as that one does not trigger two events
if (cmd != APPCOMMAND_BROWSER_HOME) {
MSG peekedMsg;
if (PeekMessage(&peekedMsg, msg.hwnd, 0, 0, PM_NOREMOVE)
&& peekedMsg.message == WM_KEYDOWN) {
PeekMessage(&peekedMsg, msg.hwnd, 0, 0, PM_REMOVE);
PeekMessage(&peekedMsg, msg.hwnd, 0, 0, PM_REMOVE);
}
}
// QTBUG-62838, use WM_KEYDOWN/WM_KEYUP for commands that are reflected
// in VK(s) like VK_MEDIA_NEXT_TRACK, to get correct codes and autorepeat.
// Don't do that for APPCOMMAND_BROWSER_HOME as that one does not trigger two events.
if (cmd != APPCOMMAND_BROWSER_HOME)
skipPressRelease = true;
break;
}
@ -908,7 +903,8 @@ bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window, con
return false;
const int qtKey = int(CmdTbl[cmd]);
sendExtendedPressRelease(receiver, qtKey, Qt::KeyboardModifier(state), 0, 0, 0);
if (!skipPressRelease)
sendExtendedPressRelease(receiver, qtKey, Qt::KeyboardModifier(state), 0, 0, 0);
// QTBUG-43343: Make sure to return false if Qt does not handle the key, otherwise,
// the keys are not passed to the active media player.
# if QT_CONFIG(shortcut)

View File

@ -1087,7 +1087,10 @@ bool QWindowsMimeImage::canConvertFromMime(const FORMATETC &formatetc, const QMi
const QImage image = qvariant_cast<QImage>(mimeData->imageData());
if (image.isNull())
return false;
return cf == CF_DIBV5 || (cf == CF_DIB) || cf == int(CF_PNG);
// QTBUG-64322: Use PNG only for transparent images as otherwise MS PowerPoint
// cannot handle it.
return cf == CF_DIBV5 || cf == CF_DIB
|| (cf == int(CF_PNG) && image.hasAlphaChannel());
}
bool QWindowsMimeImage::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const

View File

@ -250,6 +250,23 @@ static Qt::MouseButtons mouseButtonsFromKeyState(WPARAM keyState)
return result;
}
static Qt::MouseButtons queryMouseButtons()
{
Qt::MouseButtons result = Qt::NoButton;
const bool mouseSwapped = GetSystemMetrics(SM_SWAPBUTTON);
if (GetAsyncKeyState(VK_LBUTTON) < 0)
result |= mouseSwapped ? Qt::RightButton: Qt::LeftButton;
if (GetAsyncKeyState(VK_RBUTTON) < 0)
result |= mouseSwapped ? Qt::LeftButton : Qt::RightButton;
if (GetAsyncKeyState(VK_MBUTTON) < 0)
result |= Qt::MidButton;
if (GetAsyncKeyState(VK_XBUTTON1) < 0)
result |= Qt::XButton1;
if (GetAsyncKeyState(VK_XBUTTON2) < 0)
result |= Qt::XButton2;
return result;
}
static QWindow *getWindowUnderPointer(QWindow *window, QPoint globalPos)
{
QWindow *currentWindowUnderPointer = QWindowsScreen::windowAt(globalPos, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT);
@ -531,7 +548,7 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
if (!QWindowsContext::user32dll.getPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect))
return false;
const quint32 pointerId = penInfo->pointerInfo.pointerId;
const qint64 sourceDevice = (qint64)penInfo->pointerInfo.sourceDevice;
const QPoint globalPos = QPoint(penInfo->pointerInfo.ptPixelLocation.x, penInfo->pointerInfo.ptPixelLocation.y);
const QPoint localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPos);
const QPointF hiResGlobalPos = QPointF(dRect.left + qreal(penInfo->pointerInfo.ptHimetricLocation.x - pRect.left)
@ -547,7 +564,7 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
if (QWindowsContext::verbose > 1)
qCDebug(lcQpaEvents).noquote().nospace() << showbase
<< __FUNCTION__ << " pointerId=" << pointerId
<< __FUNCTION__ << " sourceDevice=" << sourceDevice
<< " globalPos=" << globalPos << " localPos=" << localPos << " hiResGlobalPos=" << hiResGlobalPos
<< " message=" << hex << msg.message
<< " flags=" << hex << penInfo->pointerInfo.pointerFlags;
@ -570,7 +587,7 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
switch (msg.message) {
case WM_POINTERENTER: {
QWindowSystemInterface::handleTabletEnterProximityEvent(device, type, pointerId);
QWindowSystemInterface::handleTabletEnterProximityEvent(device, type, sourceDevice);
m_windowUnderPointer = window;
// The local coordinates may fall outside the window.
// Wait until the next update to send the enter event.
@ -583,12 +600,12 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
m_windowUnderPointer = nullptr;
m_currentWindow = nullptr;
}
QWindowSystemInterface::handleTabletLeaveProximityEvent(device, type, pointerId);
QWindowSystemInterface::handleTabletLeaveProximityEvent(device, type, sourceDevice);
break;
case WM_POINTERDOWN:
case WM_POINTERUP:
case WM_POINTERUPDATE: {
QWindow *target = QGuiApplicationPrivate::tabletDevicePoint(pointerId).target; // Pass to window that grabbed it.
QWindow *target = QGuiApplicationPrivate::tabletDevicePoint(sourceDevice).target; // Pass to window that grabbed it.
if (!target && m_windowUnderPointer)
target = m_windowUnderPointer;
if (!target)
@ -607,7 +624,7 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
QWindowSystemInterface::handleTabletEvent(target, localPos, hiResGlobalPos, device, type, mouseButtons,
pressure, xTilt, yTilt, tangentialPressure, rotation, z,
pointerId, keyModifiers);
sourceDevice, keyModifiers);
return false; // Allow mouse messages to be generated.
}
}
@ -681,7 +698,6 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window,
}
const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
const Qt::MouseButtons mouseButtons = mouseButtonsFromKeyState(msg.wParam);
QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos);
if (et == QtWindows::MouseWheelEvent)
@ -709,7 +725,8 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window,
const MouseEvent mouseEvent = eventFromMsg(msg);
if (mouseEvent.type >= QEvent::NonClientAreaMouseMove && mouseEvent.type <= QEvent::NonClientAreaMouseButtonDblClick) {
QWindowSystemInterface::handleFrameStrutMouseEvent(window, localPos, globalPos, mouseButtons,
const Qt::MouseButtons nonclientButtons = queryMouseButtons();
QWindowSystemInterface::handleFrameStrutMouseEvent(window, localPos, globalPos, nonclientButtons,
mouseEvent.button, mouseEvent.type, keyModifiers, source);
return false; // Allow further event processing
}
@ -725,6 +742,8 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window,
return true;
}
const Qt::MouseButtons mouseButtons = mouseButtonsFromKeyState(msg.wParam);
handleCaptureRelease(window, currentWindowUnderPointer, hwnd, mouseEvent.type, mouseButtons);
handleEnterLeave(window, currentWindowUnderPointer, globalPos);

View File

@ -113,6 +113,9 @@ void QWindowsUiaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event
case QAccessible::ValueChanged:
QWindowsUiaMainProvider::notifyValueChange(static_cast<QAccessibleValueChangeEvent *>(event));
break;
case QAccessible::SelectionAdd:
QWindowsUiaMainProvider::notifySelectionChange(event);
break;
case QAccessible::TextAttributeChanged:
case QAccessible::TextColumnChanged:
case QAccessible::TextInserted:

View File

@ -146,9 +146,33 @@ void QWindowsUiaMainProvider::notifyStateChange(QAccessibleStateChangeEvent *eve
void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *event)
{
if (QAccessibleInterface *accessible = event->accessibleInterface()) {
if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
// Notifies changes in values of controls supporting the value interface.
if (accessible->role() == QAccessible::ComboBox && accessible->childCount() > 0) {
QAccessibleInterface *listacc = accessible->child(0);
if (listacc && listacc->role() == QAccessible::List) {
int count = listacc->childCount();
for (int i = 0; i < count; ++i) {
QAccessibleInterface *item = listacc->child(i);
if (item && item->text(QAccessible::Name) == event->value()) {
if (!item->state().selected) {
if (QAccessibleActionInterface *actionInterface = item->actionInterface())
actionInterface->doAction(QAccessibleActionInterface::toggleAction());
}
break;
}
}
}
}
if (event->value().type() == QVariant::String) {
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
// Notifies changes in string values.
VARIANT oldVal, newVal;
clearVariant(&oldVal);
setVariantString(event->value().toString(), &newVal);
QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider, UIA_ValueValuePropertyId, oldVal, newVal);
}
} else if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
// Notifies changes in values of controls supporting the value interface.
VARIANT oldVal, newVal;
clearVariant(&oldVal);
setVariantDouble(valueInterface->currentValue().toDouble(), &newVal);
@ -158,6 +182,15 @@ void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *eve
}
}
void QWindowsUiaMainProvider::notifySelectionChange(QAccessibleEvent *event)
{
if (QAccessibleInterface *accessible = event->accessibleInterface()) {
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_SelectionItem_ElementSelectedEventId);
}
}
}
// Notifies changes in text content and selection state of text controls.
void QWindowsUiaMainProvider::notifyTextChange(QAccessibleEvent *event)
{

View File

@ -68,6 +68,7 @@ public:
static void notifyFocusChange(QAccessibleEvent *event);
static void notifyStateChange(QAccessibleStateChangeEvent *event);
static void notifyValueChange(QAccessibleValueChangeEvent *event);
static void notifySelectionChange(QAccessibleEvent *event);
static void notifyTextChange(QAccessibleEvent *event);
// IUnknown

View File

@ -270,7 +270,9 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share)
// ES does not support any format option
m_format.setOptions(QSurfaceFormat::FormatOptions());
}
// Robustness must match that of the shared context.
if (share && share->format().testOption(QSurfaceFormat::ResetNotification))
m_format.setOption(QSurfaceFormat::ResetNotification);
Q_ASSERT(glVersions.count() > 0);
for (int i = 0; !m_context && i < glVersions.count(); i++) {

View File

@ -1156,66 +1156,6 @@ static QStyleHelper::WidgetSizePolicy qt_aqua_guess_size(const QWidget *widg, QS
}
#endif
static NSColor *qt_convertColorForContext(CGContextRef context, NSColor *color)
{
Q_ASSERT(color);
Q_ASSERT(context);
CGColorSpaceRef targetCGColorSpace = CGBitmapContextGetColorSpace(context);
NSColorSpace *targetNSColorSpace = [[NSColorSpace alloc] initWithCGColorSpace:targetCGColorSpace];
NSColor *adjusted = [color colorUsingColorSpace:targetNSColorSpace];
[targetNSColorSpace release];
return adjusted;
}
static NSColor *qt_colorForContext(CGContextRef context, const CGFloat (&rgba)[4])
{
Q_ASSERT(context);
auto colorSpace = CGBitmapContextGetColorSpace(context);
if (!colorSpace)
return nil;
return qt_convertColorForContext(context, [NSColor colorWithSRGBRed:rgba[0] green:rgba[1] blue:rgba[2] alpha:rgba[3]]);
}
static void qt_drawDisclosureButton(CGContextRef context, NSInteger state, bool selected, CGRect rect)
{
Q_ASSERT(context);
static const CGFloat gray[] = {0.55, 0.55, 0.55, 0.97};
static const CGFloat white[] = {1.0, 1.0, 1.0, 0.9};
NSColor *fillColor = qt_colorForContext(context, selected ? white : gray);
[fillColor setFill];
if (state == NSOffState) {
static NSBezierPath *triangle = [[NSBezierPath alloc] init];
[triangle removeAllPoints];
// In off state, a disclosure button is an equilateral triangle
// ('pointing' to the right) with a bound rect that can be described
// as NSMakeRect(0, 0, 8, 9). Inside the 'rect' it's translated by
// (2, 4).
[triangle moveToPoint:NSMakePoint(rect.origin.x + 2, rect.origin.y + 4)];
[triangle lineToPoint:NSMakePoint(rect.origin.x + 2, rect.origin.y + 4 + 9)];
[triangle lineToPoint:NSMakePoint(rect.origin.x + 2 + 8, rect.origin.y + 4 + 4.5)];
[triangle closePath];
[triangle fill];
} else {
static NSBezierPath *openTriangle = [[NSBezierPath alloc] init];
[openTriangle removeAllPoints];
// In 'on' state, the button is an equilateral triangle (looking down)
// with the bounding rect NSMakeRect(0, 0, 9, 8). Inside the 'rect'
// it's translated by (1, 4).
[openTriangle moveToPoint:NSMakePoint(rect.origin.x + 1, rect.origin.y + 4 + 8)];
[openTriangle lineToPoint:NSMakePoint(rect.origin.x + 1 + 9, rect.origin.y + 4 + 8)];
[openTriangle lineToPoint:NSMakePoint(rect.origin.x + 1 + 4.5, rect.origin.y + 4)];
[openTriangle closePath];
[openTriangle fill];
}
}
void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const
{
QPainterPath focusRingPath;
@ -3301,15 +3241,8 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
CGContextScaleCTM(cg, 1, -1);
CGContextTranslateCTM(cg, -rect.origin.x, -rect.origin.y);
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave && !qt_mac_applicationIsInDarkMode()) {
// When the real system theme is one of the 'Dark' themes, and an application forces the 'Aqua' theme,
// under some conditions (see QTBUG-74515 for more details) NSButtonCell seems to select the 'Dark'
// code path and is becoming transparent, thus 'invisible' on the white background. To workaround this,
// we draw the disclose triangle manually:
qt_drawDisclosureButton(cg, triangleCell.state, (opt->state & State_Selected) && viewHasFocus, rect);
} else {
[triangleCell drawBezelWithFrame:NSRectFromCGRect(rect) inView:[triangleCell controlView]];
}
[triangleCell drawBezelWithFrame:NSRectFromCGRect(rect) inView:[triangleCell controlView]];
d->restoreNSGraphicsContext(cg);
break; }

View File

@ -11343,7 +11343,7 @@ void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter)
}
// sourceRect must be in the given coordinate system
QRect QGraphicsItemEffectSourcePrivate::paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded) const
QRectF QGraphicsItemEffectSourcePrivate::paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded) const
{
QRectF effectRectF;
@ -11371,7 +11371,7 @@ QRect QGraphicsItemEffectSourcePrivate::paddedEffectRect(Qt::CoordinateSystem sy
*unpadded = true;
}
return effectRectF.toAlignedRect();
return effectRectF;
}
QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset,
@ -11389,7 +11389,8 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP
bool unpadded;
const QRectF sourceRect = boundingRect(system);
QRect effectRect = paddedEffectRect(system, mode, sourceRect, &unpadded);
QRectF effectRectF = paddedEffectRect(system, mode, sourceRect, &unpadded);
QRect effectRect = effectRectF.toAlignedRect();
if (offset)
*offset = effectRect.topLeft();
@ -11405,7 +11406,9 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP
if (effectRect.isEmpty())
return QPixmap();
QPixmap pixmap(effectRect.size());
const auto dpr = info ? info->painter->device()->devicePixelRatioF() : 1.0;
QPixmap pixmap(QRectF(effectRectF.topLeft(), effectRectF.size() * dpr).toAlignedRect().size());
pixmap.setDevicePixelRatio(dpr);
pixmap.fill(Qt::transparent);
QPainter pixmapPainter(&pixmap);
pixmapPainter.setRenderHints(info ? info->painter->renderHints() : QPainter::TextAntialiasing);

View File

@ -644,7 +644,7 @@ public:
QPixmap pixmap(Qt::CoordinateSystem system,
QPoint *offset,
QGraphicsEffect::PixmapPadMode mode) const override;
QRect paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded = nullptr) const;
QRectF paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded = nullptr) const;
QGraphicsItem *item;
QGraphicsItemPaintInfo *info;

View File

@ -4852,7 +4852,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
&& painter->worldTransform().type() <= QTransform::TxTranslate)
{
QRectF sourceRect = sourced->boundingRect(Qt::DeviceCoordinates);
QRect effectRect = sourced->paddedEffectRect(Qt::DeviceCoordinates, sourced->currentCachedMode(), sourceRect);
QRect effectRect = sourced->paddedEffectRect(Qt::DeviceCoordinates, sourced->currentCachedMode(), sourceRect).toAlignedRect();
sourced->setCachedOffset(effectRect.topLeft());
} else {

View File

@ -2283,13 +2283,15 @@ void QHeaderViewPrivate::_q_sectionsChanged(const QList<QPersistentModelIndex> &
: index.row());
// the new visualIndices are already adjusted / reset by initializeSections()
const int newVisualIndex = visualIndex(newLogicalIndex);
auto &newSection = sectionItems[newVisualIndex];
newSection = item.section;
if (newVisualIndex < sectionItems.count()) {
auto &newSection = sectionItems[newVisualIndex];
newSection = item.section;
if (newSection.isHidden) {
// otherwise setSectionHidden will return without doing anything
newSection.isHidden = false;
q->setSectionHidden(newLogicalIndex, true);
if (newSection.isHidden) {
// otherwise setSectionHidden will return without doing anything
newSection.isHidden = false;
q->setSectionHidden(newLogicalIndex, true);
}
}
}

View File

@ -650,11 +650,13 @@ QListWidgetItem::QListWidgetItem(const QString &text, QListWidget *listview, int
|Qt::ItemIsEnabled
|Qt::ItemIsDragEnabled)
{
QListModel *model = listModel();
{
QSignalBlocker b(view);
QSignalBlocker bm(model);
setData(Qt::DisplayRole, text);
}
if (QListModel *model = listModel())
if (model)
model->insert(model->rowCount(), this);
}
@ -683,12 +685,14 @@ QListWidgetItem::QListWidgetItem(const QIcon &icon,const QString &text,
|Qt::ItemIsEnabled
|Qt::ItemIsDragEnabled)
{
QListModel *model = listModel();
{
QSignalBlocker b(view);
QSignalBlocker bm(model);
setData(Qt::DisplayRole, text);
setData(Qt::DecorationRole, icon);
}
if (QListModel *model = listModel())
if (model)
model->insert(model->rowCount(), this);
}

View File

@ -1448,7 +1448,8 @@ bool QOpenGLWidget::event(QEvent *e)
{
// Special case: did grabFramebuffer() for a hidden widget that then became visible.
// Recreate all resources since the context now needs to share with the TLW's.
d->reset();
if (!qGuiApp->testAttribute(Qt::AA_ShareOpenGLContexts))
d->reset();
}
if (!d->initialized && !size().isEmpty() && window()->windowHandle()) {
d->initialize();

View File

@ -2908,7 +2908,10 @@ void QStyleSheetStyle::polish(QPalette &pal)
void QStyleSheetStyle::repolish(QWidget *w)
{
QList<const QObject *> children = w->findChildren<const QObject *>(QString());
QList<const QObject *> children;
children.reserve(w->children().size() + 1);
for (auto child: qAsConst(w->children()))
children.append(child);
children.append(w);
styleSheetCaches->styleSheetCache.remove(w);
updateObjects(children);

View File

@ -69,6 +69,7 @@
QT_BEGIN_NAMESPACE
class QSystemTrayIconSys;
class QSystemTrayWatcher;
class QPlatformSystemTrayIcon;
class QToolButton;
class QLabel;
@ -90,6 +91,8 @@ public:
void showMessage_sys(const QString &title, const QString &msg, const QIcon &icon,
QSystemTrayIcon::MessageIcon msgIcon, int msecs);
void destroyIcon();
static bool isSystemTrayAvailable_sys();
static bool supportsMessages_sys();
@ -101,6 +104,7 @@ public:
QSystemTrayIconSys *sys;
QPlatformSystemTrayIcon *qpa_sys;
bool visible;
QSystemTrayWatcher *trayWatcher;
private:
void install_sys_qpa();

View File

@ -92,9 +92,6 @@ protected:
virtual void resizeEvent(QResizeEvent *) override;
virtual void moveEvent(QMoveEvent *) override;
private slots:
void systemTrayWindowChanged(QScreen *screen);
private:
QSystemTrayIcon *q;
};
@ -116,15 +113,6 @@ QSystemTrayIconSys::QSystemTrayIconSys(QSystemTrayIcon *qIn)
setMouseTracking(true);
}
void QSystemTrayIconSys::systemTrayWindowChanged(QScreen *)
{
if (!locateSystemTray()) {
QBalloonTip::hideBalloon();
hide(); // still no luck
destroy();
}
}
QRect QSystemTrayIconSys::globalGeometry() const
{
return QRect(mapToGlobal(QPoint(0, 0)), size());
@ -199,10 +187,41 @@ void QSystemTrayIconSys::resizeEvent(QResizeEvent *event)
}
////////////////////////////////////////////////////////////////////////////
class QSystemTrayWatcher: public QObject
{
Q_OBJECT
public:
QSystemTrayWatcher(QSystemTrayIcon *trayIcon)
: QObject(trayIcon)
, mTrayIcon(trayIcon)
{
// This code uses string-based syntax because we want to connect to a signal
// which is defined in XCB plugin - QXcbNativeInterface::systemTrayWindowChanged().
connect(qGuiApp->platformNativeInterface(), SIGNAL(systemTrayWindowChanged(QScreen*)),
this, SLOT(systemTrayWindowChanged(QScreen*)));
}
private slots:
void systemTrayWindowChanged(QScreen *)
{
auto icon = static_cast<QSystemTrayIconPrivate *>(QObjectPrivate::get(mTrayIcon));
icon->destroyIcon();
if (icon->visible && locateSystemTray()) {
icon->sys = new QSystemTrayIconSys(mTrayIcon);
icon->sys->show();
}
}
private:
QSystemTrayIcon *mTrayIcon = nullptr;
};
////////////////////////////////////////////////////////////////////////////
QSystemTrayIconPrivate::QSystemTrayIconPrivate()
: sys(0),
qpa_sys(QGuiApplicationPrivate::platformTheme()->createPlatformSystemTrayIcon()),
visible(false)
visible(false),
trayWatcher(nullptr)
{
}
@ -213,16 +232,21 @@ QSystemTrayIconPrivate::~QSystemTrayIconPrivate()
void QSystemTrayIconPrivate::install_sys()
{
Q_Q(QSystemTrayIcon);
if (qpa_sys) {
install_sys_qpa();
return;
}
Q_Q(QSystemTrayIcon);
if (!sys && locateSystemTray()) {
sys = new QSystemTrayIconSys(q);
QObject::connect(QGuiApplication::platformNativeInterface(), SIGNAL(systemTrayWindowChanged(QScreen*)),
sys, SLOT(systemTrayWindowChanged(QScreen*)));
sys->show();
if (!sys) {
if (!trayWatcher)
trayWatcher = new QSystemTrayWatcher(q);
if (locateSystemTray()) {
sys = new QSystemTrayIconSys(q);
sys->show();
}
}
}
@ -241,14 +265,21 @@ void QSystemTrayIconPrivate::remove_sys()
remove_sys_qpa();
return;
}
destroyIcon();
}
void QSystemTrayIconPrivate::destroyIcon()
{
if (!sys)
return;
QBalloonTip::hideBalloon();
sys->hide(); // this should do the trick, but...
delete sys; // wm may resize system tray only for DestroyEvents
sys = 0;
sys->hide();
delete sys;
sys = nullptr;
}
void QSystemTrayIconPrivate::updateIcon_sys()
{
if (qpa_sys) {

View File

@ -1239,6 +1239,8 @@ void QPlainTextEditPrivate::ensureViewportLayouted()
This property gets and sets the plain text editor's contents. The previous
contents are removed and undo/redo history is reset when this property is set.
currentCharFormat() is also reset, unless textCursor() is already at the
beginning of the document.
By default, for an editor with no contents, this property contains an empty string.
*/
@ -1518,7 +1520,12 @@ void QPlainTextEdit::paste()
/*!
Deletes all the text in the text edit.
Note that the undo/redo history is cleared by this function.
Notes:
\list
\li The undo/redo history is also cleared.
\li currentCharFormat() is reset, unless textCursor()
is already at the beginning of the document.
\endlist
\sa cut(), setPlainText()
*/
@ -1651,7 +1658,12 @@ void QPlainTextEdit::timerEvent(QTimerEvent *e)
\a text is interpreted as plain text.
Note that the undo/redo history is cleared by this function.
Notes:
\list
\li The undo/redo history is also cleared.
\li currentCharFormat() is reset, unless textCursor()
is already at the beginning of the document.
\endlist
\sa toPlainText()
*/

View File

@ -556,7 +556,8 @@ void QTextEditPrivate::_q_ensureVisible(const QRectF &_rect)
This property gets and sets the text editor's contents as plain
text. Previous contents are removed and undo/redo history is reset
when the property is set.
when the property is set. currentCharFormat() is also reset, unless
textCursor() is already at the beginning of the document.
If the text edit has another content type, it will not be replaced
by plain text if you call toPlainText(). The only exception to this
@ -1034,7 +1035,12 @@ void QTextEdit::paste()
/*!
Deletes all the text in the text edit.
Note that the undo/redo history is cleared by this function.
Notes:
\list
\li The undo/redo history is also cleared.
\li currentCharFormat() is reset, unless textCursor()
is already at the beginning of the document.
\endlist
\sa cut(), setPlainText(), setHtml()
*/
@ -1139,9 +1145,13 @@ void QTextEdit::timerEvent(QTimerEvent *e)
Changes the text of the text edit to the string \a text.
Any previous text is removed.
\a text is interpreted as plain text.
Note that the undo/redo history is cleared by this function.
Notes:
\list
\li \a text is interpreted as plain text.
\li The undo/redo history is also cleared.
\li currentCharFormat() is reset, unless textCursor()
is already at the beginning of the document.
\endlist
\sa toPlainText()
*/
@ -1175,7 +1185,8 @@ QString QTextEdit::toPlainText() const
setHtml() changes the text of the text edit. Any previous text is
removed and the undo/redo history is cleared. The input text is
interpreted as rich text in html format.
interpreted as rich text in html format. currentCharFormat() is also
reset, unless textCursor() is already at the beginning of the document.
\note It is the responsibility of the caller to make sure that the
text is correctly decoded when a QString containing HTML is created

View File

@ -1559,6 +1559,16 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data()
<< NtfsTestResource(NtfsTestResource::SymLink, relToRelSymlink, relToRelTarget)
<< relToRelSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath();
}
{
// Symlink to UNC share
pwd.mkdir("unc");
QString errorMessage;
QString uncTarget = QStringLiteral("//") + QtNetworkSettings::winServerName() + "/testshare";
QString uncSymlink = QDir::toNativeSeparators(pwd.absolutePath().append("\\unc\\link_to_unc"));
QTest::newRow("UNC symlink")
<< NtfsTestResource(NtfsTestResource::SymLink, uncSymlink, uncTarget)
<< QDir::fromNativeSeparators(uncSymlink) << true << QDir::fromNativeSeparators(uncTarget) << uncTarget;
}
//Junctions
QString target = "target";
@ -1630,7 +1640,7 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks()
// Ensure that junctions, mountpoints are removed. If this fails, do not remove
// temporary directory to prevent it from trashing the system.
if (fi.isDir()) {
if (!QDir().rmdir(fi.fileName())) {
if (!QDir().rmdir(fi.filePath())) {
qWarning("Unable to remove NTFS junction '%s'', keeping '%s'.",
qPrintable(fi.fileName()), qPrintable(QDir::toNativeSeparators(m_dir.path())));
m_dir.setAutoRemove(false);

View File

@ -1,4 +1,5 @@
CONFIG += testcase
qtConfig(c++14): CONFIG += c++14
TARGET = tst_qmetaobject
QT = core-private testlib
SOURCES = tst_qmetaobject.cpp

View File

@ -816,6 +816,15 @@ void tst_QMetaObject::invokePointer()
QCOMPARE(obj.slotResult, QString("sl1:bubu"));
}
QCOMPARE(countedStructObjectsCount, 0);
#ifdef __cpp_init_captures
{
CountedStruct str;
std::unique_ptr<int> ptr( new int );
QVERIFY(QMetaObject::invokeMethod(&obj, [str, &t1, &obj, p = std::move(ptr)]() { obj.sl1(t1); }));
QCOMPARE(obj.slotResult, QString("sl1:1"));
}
QCOMPARE(countedStructObjectsCount, 0);
#endif
}
void tst_QMetaObject::invokeQueuedMetaMember()
@ -1121,6 +1130,15 @@ void tst_QMetaObject::invokeBlockingQueuedPointer()
QCOMPARE(exp, QString("yessir"));
QCOMPARE(obj.slotResult, QString("sl1:bubu"));
}
#ifdef __cpp_init_captures
{
std::unique_ptr<int> ptr(new int);
QVERIFY(QMetaObject::invokeMethod(&obj,
[&obj, p = std::move(ptr)]() { return obj.sl1("hehe"); },
Qt::BlockingQueuedConnection));
QCOMPARE(obj.slotResult, QString("sl1:hehe"));
}
#endif
QVERIFY(QMetaObject::invokeMethod(&obj, [&](){obj.moveToThread(QThread::currentThread());}, Qt::BlockingQueuedConnection));
t.quit();
QVERIFY(t.wait());

View File

@ -78,9 +78,11 @@ private slots:
void toString_isoDate_data();
void toString_isoDate();
void toString_isoDate_extra();
#if QT_CONFIG(datestring)
void toString_textDate_data();
void toString_textDate();
void toString_textDate_extra();
#endif
void toString_rfcDate_data();
void toString_rfcDate();
void toString_enumformat();
@ -800,11 +802,11 @@ void tst_QDateTime::toString_isoDate_data()
QTest::newRow("positive OffsetFromUTC")
<< dt << Qt::ISODate
<< QString("1978-11-09T13:28:34+05:30");
dt.setUtcOffset(-7200);
dt.setOffsetFromUtc(-7200);
QTest::newRow("negative OffsetFromUTC")
<< dt << Qt::ISODate
<< QString("1978-11-09T13:28:34-02:00");
dt.setUtcOffset(-900);
dt.setOffsetFromUtc(-900);
QTest::newRow("negative non-integral OffsetFromUTC")
<< dt << Qt::ISODate
<< QString("1978-11-09T13:28:34-00:15");
@ -840,7 +842,7 @@ void tst_QDateTime::toString_isoDate()
QCOMPARE(resultDatetime.date(), datetime.date());
QCOMPARE(resultDatetime.time(), datetime.time());
QCOMPARE(resultDatetime.timeSpec(), datetime.timeSpec());
QCOMPARE(resultDatetime.utcOffset(), datetime.utcOffset());
QCOMPARE(resultDatetime.offsetFromUtc(), datetime.offsetFromUtc());
} else {
QCOMPARE(resultDatetime, QDateTime());
}
@ -870,12 +872,14 @@ void tst_QDateTime::toString_isoDate_extra()
#endif // timezone
}
#if QT_CONFIG(datestring)
void tst_QDateTime::toString_textDate_data()
{
QTest::addColumn<QDateTime>("datetime");
QTest::addColumn<QString>("expected");
QString wednesdayJanuary = QDate::shortDayName(3) + ' ' + QDate::shortMonthName(1);
QString wednesdayJanuary = QLocale::system().dayName(3, QLocale::ShortFormat)
+ ' ' + QLocale::system().monthName(1, QLocale::ShortFormat);
QTest::newRow("localtime") << QDateTime(QDate(2013, 1, 2), QTime(1, 2, 3), Qt::LocalTime)
<< wednesdayJanuary + QString(" 2 01:02:03 2013");
@ -904,7 +908,7 @@ void tst_QDateTime::toString_textDate()
QCOMPARE(resultDatetime.date(), datetime.date());
QCOMPARE(resultDatetime.time(), datetime.time());
QCOMPARE(resultDatetime.timeSpec(), datetime.timeSpec());
QCOMPARE(resultDatetime.utcOffset(), datetime.utcOffset());
QCOMPARE(resultDatetime.offsetFromUtc(), datetime.offsetFromUtc());
}
void tst_QDateTime::toString_textDate_extra()
@ -953,6 +957,7 @@ void tst_QDateTime::toString_textDate_extra()
dt = QDateTime::fromMSecsSinceEpoch(0, Qt::UTC);
QVERIFY(dt.toString().endsWith(GMT));
}
#endif // datestring
void tst_QDateTime::toString_rfcDate_data()
{
@ -968,11 +973,11 @@ void tst_QDateTime::toString_rfcDate_data()
<< QDateTime(QDate(1978, 11, 9), QTime(13, 28, 34), Qt::UTC)
<< QString("09 Nov 1978 13:28:34 +0000");
QDateTime dt(QDate(1978, 11, 9), QTime(13, 28, 34));
dt.setUtcOffset(19800);
dt.setOffsetFromUtc(19800);
QTest::newRow("positive OffsetFromUTC")
<< dt
<< QString("09 Nov 1978 13:28:34 +0530");
dt.setUtcOffset(-7200);
dt.setOffsetFromUtc(-7200);
QTest::newRow("negative OffsetFromUTC")
<< dt
<< QString("09 Nov 1978 13:28:34 -0200");

View File

@ -35,11 +35,13 @@
namespace
{
QShaderFormat createFormat(QShaderFormat::Api api, int majorVersion, int minorVersion)
QShaderFormat createFormat(QShaderFormat::Api api, int majorVersion, int minorVersion,
QShaderFormat::ShaderType shaderType= QShaderFormat::Fragment)
{
auto format = QShaderFormat();
format.setApi(api);
format.setVersion(QVersionNumber(majorVersion, minorVersion));
format.setShaderType(shaderType);
return format;
}
@ -74,7 +76,7 @@ namespace
return edge;
}
QShaderGraph createGraph()
QShaderGraph createFragmentShaderGraph()
{
const auto openGLES2 = createFormat(QShaderFormat::OpenGLES, 2, 0);
const auto openGL3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0);
@ -194,6 +196,7 @@ private slots:
void shouldProcessLanguageQualifierAndTypeEnums_data();
void shouldProcessLanguageQualifierAndTypeEnums();
void shouldGenerateDifferentCodeDependingOnActiveLayers();
void shouldUseGlobalVariableRatherThanTemporaries();
};
void tst_QShaderGenerator::shouldHaveDefaultState()
@ -213,7 +216,7 @@ void tst_QShaderGenerator::shouldGenerateShaderCode_data()
QTest::addColumn<QShaderFormat>("format");
QTest::addColumn<QByteArray>("expectedCode");
const auto graph = createGraph();
const auto graph = createFragmentShaderGraph();
const auto openGLES2 = createFormat(QShaderFormat::OpenGLES, 2, 0);
const auto openGL3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0);
@ -234,14 +237,9 @@ void tst_QShaderGenerator::shouldGenerateShaderCode_data()
<< ""
<< "void main()"
<< "{"
<< " highp vec2 v2 = texCoord;"
<< " sampler2D v1 = texture;"
<< " highp float v3 = lightIntensity;"
<< " highp vec4 v5 = texture2D(v1, v2);"
<< " highp vec3 v0 = worldPosition;"
<< " highp float v4 = exposure;"
<< " highp vec4 v6 = lightModel(v5, v0, v3);"
<< " highp vec4 v7 = v6 * pow(2.0, v4);"
<< " highp vec4 v5 = texture2D(texture, texCoord);"
<< " highp vec4 v6 = lightModel(v5, worldPosition, lightIntensity);"
<< " highp vec4 v7 = v6 * pow(2.0, exposure);"
<< " gl_fragColor = v7;"
<< "}"
<< "";
@ -256,14 +254,9 @@ void tst_QShaderGenerator::shouldGenerateShaderCode_data()
<< ""
<< "void main()"
<< "{"
<< " vec2 v2 = texCoord;"
<< " sampler2D v1 = texture;"
<< " float v3 = lightIntensity;"
<< " vec4 v5 = texture2D(v1, v2);"
<< " vec3 v0 = worldPosition;"
<< " float v4 = exposure;"
<< " vec4 v6 = lightModel(v5, v0, v3);"
<< " vec4 v7 = v6 * pow(2.0, v4);"
<< " vec4 v5 = texture2D(texture, texCoord);"
<< " vec4 v6 = lightModel(v5, worldPosition, lightIntensity);"
<< " vec4 v7 = v6 * pow(2.0, exposure);"
<< " fragColor = v7;"
<< "}"
<< "";
@ -580,120 +573,190 @@ void tst_QShaderGenerator::shouldProcessLanguageQualifierAndTypeEnums_data()
QTest::addColumn<QShaderFormat>("format");
QTest::addColumn<QByteArray>("expectedCode");
const auto es2 = createFormat(QShaderFormat::OpenGLES, 2, 0);
const auto es3 = createFormat(QShaderFormat::OpenGLES, 3, 0);
const auto gl2 = createFormat(QShaderFormat::OpenGLNoProfile, 2, 0);
const auto gl3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0);
const auto gl4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0);
{
const auto es2 = createFormat(QShaderFormat::OpenGLES, 2, 0);
const auto es3 = createFormat(QShaderFormat::OpenGLES, 3, 0);
const auto gl2 = createFormat(QShaderFormat::OpenGLNoProfile, 2, 0);
const auto gl3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0);
const auto gl4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0);
const auto qualifierEnum = QMetaEnum::fromType<QShaderLanguage::StorageQualifier>();
const auto typeEnum = QMetaEnum::fromType<QShaderLanguage::VariableType>();
const auto qualifierEnum = QMetaEnum::fromType<QShaderLanguage::StorageQualifier>();
const auto typeEnum = QMetaEnum::fromType<QShaderLanguage::VariableType>();
for (int qualifierIndex = 0; qualifierIndex < qualifierEnum.keyCount(); qualifierIndex++) {
const auto qualifierName = qualifierEnum.key(qualifierIndex);
const auto qualifierValue = static_cast<QShaderLanguage::StorageQualifier>(qualifierEnum.value(qualifierIndex));
for (int qualifierIndex = 0; qualifierIndex < qualifierEnum.keyCount(); qualifierIndex++) {
const auto qualifierName = qualifierEnum.key(qualifierIndex);
const auto qualifierValue = static_cast<QShaderLanguage::StorageQualifier>(qualifierEnum.value(qualifierIndex));
for (int typeIndex = 0; typeIndex < typeEnum.keyCount(); typeIndex++) {
const auto typeName = typeEnum.key(typeIndex);
const auto typeValue = static_cast<QShaderLanguage::VariableType>(typeEnum.value(typeIndex));
for (int typeIndex = 0; typeIndex < typeEnum.keyCount(); typeIndex++) {
const auto typeName = typeEnum.key(typeIndex);
const auto typeValue = static_cast<QShaderLanguage::VariableType>(typeEnum.value(typeIndex));
auto graph = QShaderGraph();
auto worldPosition = createNode({
createPort(QShaderNodePort::Output, "value")
});
worldPosition.setParameter("name", "worldPosition");
worldPosition.setParameter("qualifier", QVariant::fromValue<QShaderLanguage::StorageQualifier>(qualifierValue));
worldPosition.setParameter("type", QVariant::fromValue<QShaderLanguage::VariableType>(typeValue));
worldPosition.addRule(es2, QShaderNode::Rule("highp $type $value = $name;",
QByteArrayList() << "$qualifier highp $type $name;"));
worldPosition.addRule(gl2, QShaderNode::Rule("$type $value = $name;",
QByteArrayList() << "$qualifier $type $name;"));
worldPosition.addRule(gl3, QShaderNode::Rule("$type $value = $name;",
QByteArrayList() << "$qualifier $type $name;"));
auto fragColor = createNode({
createPort(QShaderNodePort::Input, "fragColor")
});
fragColor.addRule(es2, QShaderNode::Rule("gl_fragColor = $fragColor;"));
fragColor.addRule(gl2, QShaderNode::Rule("gl_fragColor = $fragColor;"));
fragColor.addRule(gl3, QShaderNode::Rule("fragColor = $fragColor;",
QByteArrayList() << "out vec4 fragColor;"));
graph.addNode(worldPosition);
graph.addNode(fragColor);
graph.addEdge(createEdge(worldPosition.uuid(), "value", fragColor.uuid(), "fragColor"));
const auto gl2Code = (QByteArrayList() << "#version 110"
<< ""
<< QStringLiteral("%1 %2 worldPosition;").arg(toGlsl(qualifierValue, gl2))
.arg(toGlsl(typeValue))
.toUtf8()
<< ""
<< "void main()"
<< "{"
<< " gl_fragColor = worldPosition;"
<< "}"
<< "").join("\n");
const auto gl3Code = (QByteArrayList() << "#version 130"
<< ""
<< QStringLiteral("%1 %2 worldPosition;").arg(toGlsl(qualifierValue, gl3))
.arg(toGlsl(typeValue))
.toUtf8()
<< "out vec4 fragColor;"
<< ""
<< "void main()"
<< "{"
<< " fragColor = worldPosition;"
<< "}"
<< "").join("\n");
const auto gl4Code = (QByteArrayList() << "#version 400 core"
<< ""
<< QStringLiteral("%1 %2 worldPosition;").arg(toGlsl(qualifierValue, gl4))
.arg(toGlsl(typeValue))
.toUtf8()
<< "out vec4 fragColor;"
<< ""
<< "void main()"
<< "{"
<< " fragColor = worldPosition;"
<< "}"
<< "").join("\n");
const auto es2Code = (QByteArrayList() << "#version 100"
<< ""
<< QStringLiteral("%1 highp %2 worldPosition;").arg(toGlsl(qualifierValue, es2))
.arg(toGlsl(typeValue))
.toUtf8()
<< ""
<< "void main()"
<< "{"
<< " gl_fragColor = worldPosition;"
<< "}"
<< "").join("\n");
const auto es3Code = (QByteArrayList() << "#version 300 es"
<< ""
<< QStringLiteral("%1 highp %2 worldPosition;").arg(toGlsl(qualifierValue, es3))
.arg(toGlsl(typeValue))
.toUtf8()
<< ""
<< "void main()"
<< "{"
<< " gl_fragColor = worldPosition;"
<< "}"
<< "").join("\n");
QTest::addRow("%s %s ES2", qualifierName, typeName) << graph << es2 << es2Code;
QTest::addRow("%s %s ES3", qualifierName, typeName) << graph << es3 << es3Code;
QTest::addRow("%s %s GL2", qualifierName, typeName) << graph << gl2 << gl2Code;
QTest::addRow("%s %s GL3", qualifierName, typeName) << graph << gl3 << gl3Code;
QTest::addRow("%s %s GL4", qualifierName, typeName) << graph << gl4 << gl4Code;
}
}
}
{
const auto es2 = createFormat(QShaderFormat::OpenGLES, 2, 0, QShaderFormat::Vertex);
const auto es3 = createFormat(QShaderFormat::OpenGLES, 3, 0, QShaderFormat::Vertex);
const auto gl2 = createFormat(QShaderFormat::OpenGLNoProfile, 2, 0, QShaderFormat::Vertex);
const auto gl3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, QShaderFormat::Vertex);
const auto gl4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0, QShaderFormat::Vertex);
auto graph = QShaderGraph();
auto worldPosition = createNode({
auto vertexPosition = createNode({
createPort(QShaderNodePort::Output, "value")
});
worldPosition.setParameter("name", "worldPosition");
worldPosition.setParameter("qualifier", QVariant::fromValue<QShaderLanguage::StorageQualifier>(qualifierValue));
worldPosition.setParameter("type", QVariant::fromValue<QShaderLanguage::VariableType>(typeValue));
worldPosition.addRule(es2, QShaderNode::Rule("highp $type $value = $name;",
vertexPosition.setParameter("name", "vertexPosition");
vertexPosition.setParameter("qualifier", QVariant::fromValue<QShaderLanguage::StorageQualifier>(QShaderLanguage::Input));
vertexPosition.setParameter("type", QVariant::fromValue<QShaderLanguage::VariableType>(QShaderLanguage::Vec4));
vertexPosition.addRule(es2, QShaderNode::Rule("",
QByteArrayList() << "$qualifier highp $type $name;"));
worldPosition.addRule(gl2, QShaderNode::Rule("$type $value = $name;",
vertexPosition.addRule(gl2, QShaderNode::Rule("",
QByteArrayList() << "$qualifier $type $name;"));
worldPosition.addRule(gl3, QShaderNode::Rule("$type $value = $name;",
vertexPosition.addRule(gl3, QShaderNode::Rule("",
QByteArrayList() << "$qualifier $type $name;"));
auto fragColor = createNode({
createPort(QShaderNodePort::Input, "fragColor")
});
fragColor.addRule(es2, QShaderNode::Rule("gl_fragColor = $fragColor;"));
fragColor.addRule(gl2, QShaderNode::Rule("gl_fragColor = $fragColor;"));
fragColor.addRule(gl3, QShaderNode::Rule("fragColor = $fragColor;",
QByteArrayList() << "out vec4 fragColor;"));
graph.addNode(worldPosition);
graph.addNode(fragColor);
graph.addEdge(createEdge(worldPosition.uuid(), "value", fragColor.uuid(), "fragColor"));
graph.addNode(vertexPosition);
const auto gl2Code = (QByteArrayList() << "#version 110"
<< ""
<< QStringLiteral("%1 %2 worldPosition;").arg(toGlsl(qualifierValue, gl2))
.arg(toGlsl(typeValue))
.toUtf8()
<< "attribute vec4 vertexPosition;"
<< ""
<< "void main()"
<< "{"
<< QStringLiteral(" %1 v0 = worldPosition;").arg(toGlsl(typeValue)).toUtf8()
<< " gl_fragColor = v0;"
<< "}"
<< "").join("\n");
const auto gl3Code = (QByteArrayList() << "#version 130"
<< ""
<< QStringLiteral("%1 %2 worldPosition;").arg(toGlsl(qualifierValue, gl3))
.arg(toGlsl(typeValue))
.toUtf8()
<< "out vec4 fragColor;"
<< "in vec4 vertexPosition;"
<< ""
<< "void main()"
<< "{"
<< QStringLiteral(" %1 v0 = worldPosition;").arg(toGlsl(typeValue)).toUtf8()
<< " fragColor = v0;"
<< "}"
<< "").join("\n");
const auto gl4Code = (QByteArrayList() << "#version 400 core"
<< ""
<< QStringLiteral("%1 %2 worldPosition;").arg(toGlsl(qualifierValue, gl4))
.arg(toGlsl(typeValue))
.toUtf8()
<< "out vec4 fragColor;"
<< "in vec4 vertexPosition;"
<< ""
<< "void main()"
<< "{"
<< QStringLiteral(" %1 v0 = worldPosition;").arg(toGlsl(typeValue)).toUtf8()
<< " fragColor = v0;"
<< "}"
<< "").join("\n");
const auto es2Code = (QByteArrayList() << "#version 100"
<< ""
<< QStringLiteral("%1 highp %2 worldPosition;").arg(toGlsl(qualifierValue, es2))
.arg(toGlsl(typeValue))
.toUtf8()
<< "attribute highp vec4 vertexPosition;"
<< ""
<< "void main()"
<< "{"
<< QStringLiteral(" highp %1 v0 = worldPosition;").arg(toGlsl(typeValue)).toUtf8()
<< " gl_fragColor = v0;"
<< "}"
<< "").join("\n");
const auto es3Code = (QByteArrayList() << "#version 300 es"
<< ""
<< QStringLiteral("%1 highp %2 worldPosition;").arg(toGlsl(qualifierValue, es3))
.arg(toGlsl(typeValue))
.toUtf8()
<< "in highp vec4 vertexPosition;"
<< ""
<< "void main()"
<< "{"
<< QStringLiteral(" highp %1 v0 = worldPosition;").arg(toGlsl(typeValue)).toUtf8()
<< " gl_fragColor = v0;"
<< "}"
<< "").join("\n");
QTest::addRow("%s %s ES2", qualifierName, typeName) << graph << es2 << es2Code;
QTest::addRow("%s %s ES3", qualifierName, typeName) << graph << es3 << es3Code;
QTest::addRow("%s %s GL2", qualifierName, typeName) << graph << gl2 << gl2Code;
QTest::addRow("%s %s GL3", qualifierName, typeName) << graph << gl3 << gl3Code;
QTest::addRow("%s %s GL4", qualifierName, typeName) << graph << gl4 << gl4Code;
}
QTest::addRow("Attribute header substitution ES2") << graph << es2 << es2Code;
QTest::addRow("Attribute header substitution ES3") << graph << es3 << es3Code;
QTest::addRow("Attribute header substitution GL2") << graph << gl2 << gl2Code;
QTest::addRow("Attribute header substitution GL3") << graph << gl3 << gl3Code;
QTest::addRow("Attribute header substitution GL4") << graph << gl4 << gl4Code;
}
}
@ -806,9 +869,7 @@ void tst_QShaderGenerator::shouldGenerateDifferentCodeDependingOnActiveLayers()
<< ""
<< "void main()"
<< "{"
<< " vec3 v1 = normalUniform;"
<< " vec4 v0 = diffuseUniform;"
<< " vec4 v2 = lightModel(v0, v1);"
<< " vec4 v2 = lightModel(diffuseUniform, normalUniform);"
<< " fragColor = v2;"
<< "}"
<< "";
@ -831,10 +892,8 @@ void tst_QShaderGenerator::shouldGenerateDifferentCodeDependingOnActiveLayers()
<< ""
<< "void main()"
<< "{"
<< " vec2 v0 = texCoord;"
<< " vec3 v2 = texture2D(normalTexture, v0).rgb;"
<< " vec4 v1 = diffuseUniform;"
<< " vec4 v3 = lightModel(v1, v2);"
<< " vec3 v2 = texture2D(normalTexture, texCoord).rgb;"
<< " vec4 v3 = lightModel(diffuseUniform, v2);"
<< " fragColor = v3;"
<< "}"
<< "";
@ -857,10 +916,8 @@ void tst_QShaderGenerator::shouldGenerateDifferentCodeDependingOnActiveLayers()
<< ""
<< "void main()"
<< "{"
<< " vec2 v0 = texCoord;"
<< " vec3 v2 = normalUniform;"
<< " vec4 v1 = texture2D(diffuseTexture, v0);"
<< " vec4 v3 = lightModel(v1, v2);"
<< " vec4 v1 = texture2D(diffuseTexture, texCoord);"
<< " vec4 v3 = lightModel(v1, normalUniform);"
<< " fragColor = v3;"
<< "}"
<< "";
@ -883,9 +940,8 @@ void tst_QShaderGenerator::shouldGenerateDifferentCodeDependingOnActiveLayers()
<< ""
<< "void main()"
<< "{"
<< " vec2 v0 = texCoord;"
<< " vec3 v2 = texture2D(normalTexture, v0).rgb;"
<< " vec4 v1 = texture2D(diffuseTexture, v0);"
<< " vec3 v2 = texture2D(normalTexture, texCoord).rgb;"
<< " vec4 v1 = texture2D(diffuseTexture, texCoord);"
<< " vec4 v3 = lightModel(v1, v2);"
<< " fragColor = v3;"
<< "}"
@ -894,6 +950,133 @@ void tst_QShaderGenerator::shouldGenerateDifferentCodeDependingOnActiveLayers()
}
}
void tst_QShaderGenerator::shouldUseGlobalVariableRatherThanTemporaries()
{
// GIVEN
const auto gl4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0);
{
// WHEN
auto vertexPosition = createNode({
createPort(QShaderNodePort::Output, "vertexPosition")
});
vertexPosition.addRule(gl4, QShaderNode::Rule("vec4 $vertexPosition = vertexPosition;",
QByteArrayList() << "in vec4 vertexPosition;"));
auto fakeMultiPlyNoSpace = createNode({
createPort(QShaderNodePort::Input, "varName"),
createPort(QShaderNodePort::Output, "out")
});
fakeMultiPlyNoSpace.addRule(gl4, QShaderNode::Rule("vec4 $out = $varName*v11;"));
auto fakeMultiPlySpace = createNode({
createPort(QShaderNodePort::Input, "varName"),
createPort(QShaderNodePort::Output, "out")
});
fakeMultiPlySpace.addRule(gl4, QShaderNode::Rule("vec4 $out = $varName * v11;"));
auto fakeJoinNoSpace = createNode({
createPort(QShaderNodePort::Input, "varName"),
createPort(QShaderNodePort::Output, "out")
});
fakeJoinNoSpace.addRule(gl4, QShaderNode::Rule("vec4 $out = vec4($varName.xyz,$varName.w);"));
auto fakeJoinSpace = createNode({
createPort(QShaderNodePort::Input, "varName"),
createPort(QShaderNodePort::Output, "out")
});
fakeJoinSpace.addRule(gl4, QShaderNode::Rule("vec4 $out = vec4($varName.xyz, $varName.w);"));
auto fakeAdd = createNode({
createPort(QShaderNodePort::Input, "varName"),
createPort(QShaderNodePort::Output, "out")
});
fakeAdd.addRule(gl4, QShaderNode::Rule("vec4 $out = $varName.xyzw + $varName;"));
auto fakeSub = createNode({
createPort(QShaderNodePort::Input, "varName"),
createPort(QShaderNodePort::Output, "out")
});
fakeSub.addRule(gl4, QShaderNode::Rule("vec4 $out = $varName.xyzw - $varName;"));
auto fakeDiv = createNode({
createPort(QShaderNodePort::Input, "varName"),
createPort(QShaderNodePort::Output, "out")
});
fakeDiv.addRule(gl4, QShaderNode::Rule("vec4 $out = $varName / v0;"));
auto fragColor = createNode({
createPort(QShaderNodePort::Input, "input1"),
createPort(QShaderNodePort::Input, "input2"),
createPort(QShaderNodePort::Input, "input3"),
createPort(QShaderNodePort::Input, "input4"),
createPort(QShaderNodePort::Input, "input5"),
createPort(QShaderNodePort::Input, "input6"),
createPort(QShaderNodePort::Input, "input7")
});
fragColor.addRule(gl4, QShaderNode::Rule("fragColor = $input1 + $input2 + $input3 + $input4 + $input5 + $input6 + $input7;",
QByteArrayList() << "out vec4 fragColor;"));
const auto graph = [=] {
auto res = QShaderGraph();
res.addNode(vertexPosition);
res.addNode(fakeMultiPlyNoSpace);
res.addNode(fakeMultiPlySpace);
res.addNode(fakeJoinNoSpace);
res.addNode(fakeJoinSpace);
res.addNode(fakeAdd);
res.addNode(fakeSub);
res.addNode(fakeDiv);
res.addNode(fragColor);
res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeMultiPlyNoSpace.uuid(), "varName"));
res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeMultiPlySpace.uuid(), "varName"));
res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeJoinNoSpace.uuid(), "varName"));
res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeJoinSpace.uuid(), "varName"));
res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeAdd.uuid(), "varName"));
res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeSub.uuid(), "varName"));
res.addEdge(createEdge(vertexPosition.uuid(), "vertexPosition", fakeDiv.uuid(), "varName"));
res.addEdge(createEdge(fakeMultiPlyNoSpace.uuid(), "out", fragColor.uuid(), "input1"));
res.addEdge(createEdge(fakeMultiPlySpace.uuid(), "out", fragColor.uuid(), "input2"));
res.addEdge(createEdge(fakeJoinNoSpace.uuid(), "out", fragColor.uuid(), "input3"));
res.addEdge(createEdge(fakeJoinSpace.uuid(), "out", fragColor.uuid(), "input4"));
res.addEdge(createEdge(fakeAdd.uuid(), "out", fragColor.uuid(), "input5"));
res.addEdge(createEdge(fakeSub.uuid(), "out", fragColor.uuid(), "input6"));
res.addEdge(createEdge(fakeDiv.uuid(), "out", fragColor.uuid(), "input7"));
return res;
}();
auto generator = QShaderGenerator();
generator.graph = graph;
generator.format = gl4;
const auto code = generator.createShaderCode({"diffuseUniform", "normalUniform"});
// THEN
const auto expected = QByteArrayList()
<< "#version 400 core"
<< ""
<< "in vec4 vertexPosition;"
<< "out vec4 fragColor;"
<< ""
<< "void main()"
<< "{"
<< " vec4 v7 = vertexPosition / vertexPosition;"
<< " vec4 v6 = vertexPosition.xyzw - vertexPosition;"
<< " vec4 v5 = vertexPosition.xyzw + vertexPosition;"
<< " vec4 v4 = vec4(vertexPosition.xyz, vertexPosition.w);"
<< " vec4 v3 = vec4(vertexPosition.xyz,vertexPosition.w);"
<< " vec4 v2 = vertexPosition * v11;"
<< " vec4 v1 = vertexPosition*v11;"
<< " fragColor = v1 + v2 + v3 + v4 + v5 + v6 + v7;"
<< "}"
<< "";
QCOMPARE(code, expected.join("\n"));
}
}
QTEST_MAIN(tst_QShaderGenerator)
#include "tst_qshadergenerator.moc"

View File

@ -248,6 +248,7 @@ private slots:
void sizeHintCrash();
void testResetCachedSizeHint();
void statusTips();
void testRemovingColumnsViaLayoutChanged();
protected:
void setupTestData(bool use_reset_model = false);
@ -353,6 +354,7 @@ public:
void cleanup()
{
emit layoutAboutToBeChanged();
cols = 3;
rows = 3;
emit layoutChanged();
@ -3489,5 +3491,20 @@ void tst_QHeaderView::statusTips()
QCOMPARE(headerView.statusTipText, QLatin1String("[0,1,0] -- Header"));
}
void tst_QHeaderView::testRemovingColumnsViaLayoutChanged()
{
const int persistentSectionSize = 101;
QtTestModel model;
model.rows = model.cols = 5;
view->setModel(&model);
for (int i = 0; i < model.cols; ++i)
view->resizeSection(i, persistentSectionSize + i);
model.cleanup(); // down to 3 via layoutChanged (not columnsRemoved)
for (int j = 0; j < model.cols; ++j)
QCOMPARE(view->sectionSize(j), persistentSectionSize + j);
// The main point of this test is that the section-size restoring code didn't go out of bounds.
}
QTEST_MAIN(tst_QHeaderView)
#include "tst_qheaderview.moc"

View File

@ -267,6 +267,7 @@ tst_QListWidget::tst_QListWidget(): testWidget(0), rcParent(8), rcFirst(8,0), rc
void tst_QListWidget::initTestCase()
{
qRegisterMetaType<QListWidgetItem*>("QListWidgetItem*");
testWidget = new QListWidget();
testWidget->show();
@ -663,6 +664,9 @@ void tst_QListWidget::insertItems()
QFETCH(int, rowCount);
QFETCH(int, insertType);
QSignalSpy itemChangedSpy(testWidget, &QListWidget::itemChanged);
QSignalSpy dataChangedSpy(testWidget->model(), &QAbstractItemModel::dataChanged);
if (insertType == 3) {
QStringList strings;
for (int i=0; i<rowCount; ++i)
@ -700,6 +704,9 @@ void tst_QListWidget::insertItems()
// make sure all items have view set correctly
for (int i=0; i<testWidget->count(); ++i)
QCOMPARE(testWidget->item(i)->listWidget(), testWidget);
QCOMPARE(itemChangedSpy.count(), 0);
QCOMPARE(dataChangedSpy.count(), 0);
}
void tst_QListWidget::itemAssignment()
@ -1257,7 +1264,6 @@ void tst_QListWidget::setData()
QFETCH(IntList, roles);
QFETCH(QVariantList, values);
QFETCH(int, expectedSignalCount);
qRegisterMetaType<QListWidgetItem *>("QListWidgetItem*");
QCOMPARE(roles.count(), values.count());
@ -1715,7 +1721,6 @@ void tst_QListWidget::task258949_keypressHangup()
void tst_QListWidget::QTBUG8086_currentItemChangedOnClick()
{
qRegisterMetaType<QListWidgetItem*>("QListWidgetItem*");
QWidget win;
QHBoxLayout layout(&win);
QListWidget list;
@ -1837,7 +1842,6 @@ void tst_QListWidget::mimeData()
void tst_QListWidget::QTBUG50891_ensureSelectionModelSignalConnectionsAreSet()
{
qRegisterMetaType<QListWidgetItem*>("QListWidgetItem*");
QListWidget list;
for (int i = 0 ; i < 4; ++i)
new QListWidgetItem(QString::number(i), &list);

View File

@ -46,3 +46,6 @@ osx
osx-10.12 ci
[multipleToplevelFocusCheck]
linux
[windowState]
# QTBUG-75270
winrt

View File

@ -48,6 +48,7 @@ public:
private slots:
void init();
void repolish();
void repolish_without_crashing();
void numinstances();
void widgetsBeforeAppStyleSheet();
void widgetsAfterAppStyleSheet();
@ -367,6 +368,26 @@ void tst_QStyleSheetStyle::repolish()
QCOMPARE(BACKGROUND(p1), APPBACKGROUND(p1));
}
void tst_QStyleSheetStyle::repolish_without_crashing()
{
// This used to crash, QTBUG-69204
QMainWindow w;
QScopedPointer<QSplitter> splitter1(new QSplitter(w.centralWidget()));
QScopedPointer<QSplitter> splitter2(new QSplitter);
QScopedPointer<QSplitter> splitter3(new QSplitter);
splitter2->addWidget(splitter3.data());
splitter2->setStyleSheet("color: red");
QScopedPointer<QLabel> label(new QLabel);
label->setTextFormat(Qt::RichText);
splitter3->addWidget(label.data());
label->setText("hey");
splitter1->addWidget(splitter2.data());
w.show();
QCOMPARE(COLOR(*label), QColor(Qt::red));
}
void tst_QStyleSheetStyle::widgetStyle()
{
qApp->setStyleSheet(QString());

View File

@ -90,15 +90,15 @@ int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
if (argc < 3) {
printf("\nusage: %s inputFile outputFile\n\n", argv[0]);
printf("\nUsage: ./%s inputFile outputFile\n\n", argv[0]);
printf("'inputFile' should be a list of effective TLDs, one per line,\n");
printf("as obtained from http://publicsuffix.org . To create indices and data file\n");
printf("as obtained from http://publicsuffix.org/. To create indices and data\n");
printf("file, do the following:\n\n");
printf(" wget https://publicsuffix.org/list/effective_tld_names.dat -O effective_tld_names.dat\n");
printf(" grep '^[^\\/\\/]' effective_tld_names.dat > effective_tld_names.dat.trimmed\n");
printf(" %s effective_tld_names.dat.trimmed effective_tld_names.dat.qt\n\n", argv[0]);
printf("Now copy the data from effective_tld_names.dat.qt to the file src/corelib/io/qurltlds_p.h in your Qt repo\n\n");
exit(1);
printf(" wget https://publicsuffix.org/list/public_suffix_list.dat -O public_suffix_list.dat\n");
printf(" grep -v '^//' public_suffix_list.dat | grep . > public_suffix_list.dat.trimmed\n");
printf(" ./%s public_suffix_list.dat.trimmed public_suffix_list.cpp\n\n", argv[0]);
printf("Now replace the code in qtbase/src/corelib/io/qurltlds_p.h with public_suffix_list.cpp's contents\n\n");
return 1;
}
QFile file(argv[1]);
if (!file.open(QIODevice::ReadOnly)) {