diff options
53 files changed, 556 insertions, 398 deletions
diff --git a/config_help.txt b/config_help.txt index e47fc9adb7..94471d27cf 100644 --- a/config_help.txt +++ b/config_help.txt @@ -281,6 +281,7 @@ Gui, printing, widget options: es2 (default on Windows), desktop (default on Unix), dynamic (Windows only) -opengles3 ........... Enable OpenGL ES 3.x support instead of ES 2.x [auto] + -egl ................. Enable EGL support [auto] -angle ............... Use bundled ANGLE to support OpenGL ES 2.0 [auto] (Windows only) -combined-angle-lib .. Merge LibEGL and LibGLESv2 into LibANGLE (Windows only) diff --git a/configure.pri b/configure.pri index ecd46b8e38..e26b557705 100644 --- a/configure.pri +++ b/configure.pri @@ -843,9 +843,6 @@ defineTest(qtConfOutput_preparePaths) { addConfStr($$[QMAKE_SPEC]) $${currentConfig}.output.qconfigSource = \ - "/* Installation date */" \ - "static const char qt_configure_installation [12+11] = \"qt_instdate=2012-12-20\";" \ - "" \ "/* Installation Info */" \ "static const char qt_configure_prefix_path_str [12+256] = \"qt_prfxpath=$$config.input.prefix\";" \ "$${LITERAL_HASH}ifdef QT_BUILD_QMAKE" \ diff --git a/mkspecs/features/mac/default_post.prf b/mkspecs/features/mac/default_post.prf index 60b2eb2117..26bd3e2e98 100644 --- a/mkspecs/features/mac/default_post.prf +++ b/mkspecs/features/mac/default_post.prf @@ -270,7 +270,7 @@ xcode_product_bundle_identifier_setting.value = "$${xcode_product_bundle_identif QMAKE_MAC_XCODE_SETTINGS += xcode_product_bundle_identifier_setting !macx-xcode { - generate_xcode_project.commands = @$(QMAKE) -spec macx-xcode $(EXPORT__PRO_FILE_) $$QMAKE_ARGS + generate_xcode_project.commands = @$(QMAKE) -spec macx-xcode \"$(EXPORT__PRO_FILE_)\" $$QMAKE_ARGS generate_xcode_project.target = xcodeproj QMAKE_EXTRA_VARIABLES += _PRO_FILE_ QMAKE_EXTRA_TARGETS += generate_xcode_project diff --git a/mkspecs/features/uikit/gc_binaries.prf b/mkspecs/features/uikit/gc_binaries.prf index c4f7445951..aa27e69054 100644 --- a/mkspecs/features/uikit/gc_binaries.prf +++ b/mkspecs/features/uikit/gc_binaries.prf @@ -1,2 +1,6 @@ # bitcode (release mode) is incompatible with splitting sections. -!bitcode|!release: load(gc_binaries) +# We have to explicitly exclude Xcode, as that supports both debug +# and release builds in the same project. Xcode already has a settting +# for dead code stripping which is enabled by default, so we'll still +# strip any libraries build with split sections. +!bitcode|if(!macx-xcode:!release): load(gc_binaries) diff --git a/mkspecs/features/wasm/wasm.prf b/mkspecs/features/wasm/wasm.prf index 54d351bfd5..25413d7470 100644 --- a/mkspecs/features/wasm/wasm.prf +++ b/mkspecs/features/wasm/wasm.prf @@ -6,16 +6,6 @@ exists($$QMAKE_QT_CONFIG) { qtConfig(thread) { EMCC_THREAD_LFLAGS += -s USE_PTHREADS=1 - # Hardcode wasm memory size. Emscripten does not currently support memory growth - # (ALLOW_MEMORY_GROWTH) in pthreads mode, and requires specifying the memory size - # at build time. Further, browsers limit the maximum initial memory size to 1GB. - TOTAL_MEMORY = 1GB - !isEmpty(QMAKE_WASM_TOTAL_MEMORY) { - TOTAL_MEMORY = $$QMAKE_WASM_TOTAL_MEMORY - } - - message("Setting TOTAL_MEMORY to" $$TOTAL_MEMORY) - EMCC_THREAD_LFLAGS += -s TOTAL_MEMORY=$$TOTAL_MEMORY # Create worker threads at startup. This is supposed to be an optimization, # however exceeding the pool size has been obesverved to hang the application. @@ -29,6 +19,20 @@ exists($$QMAKE_QT_CONFIG) { } else { EMCC_THREAD_LFLAGS += -s ALLOW_MEMORY_GROWTH=1 } + + qtConfig(thread) | !isEmpty(QMAKE_WASM_TOTAL_MEMORY) { + + # Hardcode wasm memory size. Emscripten does not currently support memory growth + # (ALLOW_MEMORY_GROWTH) in pthreads mode, and requires specifying the memory size + # at build time. Further, browsers limit the maximum initial memory size to 1GB. + # QMAKE_WASM_TOTAL_MEMORY must be a multiple of 64KB + TOTAL_MEMORY = 1GB + !isEmpty(QMAKE_WASM_TOTAL_MEMORY) { + TOTAL_MEMORY = $$QMAKE_WASM_TOTAL_MEMORY + } + message("Setting TOTAL_MEMORY to" $$TOTAL_MEMORY) + EMCC_THREAD_LFLAGS += -s TOTAL_MEMORY=$$TOTAL_MEMORY + } QMAKE_LFLAGS += $$EMCC_THREAD_LFLAGS QMAKE_LFLAGS_DEBUG += $$EMCC_THREAD_LFLAGS QMAKE_CFLAGS += $$EMCC_THREAD_LFLAGS diff --git a/qmake/generators/projectgenerator.cpp b/qmake/generators/projectgenerator.cpp index c43f6b4e4a..613c97fb85 100644 --- a/qmake/generators/projectgenerator.cpp +++ b/qmake/generators/projectgenerator.cpp @@ -36,7 +36,7 @@ QT_BEGIN_NAMESPACE -QString project_builtin_regx() //calculate the builtin regular expression.. +static QString project_builtin_regx() //calculate the builtin regular expression.. { QString ret; QStringList builtin_exts; diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp index b6fe683d2c..8129bd76be 100644 --- a/qmake/generators/win32/msvc_objectmodel.cpp +++ b/qmake/generators/win32/msvc_objectmodel.cpp @@ -1568,21 +1568,12 @@ bool VCLinkerTool::parseOption(const char* option) const char* str = option+6; if (*str == 'S') ShowProgress = linkProgressAll; -#ifndef Q_OS_WIN - else if (strncasecmp(str, "pginstrument", 12)) + else if (qstricmp(str, "pginstrument") == 0) LinkTimeCodeGeneration = optLTCGInstrument; - else if (strncasecmp(str, "pgoptimize", 10)) + else if (qstricmp(str, "pgoptimize") == 0) LinkTimeCodeGeneration = optLTCGOptimize; - else if (strncasecmp(str, "pgupdate", 8 )) + else if (qstricmp(str, "pgupdate") == 0) LinkTimeCodeGeneration = optLTCGUpdate; -#else - else if (_stricmp(str, "pginstrument")) - LinkTimeCodeGeneration = optLTCGInstrument; - else if (_stricmp(str, "pgoptimize")) - LinkTimeCodeGeneration = optLTCGOptimize; - else if (_stricmp(str, "pgupdate")) - LinkTimeCodeGeneration = optLTCGUpdate; -#endif } } else { AdditionalOptions.append(option); diff --git a/qmake/main.cpp b/qmake/main.cpp index a598296898..dd1cca9633 100644 --- a/qmake/main.cpp +++ b/qmake/main.cpp @@ -242,6 +242,39 @@ static int doLink(int argc, char **argv) #endif +static bool setFilePermissions(QFile &file, QFileDevice::Permissions permissions) +{ + if (file.setPermissions(permissions)) + return true; + fprintf(stderr, "Error setting permissions on %s: %s\n", + qPrintable(file.fileName()), qPrintable(file.errorString())); + return false; +} + +static bool copyFileTimes(QFile &targetFile, const QString &sourceFilePath, + bool mustEnsureWritability, QString *errorString) +{ +#ifdef Q_OS_WIN + bool mustRestorePermissions = false; + QFileDevice::Permissions targetPermissions; + if (mustEnsureWritability) { + targetPermissions = targetFile.permissions(); + if (!targetPermissions.testFlag(QFileDevice::WriteUser)) { + mustRestorePermissions = true; + if (!setFilePermissions(targetFile, targetPermissions | QFileDevice::WriteUser)) + return false; + } + } +#endif + if (!IoUtils::touchFile(targetFile.fileName(), sourceFilePath, errorString)) + return false; +#ifdef Q_OS_WIN + if (mustRestorePermissions && !setFilePermissions(targetFile, targetPermissions)) + return false; +#endif + return true; +} + static int installFile(const QString &source, const QString &target, bool exe = false, bool preservePermissions = false) { @@ -270,18 +303,15 @@ static int installFile(const QString &source, const QString &target, bool exe = targetPermissions |= QFileDevice::ExeOwner | QFileDevice::ExeUser | QFileDevice::ExeGroup | QFileDevice::ExeOther; } - if (!targetFile.setPermissions(targetPermissions)) { - fprintf(stderr, "Error setting permissions on %s: %s\n", - qPrintable(target), qPrintable(targetFile.errorString())); + if (!setFilePermissions(targetFile, targetPermissions)) return 3; - } - // Copy file times QString error; - if (!IoUtils::touchFile(target, sourceFile.fileName(), &error)) { + if (!copyFileTimes(targetFile, sourceFile.fileName(), preservePermissions, &error)) { fprintf(stderr, "%s", qPrintable(error)); return 3; } + return 0; } diff --git a/qmake/option.cpp b/qmake/option.cpp index 1e31ecd6b7..d8143468e6 100644 --- a/qmake/option.cpp +++ b/qmake/option.cpp @@ -121,7 +121,6 @@ static QString detectProjectFile(const QString &path) return ret; } -QString project_builtin_regx(); bool usage(const char *a0) { fprintf(stdout, "Usage: %s [mode] [options] [files]\n" @@ -133,9 +132,9 @@ bool usage(const char *a0) "\n" "Mode:\n" " -project Put qmake into project file generation mode%s\n" - " In this mode qmake interprets files as files to\n" - " be built,\n" - " defaults to %s\n" + " In this mode qmake interprets [files] as files to\n" + " be added to the .pro file. By default, all files with\n" + " known source extensions are added.\n" " Note: The created .pro file probably will \n" " need to be edited. For example add the QT variable to \n" " specify what modules are required.\n" @@ -183,7 +182,7 @@ bool usage(const char *a0) " -nomoc Don't generate moc targets [makefile mode only]\n" " -nopwd Don't look for files in pwd [project mode only]\n" ,a0, - default_mode(a0) == Option::QMAKE_GENERATE_PROJECT ? " (default)" : "", project_builtin_regx().toLatin1().constData(), + default_mode(a0) == Option::QMAKE_GENERATE_PROJECT ? " (default)" : "", default_mode(a0) == Option::QMAKE_GENERATE_MAKEFILE ? " (default)" : "" ); return false; diff --git a/src/corelib/codecs/qicucodec.cpp b/src/corelib/codecs/qicucodec.cpp index b9f1a814fa..5a778c2638 100644 --- a/src/corelib/codecs/qicucodec.cpp +++ b/src/corelib/codecs/qicucodec.cpp @@ -42,16 +42,17 @@ #include "qtextcodec_p.h" #include "qutfcodec_p.h" #include "qlatincodec_p.h" -#if QT_CONFIG(codecs) -#include "qtsciicodec_p.h" -#include "qisciicodec_p.h" -#endif #include "qsimplecodec_p.h" #include "private/qcoreglobaldata_p.h" #include "qdebug.h" #include "unicode/ucnv.h" +#if QT_CONFIG(codecs) +#include "qtsciicodec_p.h" +#include "qisciicodec_p.h" +#endif + QT_BEGIN_NAMESPACE typedef QList<QTextCodec*>::ConstIterator TextCodecListConstIt; diff --git a/src/corelib/configure.json b/src/corelib/configure.json index 3febb59480..f7b6d41534 100644 --- a/src/corelib/configure.json +++ b/src/corelib/configure.json @@ -884,7 +884,7 @@ }, "datestring": { "label": "QDate/QTime/QDateTime", - "purpose": "Provides convertion between dates and strings.", + "purpose": "Provides conversion between dates and strings.", "section": "Data structures", "condition": "features.textdate", "output": [ "publicFeature", "feature" ] diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index 2b271ef5be..4c1b04f05e 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -274,7 +274,7 @@ QLibraryInfo::licensedProducts() QDate QLibraryInfo::buildDate() { - return QDate::fromString(QString::fromLatin1(qt_configure_installation + 12), Qt::ISODate); + return QDate::fromString(QString::fromLatin1("2012-12-20"), Qt::ISODate); } #endif #endif // datestring diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index 491823f217..cebab1daef 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -1910,12 +1910,14 @@ void qErrnoWarning(const char *msg, ...) { // qt_error_string() will allocate anyway, so we don't have // to be careful here (like we do in plain qWarning()) + QString error_string = qt_error_string(-1); // before vasprintf changes errno/GetLastError() + va_list ap; va_start(ap, msg); QString buf = QString::vasprintf(msg, ap); va_end(ap); - buf += QLatin1String(" (") + qt_error_string(-1) + QLatin1Char(')'); + buf += QLatin1String(" (") + error_string + QLatin1Char(')'); QMessageLogContext context; qt_message_output(QtCriticalMsg, context, buf); } diff --git a/src/corelib/io/qloggingcategory.cpp b/src/corelib/io/qloggingcategory.cpp index f6ff56c83c..4d4784cdf7 100644 --- a/src/corelib/io/qloggingcategory.cpp +++ b/src/corelib/io/qloggingcategory.cpp @@ -70,14 +70,16 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift) QLoggingCategory represents a certain logging category - identified by a string - at runtime. A category can be configured to enable or disable - logging of messages per message type. Whether a message type is enabled or - not can be checked with the \l isDebugEnabled(), \l isInfoEnabled(), - \l isWarningEnabled(), and \l isCriticalEnabled() methods. - - All objects are meant to be configured by a common registry (see also - \l{Configuring Categories}). Different objects can also represent the same - category. It is therefore not recommended to export objects across module - boundaries, nor to manipulate the objects directly, nor to inherit from + logging of messages per message type. + + To check whether a message type is enabled or not, use one of these methods: + \l isDebugEnabled(), \l isInfoEnabled(), \l isWarningEnabled(), and + \l isCriticalEnabled(). + + All objects are meant to be configured by a common registry, as described in + \l{Configuring Categories}. Different objects can also represent the same + category. Therefore, it's \b{not} recommended to export objects across + module boundaries, to manipulate the objects directly, or to inherit from QLoggingCategory. \section1 Creating Category Objects @@ -87,17 +89,17 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift) \snippet qloggingcategory/main.cpp 1 - \note Category names are free text. However, to allow easy configuration - of the categories using \l{Logging Rules} the names should follow some rules: + Category names are free text; to configure categories using \l{Logging Rules}, their + names should follow this convention: \list \li Use letters and numbers only. - \li Further structure categories into common areas by using dots. - \li Avoid the category names \c{debug}, \c{info}, \c{warning}, and \c{critical}. - \li Category names starting with \c{qt} are reserved for Qt modules. + \li Use dots to further structure categories into common areas. + \li Avoid the category names: \c{debug}, \c{info}, \c{warning}, and \c{critical}. + \li Category names with the \c{qt} prefix are solely reserved for Qt modules. \endlist - QLoggingCategory objects implicitly defined by Q_LOGGING_CATEGORY() - are created on first use in a thread-safe manner. + QLoggingCategory objects that are implicitly defined by Q_LOGGING_CATEGORY() + are created on first use, in a thread-safe manner. \section1 Checking Category Configuration @@ -105,8 +107,8 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift) \l isWarningEnabled(), \l isCriticalEnabled(), as well as \l isEnabled() to check whether messages for the given message type should be logged. - \note The qCDebug(), qCWarning(), qCCritical() macros prevent arguments - from being evaluated if the respective message types are not enabled for the + The qCDebug(), qCWarning(), and qCCritical() macros prevent arguments from + being evaluated if the respective message types are not enabled for the category, so explicit checking is not needed: \snippet qloggingcategory/main.cpp 4 @@ -119,28 +121,27 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift) \snippet qloggingcategory/main.cpp 5 - will log messages of type \c QtWarningMsg, \c QtCriticalMsg, \c QtFatalMsg, but will - ignore messages of type \c QtDebugMsg and \c QtInfoMsg. + logs messages of type \c QtWarningMsg, \c QtCriticalMsg, \c QtFatalMsg, but + ignores messages of type \c QtDebugMsg and \c QtInfoMsg. - If no argument is passed, all messages will be logged. + If no argument is passed, all messages are logged. \section1 Configuring Categories - The default configuration of categories can be overridden either by setting logging - rules, or by installing a custom filter. + You can override the default configuration for categories either by setting + logging rules, or by installing a custom filter. \section2 Logging Rules - Logging rules allow logging for categories to be enabled or disabled in a - flexible way. Rules are specified in text, where every line must have the - format + Logging rules let you enable or disable logging for categories in a flexible + way. Rules are specified in text, where every line must have the format: \snippet code/src_corelib_io_qloggingcategory.cpp 0 \c <category> is the name of the category, potentially with \c{*} as a - wildcard symbol as the first or last character (or at both positions). - The optional \c <type> must be either \c debug, \c info, \c warning, or \c critical. - Lines that do not fit this scheme are ignored. + wildcard symbol for the first or last character; or at both positions. + The optional \c <type> must be \c debug, \c info, \c warning, or \c critical. + Lines that don't fit this scheme are ignored. Rules are evaluated in text order, from first to last. That is, if two rules apply to a category/type, the rule that comes later is applied. @@ -149,47 +150,37 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift) \snippet code/src_corelib_io_qloggingcategory.cpp 1 - Since Qt 5.3, logging rules are also - automatically loaded from the \c [Rules] section of a logging - configuration file. Such configuration files are looked up in the QtProject - configuration directory, or explicitly set in a \c QT_LOGGING_CONF - environment variable: + Logging rules are automatically loaded from the \c [Rules] section in a logging + configuration file. These configuration files are looked up in the QtProject + configuration directory, or explicitly set in a \c QT_LOGGING_CONF environment + variable: \snippet code/src_corelib_io_qloggingcategory.cpp 2 - Since Qt 5.3, logging rules can also be specified in a \c QT_LOGGING_RULES - environment variable. And since Qt 5.6, multiple rules can also be - separated by semicolons: + Logging rules can also be specified in a \c QT_LOGGING_RULES environment variable; + multiple rules can also be separated by semicolons: \snippet code/src_corelib_io_qloggingcategory.cpp 3 - Rules set by \l setFilterRules() take precedence over rules specified - in the QtProject configuration directory, and can, in turn, be - overwritten by rules from the configuration file specified by - \c QT_LOGGING_CONF, and rules set by \c QT_LOGGING_RULES. - - Order of evaluation: - \list - \li [QLibraryInfo::DataPath]/qtlogging.ini - \li QtProject/qtlogging.ini - \li \l setFilterRules() - \li \c QT_LOGGING_CONF - \li \c QT_LOGGING_RULES + Rules set by \l setFilterRules() take precedence over rules specified in the + QtProject configuration directory. In turn, these rules can be overwritten by those + from the configuration file specified by \c QT_LOGGING_CONF, and those set by + \c QT_LOGGING_RULES. + + The order of evaluation is as follows: + \list 1 + \li [QLibraryInfo::DataPath]/qtlogging.ini + \li QtProject/qtlogging.ini + \li \l setFilterRules() + \li \c QT_LOGGING_CONF + \li \c QT_LOGGING_RULES \endlist The \c QtProject/qtlogging.ini file is looked up in all directories returned - by QStandardPaths::GenericConfigLocation, e.g. + by QStandardPaths::GenericConfigLocation. - \list - \li on \macos and iOS: \c ~/Library/Preferences - \li on Unix: \c ~/.config, \c /etc/xdg - \li on Windows: \c %LOCALAPPDATA%, \c %ProgramData%, - \l QCoreApplication::applicationDirPath(), - QCoreApplication::applicationDirPath() + \c "/data" - \endlist - - Set the \c QT_LOGGING_DEBUG environment variable to see from where - logging rules are loaded. + Set the \c QT_LOGGING_DEBUG environment variable to find out where you logging + rules are loaded from. \section2 Installing a Custom Filter @@ -211,7 +202,7 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift) If \a category is \c{0}, the category name is changed to \c "default". - Note that \a category must be kept valid during the lifetime of this object. + \note \a category must be kept valid during the lifetime of this object. */ QLoggingCategory::QLoggingCategory(const char *category) : d(nullptr), @@ -226,7 +217,7 @@ QLoggingCategory::QLoggingCategory(const char *category) If \a category is \c{0}, the category name is changed to \c "default". - Note that \a category must be kept valid during the lifetime of this object. + \note \a category must be kept valid during the lifetime of this object. \since 5.4 */ @@ -251,7 +242,7 @@ void QLoggingCategory::init(const char *category, QtMsgType severityLevel) } /*! - Destructs a QLoggingCategory object. + Destroys a QLoggingCategory object. */ QLoggingCategory::~QLoggingCategory() { @@ -268,24 +259,24 @@ QLoggingCategory::~QLoggingCategory() /*! \fn bool QLoggingCategory::isDebugEnabled() const - Returns \c true if debug messages should be shown for this category. - Returns \c false otherwise. + Returns \c true if debug messages should be shown for this category; + \c false otherwise. - \note The \l qCDebug() macro already does this check before executing any - code. However, calling this method may be useful to avoid - expensive generation of data that is only used for debug output. + \note The \l qCDebug() macro already does this check before running any + code. However, calling this method may be useful to avoid the + expensive generation of data for debug output only. */ /*! \fn bool QLoggingCategory::isInfoEnabled() const - Returns \c true if informational messages should be shown for this category. - Returns \c false otherwise. + Returns \c true if informational messages should be shown for this category; + \c false otherwise. \note The \l qCInfo() macro already does this check before executing any - code. However, calling this method may be useful to avoid - expensive generation of data that is only used for debug output. + code. However, calling this method may be useful to avoid the + expensive generation of data for debug output only. \since 5.5 */ @@ -294,28 +285,28 @@ QLoggingCategory::~QLoggingCategory() /*! \fn bool QLoggingCategory::isWarningEnabled() const - Returns \c true if warning messages should be shown for this category. - Returns \c false otherwise. + Returns \c true if warning messages should be shown for this category; + \c false otherwise. \note The \l qCWarning() macro already does this check before executing any - code. However, calling this method may be useful to avoid - expensive generation of data that is only used for debug output. + code. However, calling this method may be useful to avoid the + expensive generation of data for debug output only. */ /*! \fn bool QLoggingCategory::isCriticalEnabled() const - Returns \c true if critical messages should be shown for this category. - Returns \c false otherwise. + Returns \c true if critical messages should be shown for this category; + \c false otherwise. \note The \l qCCritical() macro already does this check before executing any - code. However, calling this method may be useful to avoid - expensive generation of data that is only used for debug output. + code. However, calling this method may be useful to avoid the + expensive generation of data for debug output only. */ /*! Returns \c true if a message of type \a msgtype for the category should be - shown. Returns \c false otherwise. + shown; \c false otherwise. */ bool QLoggingCategory::isEnabled(QtMsgType msgtype) const { @@ -332,11 +323,11 @@ bool QLoggingCategory::isEnabled(QtMsgType msgtype) const /*! Changes the message type \a type for the category to \a enable. - This method is meant to be used only from inside a filter - installed by \l installFilter(). See \l {Configuring Categories} for - an overview on how to configure categories globally. + This method is meant for use only from inside a filter installed with + \l installFilter(). For an overview on how to configure categories globally, + see \l {Configuring Categories}. - \note \c QtFatalMsg cannot be changed. It will always remain \c true. + \note \c QtFatalMsg cannot be changed; it will always remain \c true. */ void QLoggingCategory::setEnabled(QtMsgType type, bool enable) { @@ -359,28 +350,25 @@ void QLoggingCategory::setEnabled(QtMsgType type, bool enable) /*! \fn QLoggingCategory &QLoggingCategory::operator()() - Returns the object itself. This allows both a QLoggingCategory variable, and - a factory method returning a QLoggingCategory, to be used in \l qCDebug(), - \l qCWarning(), \l qCCritical() macros. + Returns the object itself. This allows for both: a QLoggingCategory variable, and + a factory method that returns a QLoggingCategory, to be used in \l qCDebug(), + \l qCWarning(), or \l qCCritical() macros. */ /*! \fn const QLoggingCategory &QLoggingCategory::operator()() const - Returns the object itself. This allows both a QLoggingCategory variable, and - a factory method returning a QLoggingCategory, to be used in \l qCDebug(), - \l qCWarning(), \l qCCritical() macros. + Returns the object itself. This allows for both: a QLoggingCategory variable, and + a factory method that returns a QLoggingCategory, to be used in \l qCDebug(), + \l qCWarning(), or \l qCCritical() macros. */ /*! - Returns a pointer to the global category \c "default" that - is used e.g. by qDebug(), qInfo(), qWarning(), qCritical(), qFatal(). + Returns a pointer to the global category \c "default" that is used, for + example, by qDebug(), qInfo(), qWarning(), qCritical(), or qFatal(). - \note The returned pointer may be null during destruction of - static objects. - - \note Ownership of the category is not transferred, do not - \c delete the returned pointer. + \note The pointer returned may be null during destruction of static objects. + Also, don't \c delete this pointer, as ownership of the category isn't transferred. */ QLoggingCategory *QLoggingCategory::defaultCategory() @@ -391,8 +379,7 @@ QLoggingCategory *QLoggingCategory::defaultCategory() /*! \typedef QLoggingCategory::CategoryFilter - This is a typedef for a pointer to a function with the following - signature: + This is a typedef for a pointer to a function with the following signature: \snippet qloggingcategory/main.cpp 20 @@ -408,14 +395,13 @@ QLoggingCategory *QLoggingCategory::defaultCategory() filter is free to change the respective category configuration with \l setEnabled(). - The filter might be called from different threads, but never concurrently. - The filter shall not call any static functions of QLoggingCategory. + When you define your filter, note that it can be called from different threads; but never + concurrently. This filter cannot call any static functions from QLoggingCategory. Example: \snippet qloggingcategory/main.cpp 21 - An alternative way of configuring the default filter is via - \l setFilterRules(). + Alternatively, you can configure the default filter via \l setFilterRules(). */ QLoggingCategory::CategoryFilter QLoggingCategory::installFilter(QLoggingCategory::CategoryFilter filter) @@ -425,15 +411,15 @@ QLoggingCategory::installFilter(QLoggingCategory::CategoryFilter filter) /*! Configures which categories and message types should be enabled through a - a set of \a rules. + set of \a rules. Example: \snippet qloggingcategory/main.cpp 2 \note The rules might be ignored if a custom category filter is installed - with \l installFilter(), or if the user defined \c QT_LOGGING_CONF or \c QT_LOGGING_RULES - environment variable. + with \l installFilter(), or if the user has defined the \c QT_LOGGING_CONF + or the \c QT_LOGGING_RULES environment variable. */ void QLoggingCategory::setFilterRules(const QString &rules) { @@ -446,7 +432,7 @@ void QLoggingCategory::setFilterRules(const QString &rules) \threadsafe \since 5.2 - Returns an output stream for debug messages in the logging category + Returns an output stream for debug messages in the logging category, \a category. The macro expands to code that checks whether @@ -457,8 +443,8 @@ void QLoggingCategory::setFilterRules(const QString &rules) \snippet qloggingcategory/main.cpp 10 - \note Arguments are not processed if debug output for the category is not - enabled, so do not rely on any side effects. + \note Arguments aren't processed if the debug output for that \a category is not + enabled, so don't rely on any side effects. \sa qDebug() */ @@ -469,16 +455,16 @@ void QLoggingCategory::setFilterRules(const QString &rules) \threadsafe \since 5.3 - Logs a debug message \a message in the logging category \a category. - \a message might contain place holders that are replaced by additional - arguments, similar to the C printf() function. + Logs a debug message, \a message, in the logging category, \a category. + \a message may contain place holders to be replaced by additional arguments, + similar to the C printf() function. Example: \snippet qloggingcategory/main.cpp 13 - \note Arguments might not be processed if debug output for the category is - not enabled, so do not rely on any side effects. + \note Arguments aren't processed if the debug output for that \a category is not + enabled, so don't rely on any side effects. \sa qDebug() */ @@ -489,7 +475,7 @@ void QLoggingCategory::setFilterRules(const QString &rules) \threadsafe \since 5.5 - Returns an output stream for informational messages in the logging category + Returns an output stream for informational messages in the logging category, \a category. The macro expands to code that checks whether @@ -500,8 +486,8 @@ void QLoggingCategory::setFilterRules(const QString &rules) \snippet qloggingcategory/main.cpp qcinfo_stream - \note Arguments are not processed if debug output for the category is not - enabled, so do not rely on any side effects. + \note If the debug output for a particular category isn't enabled, arguments + won't be processed, so don't rely on any side effects. \sa qInfo() */ @@ -512,16 +498,16 @@ void QLoggingCategory::setFilterRules(const QString &rules) \threadsafe \since 5.5 - Logs an informational message \a message in the logging category \a category. - \a message might contain place holders that are replaced by additional - arguments, similar to the C printf() function. + Logs an informational message, \a message, in the logging category, \a category. + \a message may contain place holders to be replaced by additional arguments, + similar to the C printf() function. Example: \snippet qloggingcategory/main.cpp qcinfo_printf - \note Arguments might not be processed if debug output for the category is - not enabled, so do not rely on any side effects. + \note If the debug output for a particular category isn't enabled, arguments + won't be processed, so don't rely on any side effects. \sa qInfo() */ @@ -532,7 +518,7 @@ void QLoggingCategory::setFilterRules(const QString &rules) \threadsafe \since 5.2 - Returns an output stream for warning messages in the logging category + Returns an output stream for warning messages in the logging category, \a category. The macro expands to code that checks whether @@ -543,8 +529,8 @@ void QLoggingCategory::setFilterRules(const QString &rules) \snippet qloggingcategory/main.cpp 11 - \note Arguments are not processed if warning output for the category is not - enabled, so do not rely on any side effects. + \note If the warning output for a particular category isn't enabled, arguments + won't be processed, so don't rely on any side effects. \sa qWarning() */ @@ -555,16 +541,16 @@ void QLoggingCategory::setFilterRules(const QString &rules) \threadsafe \since 5.3 - Logs a warning message \a message in the logging category \a category. - \a message might contain place holders that are replaced by additional - arguments, similar to the C printf() function. + Logs a warning message, \a message, in the logging category, \a category. + \a message may contain place holders to be replaced by additional arguments, + similar to the C printf() function. Example: \snippet qloggingcategory/main.cpp 14 - \note Arguments might not be processed if warning output for the category is - not enabled, so do not rely on any side effects. + \note If the warning output for a particular category isn't enabled, arguments + won't be processed, so don't rely on any side effects. \sa qWarning() */ @@ -575,7 +561,7 @@ void QLoggingCategory::setFilterRules(const QString &rules) \threadsafe \since 5.2 - Returns an output stream for critical messages in the logging category + Returns an output stream for critical messages in the logging category, \a category. The macro expands to code that checks whether @@ -586,8 +572,9 @@ void QLoggingCategory::setFilterRules(const QString &rules) \snippet qloggingcategory/main.cpp 12 - \note Arguments are not processed if critical output for the category is not - enabled, so do not rely on any side effects. + + \note If the critical output for a particular category isn't enabled, arguments + won't be processed, so don't rely on any side effects. \sa qCritical() */ @@ -598,16 +585,16 @@ void QLoggingCategory::setFilterRules(const QString &rules) \threadsafe \since 5.3 - Logs a critical message \a message in the logging category \a category. - \a message might contain place holders that are replaced by additional - arguments, similar to the C printf() function. + Logs a critical message, \a message, in the logging category, \a category. + \a message may contain place holders to be replaced by additional arguments, + similar to the C printf() function. Example: \snippet qloggingcategory/main.cpp 15 - \note Arguments might not be processed if critical output for the category - is not enabled, so do not rely on any side effects. + \note If the critical output for a particular category isn't enabled, arguments + won't be processed, so don't rely on any side effects. \sa qCritical() */ @@ -633,7 +620,7 @@ void QLoggingCategory::setFilterRules(const QString &rules) \a string identifier. By default, all message types are enabled. Only one translation unit in a library or executable can define a category - with a specific name. The implicitly defined QLoggingCategory object is + with a specific name. The implicitly-defined QLoggingCategory object is created on first use, in a thread-safe manner. This macro must be used outside of a class or method. @@ -650,7 +637,7 @@ void QLoggingCategory::setFilterRules(const QString &rules) and more severe are enabled, types with a lower severity are disabled. Only one translation unit in a library or executable can define a category - with a specific name. The implicitly defined QLoggingCategory object is + with a specific name. The implicitly-defined QLoggingCategory object is created on first use, in a thread-safe manner. This macro must be used outside of a class or method. It is only defined diff --git a/src/corelib/io/qsavefile.cpp b/src/corelib/io/qsavefile.cpp index f41e6302a2..0a884a7df9 100644 --- a/src/corelib/io/qsavefile.cpp +++ b/src/corelib/io/qsavefile.cpp @@ -243,9 +243,15 @@ bool QSaveFile::open(OpenMode mode) return false; }; + bool requiresDirectWrite = false; #ifdef Q_OS_WIN // check if it is an Alternate Data Stream - if (d->finalFileName == d->fileName && d->fileName.indexOf(QLatin1Char(':'), 2) > 1) { + requiresDirectWrite = d->finalFileName == d->fileName && d->fileName.indexOf(QLatin1Char(':'), 2) > 1; +#elif defined(Q_OS_ANDROID) + // check if it is a content:// URL + requiresDirectWrite = d->fileName.startsWith(QLatin1String("content://")); +#endif + if (requiresDirectWrite) { // yes, we can't rename onto it... if (d->directWriteFallback) { if (openDirectly()) @@ -254,14 +260,12 @@ bool QSaveFile::open(OpenMode mode) d->fileEngine.reset(); } else { QString msg = - QSaveFile::tr("QSaveFile cannot open '%1' without direct write fallback " - "enabled: path contains an Alternate Data Stream specifier") - .arg(QDir::toNativeSeparators(d->fileName)); + QSaveFile::tr("QSaveFile cannot open '%1' without direct write fallback enabled.") + .arg(QDir::toNativeSeparators(d->fileName)); d->setError(QFileDevice::OpenError, msg); } return false; } -#endif d->fileEngine.reset(new QTemporaryFileEngine(&d->finalFileName, QTemporaryFileEngine::Win32NonShared)); // if the target file exists, we'll copy its permissions below, diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index cc396d9239..5cb30a74ac 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -112,6 +112,13 @@ QT_BEGIN_NAMESPACE are returned by classInfo(), and you can search for pairs with indexOfClassInfo(). + \note Operations that use the meta object system are generally thread- + safe, as QMetaObjects are typically static read-only instances + generated at compile time. However, if meta objects are dynamically + modified by the application (for instance, when using QQmlPropertyMap), + then the application has to explicitly synchronize access to the + respective meta object. + \sa QMetaClassInfo, QMetaEnum, QMetaMethod, QMetaProperty, QMetaType, {Meta-Object System} */ diff --git a/src/corelib/serialization/qjsondocument.cpp b/src/corelib/serialization/qjsondocument.cpp index 193b80ee22..8c3818caff 100644 --- a/src/corelib/serialization/qjsondocument.cpp +++ b/src/corelib/serialization/qjsondocument.cpp @@ -332,7 +332,7 @@ QVariant QJsonDocument::toVariant() const } /*! - Converts the QJsonDocument to a UTF-8 encoded JSON document. + Converts the QJsonDocument to an indented, UTF-8 encoded JSON document. \sa fromJson() */ diff --git a/src/corelib/text/qregexp.cpp b/src/corelib/text/qregexp.cpp index 41f3508ff8..ac4d9bbc36 100644 --- a/src/corelib/text/qregexp.cpp +++ b/src/corelib/text/qregexp.cpp @@ -3008,12 +3008,10 @@ int QRegExpEngine::getEscape() yyCharClass->addSingleton(0x005f); // '_' return Tok_CharClass; case 'I': - if (xmlSchemaExtensions) { - yyCharClass->setNegative(!yyCharClass->negative()); - Q_FALLTHROUGH(); - } else { + if (!xmlSchemaExtensions) break; - } + yyCharClass->setNegative(!yyCharClass->negative()); + Q_FALLTHROUGH(); case 'i': if (xmlSchemaExtensions) { yyCharClass->addCategories(FLAG(QChar::Mark_NonSpacing) | @@ -3048,12 +3046,10 @@ int QRegExpEngine::getEscape() break; } case 'C': - if (xmlSchemaExtensions) { - yyCharClass->setNegative(!yyCharClass->negative()); - Q_FALLTHROUGH(); - } else { + if (!xmlSchemaExtensions) break; - } + yyCharClass->setNegative(!yyCharClass->negative()); + Q_FALLTHROUGH(); case 'c': if (xmlSchemaExtensions) { yyCharClass->addCategories(FLAG(QChar::Mark_NonSpacing) | @@ -3094,12 +3090,10 @@ int QRegExpEngine::getEscape() break; } case 'P': - if (xmlSchemaExtensions) { - yyCharClass->setNegative(!yyCharClass->negative()); - Q_FALLTHROUGH(); - } else { + if (!xmlSchemaExtensions) break; - } + yyCharClass->setNegative(!yyCharClass->negative()); + Q_FALLTHROUGH(); case 'p': if (xmlSchemaExtensions) { if (yyCh != '{') { diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index 375843e36e..4d8eff113f 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -1193,10 +1193,10 @@ static int qt_compare_strings(QLatin1String lhs, QStringView rhs, Qt::CaseSensit static int qt_compare_strings(QLatin1String lhs, QLatin1String rhs, Qt::CaseSensitivity cs) noexcept { - if (cs == Qt::CaseInsensitive) - return qstrnicmp(lhs.data(), lhs.size(), rhs.data(), rhs.size()); if (lhs.isEmpty()) return lencmp(0, rhs.size()); + if (cs == Qt::CaseInsensitive) + return qstrnicmp(lhs.data(), lhs.size(), rhs.data(), rhs.size()); const auto l = std::min(lhs.size(), rhs.size()); int r = qstrncmp(lhs.data(), rhs.data(), l); return r ? r : lencmp(lhs.size(), rhs.size()); diff --git a/src/dbus/qdbusserver.cpp b/src/dbus/qdbusserver.cpp index f2607e3e8d..eccffc3d3e 100644 --- a/src/dbus/qdbusserver.cpp +++ b/src/dbus/qdbusserver.cpp @@ -111,12 +111,16 @@ QDBusServer::QDBusServer(QObject *parent) */ QDBusServer::~QDBusServer() { - QWriteLocker locker(&d->lock); + QMutex *managerMutex = nullptr; + if (QDBusConnectionManager::instance()) + managerMutex = &QDBusConnectionManager::instance()->mutex; + QMutexLocker locker(managerMutex); + QWriteLocker writeLocker(&d->lock); if (QDBusConnectionManager::instance()) { - const auto locker = qt_scoped_lock(QDBusConnectionManager::instance()->mutex); for (const QString &name : qAsConst(d->serverConnectionNames)) QDBusConnectionManager::instance()->removeConnection(name); d->serverConnectionNames.clear(); + locker.unlock(); } d->serverObject = nullptr; d->ref.storeRelaxed(0); diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index ddd6726299..cb7a0b8ac9 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -3322,8 +3322,11 @@ void QGuiApplication::setFont(const QFont &font) *QGuiApplicationPrivate::app_font = font; applicationResourceFlags |= ApplicationFontExplicitlySet; - if (emitChange && qGuiApp) - emit qGuiApp->fontChanged(*QGuiApplicationPrivate::app_font); + if (emitChange && qGuiApp) { + auto font = *QGuiApplicationPrivate::app_font; + locker.unlock(); + emit qGuiApp->fontChanged(font); + } } /*! diff --git a/src/gui/opengl/qopenglprogrambinarycache.cpp b/src/gui/opengl/qopenglprogrambinarycache.cpp index 8d4d8ed183..54160e1240 100644 --- a/src/gui/opengl/qopenglprogrambinarycache.cpp +++ b/src/gui/opengl/qopenglprogrambinarycache.cpp @@ -263,10 +263,9 @@ public: bool QOpenGLProgramBinaryCache::load(const QByteArray &cacheKey, uint programId) { - if (m_memCache.contains(cacheKey)) { - const MemCacheEntry *e = m_memCache[cacheKey]; + QMutexLocker lock(&m_mutex); + if (const MemCacheEntry *e = m_memCache.object(cacheKey)) return setProgramBinary(programId, e->format, e->blob.constData(), e->blob.size()); - } QByteArray buf; const QString fn = cacheFileName(cacheKey); @@ -401,6 +400,7 @@ void QOpenGLProgramBinaryCache::save(const QByteArray &cacheKey, uint programId) GLint outSize = 0; #if defined(QT_OPENGL_ES_2) if (context->isOpenGLES() && context->format().majorVersion() < 3) { + QMutexLocker lock(&m_mutex); initializeProgramBinaryOES(context); getProgramBinaryOES(programId, blobSize, &outSize, &blobFormat, p); } else diff --git a/src/gui/opengl/qopenglprogrambinarycache_p.h b/src/gui/opengl/qopenglprogrambinarycache_p.h index 9fade08e66..e181a6ab81 100644 --- a/src/gui/opengl/qopenglprogrambinarycache_p.h +++ b/src/gui/opengl/qopenglprogrambinarycache_p.h @@ -54,6 +54,7 @@ #include <QtGui/qtguiglobal.h> #include <QtGui/qopenglshaderprogram.h> #include <QtCore/qcache.h> +#include <QtCore/qmutex.h> QT_BEGIN_NAMESPACE @@ -99,6 +100,7 @@ private: void initializeProgramBinaryOES(QOpenGLContext *context); bool m_programBinaryOESInitialized = false; #endif + QMutex m_mutex; }; QT_END_NAMESPACE diff --git a/src/gui/painting/XCONSORTIUM_LICENSE.txt b/src/gui/painting/XCONSORTIUM_LICENSE.txt new file mode 100644 index 0000000000..5d98625787 --- /dev/null +++ b/src/gui/painting/XCONSORTIUM_LICENSE.txt @@ -0,0 +1,43 @@ +Copyright (c) 1987, 1988 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp index 3240b83451..b0393aff95 100644 --- a/src/gui/painting/qbackingstore.cpp +++ b/src/gui/painting/qbackingstore.cpp @@ -95,6 +95,11 @@ public: QBackingStore::QBackingStore(QWindow *window) : d_ptr(new QBackingStorePrivate(window)) { + if (window->handle()) { + // Create platform backingstore up front if we have a platform window, + // otherwise delay the creation until absolutely necessary. + handle(); + } } /*! diff --git a/src/gui/painting/qbezier.cpp b/src/gui/painting/qbezier.cpp index 9861fffff3..7622262da9 100644 --- a/src/gui/painting/qbezier.cpp +++ b/src/gui/painting/qbezier.cpp @@ -106,10 +106,10 @@ void QBezier::addToPolygon(QPolygonF *polygon, qreal bezier_flattening_threshold int levels[10]; beziers[0] = *this; levels[0] = 9; - QBezier *b = beziers; - int *lvl = levels; + int top = 0; - while (b >= beziers) { + while (top >= 0) { + QBezier *b = &beziers[top]; // check if we can pop the top bezier curve from the stack qreal y4y1 = b->y4 - b->y1; qreal x4x1 = b->x4 - b->x1; @@ -123,17 +123,15 @@ void QBezier::addToPolygon(QPolygonF *polygon, qreal bezier_flattening_threshold qAbs(b->x1 - b->x3) + qAbs(b->y1 - b->y3); l = 1.; } - if (d < bezier_flattening_threshold*l || *lvl == 0) { + if (d < bezier_flattening_threshold * l || levels[top] == 0) { // good enough, we pop it off and add the endpoint polygon->append(QPointF(b->x4, b->y4)); - --b; - --lvl; + --top; } else { // split, second half of the polygon goes lower into the stack std::tie(b[1], b[0]) = b->split(); - lvl[1] = --lvl[0]; - ++b; - ++lvl; + levels[top + 1] = --levels[top]; + ++top; } } } @@ -144,10 +142,10 @@ void QBezier::addToPolygon(QDataBuffer<QPointF> &polygon, qreal bezier_flattenin int levels[10]; beziers[0] = *this; levels[0] = 9; - QBezier *b = beziers; - int *lvl = levels; + int top = 0; - while (b >= beziers) { + while (top >= 0) { + QBezier *b = &beziers[top]; // check if we can pop the top bezier curve from the stack qreal y4y1 = b->y4 - b->y1; qreal x4x1 = b->x4 - b->x1; @@ -161,17 +159,15 @@ void QBezier::addToPolygon(QDataBuffer<QPointF> &polygon, qreal bezier_flattenin qAbs(b->x1 - b->x3) + qAbs(b->y1 - b->y3); l = 1.; } - if (d < bezier_flattening_threshold*l || *lvl == 0) { + if (d < bezier_flattening_threshold * l || levels[top] == 0) { // good enough, we pop it off and add the endpoint polygon.add(QPointF(b->x4, b->y4)); - --b; - --lvl; + --top; } else { // split, second half of the polygon goes lower into the stack std::tie(b[1], b[0]) = b->split(); - lvl[1] = --lvl[0]; - ++b; - ++lvl; + levels[top + 1] = --levels[top]; + ++top; } } } diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp index 51eed962f0..82f5be2b65 100644 --- a/src/gui/painting/qregion.cpp +++ b/src/gui/painting/qregion.cpp @@ -88,60 +88,6 @@ QT_BEGIN_NAMESPACE Example of using complex regions: \snippet code/src_gui_painting_qregion.cpp 0 - \section1 Additional License Information - - On Embedded Linux and X11 platforms, parts of this class rely on - code obtained under the following licenses: - - \legalese - Copyright (c) 1987 X Consortium - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the name of the X Consortium shall not be - used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from the X Consortium. - \endlegalese - - \br - - \legalese - Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - - Permission to use, copy, modify, and distribute this software and its - documentation for any purpose and without fee is hereby granted, - provided that the above copyright notice appear in all copies and that - both that copyright notice and this permission notice appear in - supporting documentation, and that the name of Digital not be - used in advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING - ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL - DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR - ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - SOFTWARE. - \endlegalese - \sa QPainter::setClipRegion(), QPainter::setClipRect(), QPainterPath */ diff --git a/src/gui/painting/qt_attribution.json b/src/gui/painting/qt_attribution.json index 9d3debc1b9..7b16e8c211 100644 --- a/src/gui/painting/qt_attribution.json +++ b/src/gui/painting/qt_attribution.json @@ -41,5 +41,20 @@ "LicenseId": "MIT", "LicenseFile": "WEBGRADIENTS_LICENSE.txt", "Copyright": "Copyright (c) 2017 itmeo" + }, + { + "Id": "xserverhelper", + "Name": "X Server helper", + "QDocModule": "qtgui", + "QtUsage": "Used in Qt GUI (QRegion).", + "Files": "qregion.cpp", + + "Description": "Code from X11's region.h, Region.c, poly.h, and PolyReg.c", + "Homepage": "https://www.x.org/", + "License": "X11 License and Historical Permission Notice and Disclaimer", + "LicenseId": "X11 AND HPND", + "LicenseFile": "XCONSORTIUM_LICENSE.txt", + "Copyright": "Copyright (c) 1987, 1988 X Consortium +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts." } ] diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index b3dec282b0..8ac81d1780 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -758,8 +758,9 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq quint64 requestStartOffset = requestRange.left(index).toULongLong(); quint64 requestEndOffset = requestRange.mid(index + 1).toULongLong(); + // In case an end offset is not given it is skipped from the request range requestRange = "bytes=" + QByteArray::number(resumeOffset + requestStartOffset) + - '-' + QByteArray::number(requestEndOffset); + '-' + (requestEndOffset ? QByteArray::number(requestEndOffset) : QByteArray()); httpRequest.setHeaderField("Range", requestRange); } else { diff --git a/src/network/access/qnetworkreplywasmimpl.cpp b/src/network/access/qnetworkreplywasmimpl.cpp index 53784407d8..f28b8415d1 100644 --- a/src/network/access/qnetworkreplywasmimpl.cpp +++ b/src/network/access/qnetworkreplywasmimpl.cpp @@ -63,6 +63,8 @@ static void q_requestErrorCallback(val event) return; val xhr = event["target"]; + if (xhr.isNull() || xhr.isUndefined()) + return; quintptr func = xhr["data-handler"].as<quintptr>(); QNetworkReplyWasmImplPrivate *reply = reinterpret_cast<QNetworkReplyWasmImplPrivate*>(func); @@ -84,6 +86,8 @@ static void q_progressCallback(val event) return; val xhr = event["target"]; + if (xhr.isNull() || xhr.isUndefined()) + return; QNetworkReplyWasmImplPrivate *reply = reinterpret_cast<QNetworkReplyWasmImplPrivate*>(xhr["data-handler"].as<quintptr>()); @@ -99,6 +103,8 @@ static void q_loadCallback(val event) return; val xhr = event["target"]; + if (xhr.isNull() || xhr.isUndefined()) + return; QNetworkReplyWasmImplPrivate *reply = reinterpret_cast<QNetworkReplyWasmImplPrivate*>(xhr["data-handler"].as<quintptr>()); @@ -123,8 +129,13 @@ static void q_loadCallback(val event) } else if (responseType == "arraybuffer" || responseType == "blob") { // handle this data in the FileReader, triggered by the call to readAsArrayBuffer val blob = xhr["response"]; + if (blob.isNull() || blob.isUndefined()) + return; val reader = val::global("FileReader").new_(); + if (reader.isNull() || reader.isUndefined()) + return; + reader.set("onload", val::module_property("qt_QNetworkReplyWasmImplPrivate_readBinary")); reader.set("data-handler", xhr["data-handler"]); @@ -151,6 +162,8 @@ static void q_responseHeadersCallback(val event) return; val xhr = event["target"]; + if (xhr.isNull() || xhr.isUndefined()) + return; if (xhr["readyState"].as<int>() == 2) { // HEADERS_RECEIVED std::string responseHeaders = xhr.call<std::string>("getAllResponseHeaders"); @@ -170,6 +183,8 @@ static void q_readBinary(val event) return; val fileReader = event["target"]; + if (fileReader.isNull() || fileReader.isUndefined()) + return; QNetworkReplyWasmImplPrivate *reply = reinterpret_cast<QNetworkReplyWasmImplPrivate*>(fileReader["data-handler"].as<quintptr>()); @@ -180,6 +195,9 @@ static void q_readBinary(val event) // Set up source typed array val result = fileReader["result"]; // ArrayBuffer + if (result.isNull() || result.isUndefined()) + return; + val Uint8Array = val::global("Uint8Array"); val sourceTypedArray = Uint8Array.new_(result); diff --git a/src/network/configure.json b/src/network/configure.json index 9652dfd1f7..bebe592088 100644 --- a/src/network/configure.json +++ b/src/network/configure.json @@ -385,7 +385,11 @@ "purpose": "Provides bearer management for the network stack.", "section": "Networking", "condition": "features.thread && features.library && features.networkinterface && features.properties", - "output": [ "publicFeature", "feature" ] + "output": [ + "publicFeature", + "feature", + { "type": "define", "negative": true, "name": "QT_NO_BEARERMANAGEMENT" } + ] }, "localserver": { "label": "QLocalServer", diff --git a/src/network/kernel/qnetworkinterface_unix.cpp b/src/network/kernel/qnetworkinterface_unix.cpp index c28c5ea9e6..4c57bff3bc 100644 --- a/src/network/kernel/qnetworkinterface_unix.cpp +++ b/src/network/kernel/qnetworkinterface_unix.cpp @@ -485,6 +485,7 @@ static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList) struct ifreq req; }; int socket = -1; + memset(&mediareq, 0, sizeof(mediareq)); // ensure both structs start with the name field, of size IFNAMESIZ Q_STATIC_ASSERT(sizeof(mediareq.ifm_name) == sizeof(req.ifr_name)); diff --git a/src/network/ssl/qsslcontext_openssl.cpp b/src/network/ssl/qsslcontext_openssl.cpp index e81e5582f4..8566d78aef 100644 --- a/src/network/ssl/qsslcontext_openssl.cpp +++ b/src/network/ssl/qsslcontext_openssl.cpp @@ -157,32 +157,36 @@ SSL* QSslContext::createSsl() for (int a = 0; a < protocols.count(); ++a) { if (protocols.at(a).size() > 255) { qCWarning(lcSsl) << "TLS NPN extension" << protocols.at(a) - << "is too long and will be truncated to 255 characters."; - protocols[a] = protocols.at(a).left(255); + << "is too long and will be ignored."; + continue; + } else if (protocols.at(a).isEmpty()) { + continue; } m_supportedNPNVersions.append(protocols.at(a).size()).append(protocols.at(a)); } - m_npnContext.data = reinterpret_cast<unsigned char *>(m_supportedNPNVersions.data()); - m_npnContext.len = m_supportedNPNVersions.count(); - m_npnContext.status = QSslConfiguration::NextProtocolNegotiationNone; + if (m_supportedNPNVersions.size()) { + m_npnContext.data = reinterpret_cast<unsigned char *>(m_supportedNPNVersions.data()); + m_npnContext.len = m_supportedNPNVersions.count(); + m_npnContext.status = QSslConfiguration::NextProtocolNegotiationNone; #if OPENSSL_VERSION_NUMBER >= 0x10002000L - if (QSslSocket::sslLibraryVersionNumber() >= 0x10002000L) { - // Callback's type has a parameter 'const unsigned char ** out' - // since it was introduced in 1.0.2. Internally, OpenSSL's own code - // (tests/examples) cast it to unsigned char * (since it's 'out'). - // We just re-use our NPN callback and cast here: - typedef int (*alpn_callback_t) (SSL *, const unsigned char **, unsigned char *, - const unsigned char *, unsigned int, void *); - // With ALPN callback is for a server side only, for a client m_npnContext.status - // will stay in NextProtocolNegotiationNone. - q_SSL_CTX_set_alpn_select_cb(ctx, alpn_callback_t(next_proto_cb), &m_npnContext); - // Client: - q_SSL_set_alpn_protos(ssl, m_npnContext.data, m_npnContext.len); - } + if (QSslSocket::sslLibraryVersionNumber() >= 0x10002000L) { + // Callback's type has a parameter 'const unsigned char ** out' + // since it was introduced in 1.0.2. Internally, OpenSSL's own code + // (tests/examples) cast it to unsigned char * (since it's 'out'). + // We just re-use our NPN callback and cast here: + typedef int (*alpn_callback_t) (SSL *, const unsigned char **, unsigned char *, + const unsigned char *, unsigned int, void *); + // With ALPN callback is for a server side only, for a client m_npnContext.status + // will stay in NextProtocolNegotiationNone. + q_SSL_CTX_set_alpn_select_cb(ctx, alpn_callback_t(next_proto_cb), &m_npnContext); + // Client: + q_SSL_set_alpn_protos(ssl, m_npnContext.data, m_npnContext.len); + } #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ... - // And in case our peer does not support ALPN, but supports NPN: - q_SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &m_npnContext); + // And in case our peer does not support ALPN, but supports NPN: + q_SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &m_npnContext); + } } #endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ... diff --git a/src/network/ssl/qsslsocket_mac.cpp b/src/network/ssl/qsslsocket_mac.cpp index 1725937bc2..e0e065679d 100644 --- a/src/network/ssl/qsslsocket_mac.cpp +++ b/src/network/ssl/qsslsocket_mac.cpp @@ -928,6 +928,13 @@ bool QSslSocketBackendPrivate::initSslContext() QCFType<CFMutableArrayRef> cfNames(CFArrayCreateMutable(nullptr, 0, &kCFTypeArrayCallBacks)); if (cfNames) { for (const QByteArray &name : protocolNames) { + if (name.size() > 255) { + qCWarning(lcSsl) << "TLS ALPN extension" << name + << "is too long and will be ignored."; + continue; + } else if (name.isEmpty()) { + continue; + } QCFString cfName(QString::fromLatin1(name).toCFString()); CFArrayAppendValue(cfNames, cfName); } diff --git a/src/network/ssl/qsslsocket_schannel.cpp b/src/network/ssl/qsslsocket_schannel.cpp index c254659a33..1db26ee9a1 100644 --- a/src/network/ssl/qsslsocket_schannel.cpp +++ b/src/network/ssl/qsslsocket_schannel.cpp @@ -408,13 +408,17 @@ QByteArray createAlpnString(const QByteArrayList &nextAllowedProtocols) for (QByteArray proto : nextAllowedProtocols) { if (proto.size() > 255) { qCWarning(lcSsl) << "TLS ALPN extension" << proto - << "is too long and will be truncated to 255 characters."; - proto = proto.left(255); + << "is too long and will be ignored."; + continue; + } else if (proto.isEmpty()) { + continue; } protocolString += char(proto.length()) + proto; } return protocolString; }(); + if (names.isEmpty()) + return alpnString; const quint16 namesSize = names.size(); const quint32 alpnId = SecApplicationProtocolNegotiationExt_ALPN; diff --git a/src/platformsupport/kmsconvenience/qkmsdevice.cpp b/src/platformsupport/kmsconvenience/qkmsdevice.cpp index d9d76c1146..6121faf362 100644 --- a/src/platformsupport/kmsconvenience/qkmsdevice.cpp +++ b/src/platformsupport/kmsconvenience/qkmsdevice.cpp @@ -355,10 +355,14 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources, } qCDebug(qLcKmsDebug) << "Physical size is" << physSize << "mm" << "for output" << connectorName; - const QByteArray formatStr = userConnectorConfig.value(QStringLiteral("format"), QStringLiteral("xrgb8888")) + const QByteArray formatStr = userConnectorConfig.value(QStringLiteral("format"), QString()) .toByteArray().toLower(); uint32_t drmFormat; - if (formatStr == "xrgb8888") { + bool drmFormatExplicit = true; + if (formatStr.isEmpty()) { + drmFormat = DRM_FORMAT_XRGB8888; + drmFormatExplicit = false; + } else if (formatStr == "xrgb8888") { drmFormat = DRM_FORMAT_XRGB8888; } else if (formatStr == "xbgr8888") { drmFormat = DRM_FORMAT_XBGR8888; @@ -381,7 +385,10 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources, } else { qWarning("Invalid pixel format \"%s\" for output %s", formatStr.constData(), connectorName.constData()); drmFormat = DRM_FORMAT_XRGB8888; + drmFormatExplicit = false; } + qCDebug(qLcKmsDebug) << "Format is" << hex << drmFormat << dec << "requested_by_user =" << drmFormatExplicit + << "for output" << connectorName; const QString cloneSource = userConnectorConfig.value(QStringLiteral("clones")).toString(); if (!cloneSource.isEmpty()) @@ -427,6 +434,7 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources, output.forced_plane_id = 0; output.forced_plane_set = false; output.drm_format = drmFormat; + output.drm_format_requested_by_user = drmFormatExplicit; output.clone_source = cloneSource; output.size = framebufferSize; diff --git a/src/platformsupport/kmsconvenience/qkmsdevice_p.h b/src/platformsupport/kmsconvenience/qkmsdevice_p.h index 77070c293d..b1150e2875 100644 --- a/src/platformsupport/kmsconvenience/qkmsdevice_p.h +++ b/src/platformsupport/kmsconvenience/qkmsdevice_p.h @@ -202,6 +202,7 @@ struct QKmsOutput uint32_t forced_plane_id = 0; bool forced_plane_set = false; uint32_t drm_format = DRM_FORMAT_XRGB8888; + bool drm_format_requested_by_user = false; QString clone_source; QVector<QKmsPlane> available_planes; struct QKmsPlane *eglfs_plane = nullptr; diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro index 02e00039ae..4cf9e64447 100644 --- a/src/plugins/platforms/cocoa/cocoa.pro +++ b/src/plugins/platforms/cocoa/cocoa.pro @@ -21,8 +21,6 @@ SOURCES += main.mm \ qcocoamenuloader.mm \ qcocoahelpers.mm \ qmultitouch_mac.mm \ - qcocoaaccessibilityelement.mm \ - qcocoaaccessibility.mm \ qcocoacursor.mm \ qcocoaclipboard.mm \ qcocoadrag.mm \ @@ -57,8 +55,6 @@ HEADERS += qcocoaintegration.h \ qcocoamenuloader.h \ qcocoahelpers.h \ qmultitouch_mac_p.h \ - qcocoaaccessibilityelement.h \ - qcocoaaccessibility.h \ qcocoacursor.h \ qcocoaclipboard.h \ qcocoadrag.h \ @@ -83,13 +79,21 @@ qtConfig(vulkan) { HEADERS += qcocoavulkaninstance.h } +qtConfig(accessibility) { + QT += accessibility_support-private + SOURCES += qcocoaaccessibilityelement.mm \ + qcocoaaccessibility.mm + HEADERS += qcocoaaccessibilityelement.h \ + qcocoaaccessibility.h +} + RESOURCES += qcocoaresources.qrc LIBS += -framework AppKit -framework CoreServices -framework Carbon -framework IOKit -framework QuartzCore -framework CoreVideo -framework Metal -framework IOSurface -lcups QT += \ core-private gui-private \ - accessibility_support-private clipboard_support-private theme_support-private \ + clipboard_support-private theme_support-private \ fontdatabase_support-private graphics_support-private qtConfig(vulkan): QT += vulkan_support-private @@ -99,17 +103,20 @@ CONFIG += no_app_extension_api_only qtHaveModule(widgets) { QT_FOR_CONFIG += widgets - SOURCES += \ - qpaintengine_mac.mm \ - qprintengine_mac.mm \ - qcocoaprintersupport.mm \ - qcocoaprintdevice.mm \ - - HEADERS += \ - qpaintengine_mac_p.h \ - qprintengine_mac_p.h \ - qcocoaprintersupport.h \ - qcocoaprintdevice.h \ + SOURCES += qpaintengine_mac.mm + HEADERS += qpaintengine_mac_p.h + + qtHaveModule(printsupport) { + QT += printsupport-private + SOURCES += \ + qprintengine_mac.mm \ + qcocoaprintersupport.mm \ + qcocoaprintdevice.mm + HEADERS += \ + qcocoaprintersupport.h \ + qcocoaprintdevice.h \ + qprintengine_mac_p.h + } qtConfig(colordialog) { SOURCES += qcocoacolordialoghelper.mm @@ -126,7 +133,7 @@ qtHaveModule(widgets) { HEADERS += qcocoafontdialoghelper.h } - QT += widgets-private printsupport-private + QT += widgets-private } OTHER_FILES += cocoa.json diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h index 9be6814ae7..a874936ce6 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.h +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h @@ -54,6 +54,8 @@ class QCocoaBackingStore : public QRasterBackingStore protected: QCocoaBackingStore(QWindow *window); QCFType<CGColorSpaceRef> colorSpace() const; + QMacNotificationObserver m_backingPropertiesObserver; + virtual void backingPropertiesChanged() = 0; }; class QNSWindowBackingStore : public QCocoaBackingStore @@ -69,6 +71,7 @@ private: bool windowHasUnifiedToolbar() const; QImage::Format format() const override; void redrawRoundedBottomCorners(CGRect) const; + void backingPropertiesChanged() override; }; class QCALayerBackingStore : public QCocoaBackingStore @@ -115,6 +118,8 @@ private: bool recreateBackBufferIfNeeded(); bool prepareForFlush(); + void backingPropertiesChanged() override; + std::list<std::unique_ptr<GraphicsBuffer>> m_buffers; }; diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index 15e0236107..eb316c53a8 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -51,6 +51,17 @@ QT_BEGIN_NAMESPACE QCocoaBackingStore::QCocoaBackingStore(QWindow *window) : QRasterBackingStore(window) { + // Ideally this would be plumbed from the platform layer to QtGui, and + // the QBackingStore would be recreated, but we don't have that code yet, + // so at least make sure we invalidate our backingstore when the backing + // properties (color space e.g.) are changed. + NSView *view = static_cast<QCocoaWindow *>(window->handle())->view(); + m_backingPropertiesObserver = QMacNotificationObserver(view.window, + NSWindowDidChangeBackingPropertiesNotification, [this]() { + qCDebug(lcQpaBackingStore) << "Backing properties for" + << this->window() << "did change"; + backingPropertiesChanged(); + }); } QCFType<CGColorSpaceRef> QCocoaBackingStore::colorSpace() const @@ -64,6 +75,37 @@ QCFType<CGColorSpaceRef> QCocoaBackingStore::colorSpace() const QNSWindowBackingStore::QNSWindowBackingStore(QWindow *window) : QCocoaBackingStore(window) { + // Choose an appropriate window depth based on the requested surface format. + // On deep color displays the default bit depth is 16-bit, so unless we need + // that level of precision we opt out of it (and the expensive RGB32 -> RGB64 + // conversions that come with it if our backingstore depth does not match). + + NSWindow *nsWindow = static_cast<QCocoaWindow *>(window->handle())->view().window; + auto colorSpaceName = NSColorSpaceFromDepth(nsWindow.depthLimit); + + static const int kDefaultBitDepth = 8; + auto surfaceFormat = window->requestedFormat(); + auto bitsPerSample = qMax(kDefaultBitDepth, qMax(surfaceFormat.redBufferSize(), + qMax(surfaceFormat.greenBufferSize(), surfaceFormat.blueBufferSize()))); + + // NSBestDepth does not seem to guarantee a window depth deep enough for the + // given bits per sample, even if documented as such. For example, requesting + // 10 bits per sample will not give us a 16-bit format, even if that's what's + // available. Work around this by manually bumping the bit depth. + bitsPerSample = !(bitsPerSample & (bitsPerSample - 1)) + ? bitsPerSample : qNextPowerOfTwo(bitsPerSample); + + auto bestDepth = NSBestDepth(colorSpaceName, bitsPerSample, 0, NO, nullptr); + + // Disable dynamic depth limit, otherwise our depth limit will be overwritten + // by AppKit if the window moves to a screen with a different depth. We call + // this before setting the depth limit, as the call will reset the depth to 0. + [nsWindow setDynamicDepthLimit:NO]; + + qCDebug(lcQpaBackingStore) << "Using" << NSBitsPerSampleFromDepth(bestDepth) + << "bit window depth for" << nsWindow; + + nsWindow.depthLimit = bestDepth; } QNSWindowBackingStore::~QNSWindowBackingStore() @@ -212,9 +254,6 @@ void QNSWindowBackingStore::flush(QWindow *window, const QRegion ®ion, const CGRect viewRect = viewLocalRect.toCGRect(); - if (windowHasUnifiedToolbar()) - NSDrawWindowBackground(viewRect); - [backingStoreImage drawInRect:viewRect fromRect:backingStoreRect.toCGRect() operation:compositingOperation fraction:1.0 respectFlipped:YES hints:nil]; @@ -302,6 +341,11 @@ void QNSWindowBackingStore::redrawRoundedBottomCorners(CGRect windowRect) const #endif } +void QNSWindowBackingStore::backingPropertiesChanged() +{ + m_image = QImage(); +} + // ---------------------------------------------------------------------------- QCALayerBackingStore::QCALayerBackingStore(QWindow *window) @@ -565,6 +609,12 @@ QImage QCALayerBackingStore::toImage() const return imageCopy; } +void QCALayerBackingStore::backingPropertiesChanged() +{ + m_buffers.clear(); + m_buffers.resize(1); +} + QPlatformGraphicsBuffer *QCALayerBackingStore::graphicsBuffer() const { return m_buffers.back().get(); diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index 9bd19dd07c..d0e69bdca5 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -59,7 +59,7 @@ #include "qguiapplication.h" #include <qdebug.h> -#ifndef QT_NO_WIDGETS +#if !defined(QT_NO_WIDGETS) && defined(QT_PRINTSUPPORT_LIB) #include "qcocoaprintersupport.h" #include "qprintengine_mac_p.h" #include <qpa/qplatformprintersupport.h> @@ -153,24 +153,24 @@ QPlatformNativeInterface::NativeResourceForIntegrationFunction QCocoaNativeInter QPlatformPrinterSupport *QCocoaNativeInterface::createPlatformPrinterSupport() { -#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER) +#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER) && defined(QT_PRINTSUPPORT_LIB) return new QCocoaPrinterSupport(); #else - qFatal("Printing is not supported when Qt is configured with -no-widgets"); + qFatal("Printing is not supported when Qt is configured with -no-widgets or -no-feature-printer"); return nullptr; #endif } void *QCocoaNativeInterface::NSPrintInfoForPrintEngine(QPrintEngine *printEngine) { -#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER) +#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER) && defined(QT_PRINTSUPPORT_LIB) QMacPrintEnginePrivate *macPrintEnginePriv = static_cast<QMacPrintEngine *>(printEngine)->d_func(); if (macPrintEnginePriv->state == QPrinter::Idle && !macPrintEnginePriv->isPrintSessionInitialized()) macPrintEnginePriv->initialize(); return macPrintEnginePriv->printInfo; #else Q_UNUSED(printEngine); - qFatal("Printing is not supported when Qt is configured with -no-widgets"); + qFatal("Printing is not supported when Qt is configured with -no-widgets or -no-feature-printer"); return nullptr; #endif } diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index fef72bc496..c6ce6e6819 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -161,6 +161,7 @@ public: Q_NOTIFICATION_HANDLER(NSWindowDidOrderOffScreenNotification) void windowDidOrderOffScreen(); Q_NOTIFICATION_HANDLER(NSWindowDidChangeOcclusionStateNotification) void windowDidChangeOcclusionState(); Q_NOTIFICATION_HANDLER(NSWindowDidChangeScreenNotification) void windowDidChangeScreen(); + Q_NOTIFICATION_HANDLER(NSWindowDidChangeBackingPropertiesNotification) void windowDidChangeBackingProperties(); Q_NOTIFICATION_HANDLER(NSWindowWillCloseNotification) void windowWillClose(); bool windowShouldClose(); diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 0c7ec7f736..db4bc12210 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1262,6 +1262,17 @@ void QCocoaWindow::windowDidChangeScreen() currentScreen->requestUpdate(); } } +/* + The window's backing scale factor or color space has changed. +*/ +void QCocoaWindow::windowDidChangeBackingProperties() +{ + // Ideally we would plumb this thought QPA in a way that lets clients + // invalidate their own caches, and recreate QBackingStore. For now we + // trigger an expose, and let QCocoaBackingStore deal with its own + // buffer invalidation. + [m_view setNeedsDisplay:YES]; +} void QCocoaWindow::windowWillClose() { @@ -1649,21 +1660,6 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBePanel) applyContentBorderThickness(nsWindow); - // Prevent CoreGraphics RGB32 -> RGB64 backing store conversions on deep color - // displays by forcing 8-bit components, unless a deep color format has been - // requested. This conversion uses significant CPU time. - QSurface::SurfaceType surfaceType = QPlatformWindow::window()->surfaceType(); - bool usesCoreGraphics = surfaceType == QSurface::RasterSurface || surfaceType == QSurface::RasterGLSurface; - QSurfaceFormat surfaceFormat = QPlatformWindow::window()->format(); - bool usesDeepColor = surfaceFormat.redBufferSize() > 8 || - surfaceFormat.greenBufferSize() > 8 || - surfaceFormat.blueBufferSize() > 8; - bool usesLayer = view().layer; - if (usesCoreGraphics && !usesDeepColor && !usesLayer) { - [nsWindow setDynamicDepthLimit:NO]; - [nsWindow setDepthLimit:NSWindowDepthTwentyfourBitRGB]; - } - if (format().colorSpace() == QSurfaceFormat::sRGBColorSpace) nsWindow.colorSpace = NSColorSpace.sRGBColorSpace; diff --git a/src/plugins/platforms/cocoa/qnsview_mouse.mm b/src/plugins/platforms/cocoa/qnsview_mouse.mm index 7c566442f0..30613eca32 100644 --- a/src/plugins/platforms/cocoa/qnsview_mouse.mm +++ b/src/plugins/platforms/cocoa/qnsview_mouse.mm @@ -394,14 +394,16 @@ } // Close the popups if the click was outside. if (!inside) { + bool selfClosed = false; Qt::WindowType type = QCocoaIntegration::instance()->activePopupWindow()->window()->type(); while (QCocoaWindow *popup = QCocoaIntegration::instance()->popPopupWindow()) { + selfClosed = self == popup->view(); QWindowSystemInterface::handleCloseEvent(popup->window()); QWindowSystemInterface::flushWindowSystemEvents(); } // Consume the mouse event when closing the popup, except for tool tips // were it's expected that the event is processed normally. - if (type != Qt::ToolTip) + if (type != Qt::ToolTip || selfClosed) return; } } diff --git a/src/plugins/platforms/cocoa/qnswindow.mm b/src/plugins/platforms/cocoa/qnswindow.mm index 52f765eb31..68cb270457 100644 --- a/src/plugins/platforms/cocoa/qnswindow.mm +++ b/src/plugins/platforms/cocoa/qnswindow.mm @@ -253,20 +253,10 @@ static bool isMouseEvent(NSEvent *ev) return m_platformWindow ? m_platformWindow->isOpaque() : [super isOpaque]; } -/*! - Borderless windows need a transparent background - - Technically windows with NSWindowStyleMaskTexturedBackground - (such as windows with unified toolbars) need to draw the textured - background of the NSWindow, and can't have a transparent - background, but as NSWindowStyleMaskBorderless is 0, you can't - have a window with NSWindowStyleMaskTexturedBackground that is - also borderless. -*/ - (NSColor *)backgroundColor { - return self.styleMask == NSWindowStyleMaskBorderless - ? [NSColor clearColor] : [super backgroundColor]; + return self.styleMask & NSWindowStyleMaskTexturedBackground ? + [super backgroundColor] : [NSColor clearColor]; } - (void)sendEvent:(NSEvent*)theEvent diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac.mm b/src/plugins/platforms/cocoa/qpaintengine_mac.mm index 3677877538..00b2267f0d 100644 --- a/src/plugins/platforms/cocoa/qpaintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qpaintengine_mac.mm @@ -38,14 +38,18 @@ ****************************************************************************/ #include "qpaintengine_mac_p.h" +#if defined(QT_PRINTSUPPORT_LIB) #include "qprintengine_mac_p.h" +#endif #include <qbitmap.h> #include <qpaintdevice.h> #include <qpainterpath.h> #include <qpixmapcache.h> #include <private/qpaintengine_raster_p.h> +#if defined(QT_PRINTSUPPORT_LIB) #include <qprinter.h> +#endif #include <qstack.h> #include <qwidget.h> #include <qvarlengtharray.h> diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp index 2034632fb3..16dbfe1522 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp @@ -155,20 +155,33 @@ gbm_surface *QEglFSKmsGbmScreen::createSurface(EGLConfig eglConfig) qCDebug(qLcEglfsKmsDebug, "Creating gbm_surface for screen %s", qPrintable(name())); const auto gbmDevice = static_cast<QEglFSKmsGbmDevice *>(device())->gbmDevice(); - EGLint native_format = -1; - EGLBoolean success = eglGetConfigAttrib(display(), eglConfig, EGL_NATIVE_VISUAL_ID, &native_format); - qCDebug(qLcEglfsKmsDebug) << "Got native format" << Qt::hex << native_format << Qt::dec << "from eglGetConfigAttrib() with return code" << bool(success); - - if (success) - m_gbm_surface = gbm_surface_create(gbmDevice, - rawGeometry().width(), - rawGeometry().height(), - native_format, - GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); + // If there was no format override given in the config file, + // query the native (here, gbm) format from the EGL config. + const bool queryFromEgl = !m_output.drm_format_requested_by_user; + if (queryFromEgl) { + EGLint native_format = -1; + EGLBoolean success = eglGetConfigAttrib(display(), eglConfig, EGL_NATIVE_VISUAL_ID, &native_format); + qCDebug(qLcEglfsKmsDebug) << "Got native format" << Qt::hex << native_format << Qt::dec + << "from eglGetConfigAttrib() with return code" << bool(success); + + if (success) { + m_gbm_surface = gbm_surface_create(gbmDevice, + rawGeometry().width(), + rawGeometry().height(), + native_format, + GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); + if (m_gbm_surface) + m_output.drm_format = gbmFormatToDrmFormat(native_format); + } + } - if (!m_gbm_surface) { // fallback for older drivers + // Fallback for older drivers, and when "format" is explicitly specified + // in the output config. (not guaranteed that the requested format works + // of course, but do what we are told to) + if (!m_gbm_surface) { uint32_t gbmFormat = drmFormatToGbmFormat(m_output.drm_format); - qCDebug(qLcEglfsKmsDebug, "Could not create surface with EGL_NATIVE_VISUAL_ID, falling back to format %x", gbmFormat); + if (queryFromEgl) + qCDebug(qLcEglfsKmsDebug, "Could not create surface with EGL_NATIVE_VISUAL_ID, falling back to format %x", gbmFormat); m_gbm_surface = gbm_surface_create(gbmDevice, rawGeometry().width(), rawGeometry().height(), diff --git a/src/plugins/platforms/ios/quiview_accessibility.mm b/src/plugins/platforms/ios/quiview_accessibility.mm index 458ddcc9b8..6612dc131e 100644 --- a/src/plugins/platforms/ios/quiview_accessibility.mm +++ b/src/plugins/platforms/ios/quiview_accessibility.mm @@ -101,7 +101,7 @@ - (id)accessibilityElementAtIndex:(NSInteger)index { [self initAccessibility]; - if (index >= [m_accessibleElements count]) + if (NSUInteger(index) >= [m_accessibleElements count]) return nil; return m_accessibleElements[index]; } diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp index 943c1ff368..b2b401dd40 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp @@ -670,18 +670,26 @@ HRESULT QWindowsUiaMainProvider::ElementProviderFromPoint(double x, double y, IR QPoint point; nativeUiaPointToPoint(uiaPoint, window, &point); - QAccessibleInterface *targetacc = accessible->childAt(point.x(), point.y()); - - if (targetacc) { - QAccessibleInterface *acc = targetacc; - // Controls can be embedded within grouping elements. By default returns the innermost control. - while (acc) { - targetacc = acc; - // For accessibility tools it may be better to return the text element instead of its subcomponents. - if (targetacc->textInterface()) break; - acc = acc->childAt(point.x(), point.y()); + if (auto targetacc = accessible->childAt(point.x(), point.y())) { + auto acc = accessible->childAt(point.x(), point.y()); + // Reject the cases where childAt() returns a different instance in each call for the same + // element (e.g., QAccessibleTree), as it causes an endless loop with Youdao Dictionary installed. + if (targetacc == acc) { + // Controls can be embedded within grouping elements. By default returns the innermost control. + while (acc) { + targetacc = acc; + // For accessibility tools it may be better to return the text element instead of its subcomponents. + if (targetacc->textInterface()) break; + acc = targetacc->childAt(point.x(), point.y()); + if (acc != targetacc->childAt(point.x(), point.y())) { + qCDebug(lcQpaUiAutomation) << "Non-unique childAt() for" << targetacc; + break; + } + } + *pRetVal = providerForAccessible(targetacc); + } else { + qCDebug(lcQpaUiAutomation) << "Non-unique childAt() for" << accessible; } - *pRetVal = providerForAccessible(targetacc); } return S_OK; } diff --git a/src/plugins/printsupport/cups/qppdprintdevice.cpp b/src/plugins/printsupport/cups/qppdprintdevice.cpp index 90411f2a2c..8bfa239dbe 100644 --- a/src/plugins/printsupport/cups/qppdprintdevice.cpp +++ b/src/plugins/printsupport/cups/qppdprintdevice.cpp @@ -40,13 +40,11 @@ #include "qppdprintdevice.h" #include "qcupsprintersupport_p.h" +#include "private/qcups_p.h" // Only needed for PDPK_* #if QT_CONFIG(mimetype) #include <QtCore/QMimeDatabase> #endif -#include <qdebug.h> - -#include "private/qcups_p.h" // Only needed for PDPK_* #ifndef QT_LINUXBASE // LSB merges everything into cups.h #include <cups/language.h> diff --git a/src/widgets/widgets/qtoolbarlayout.cpp b/src/widgets/widgets/qtoolbarlayout.cpp index d50e19a5ed..961a261e8f 100644 --- a/src/widgets/widgets/qtoolbarlayout.cpp +++ b/src/widgets/widgets/qtoolbarlayout.cpp @@ -533,7 +533,7 @@ bool QToolBarLayout::layoutActions(const QSize &size) if (expanded) rperp(o, size) = rowHeight; else - rperp(o, size) = perp(o, rect.size()) - perp(o, QSize(margins.top(), margins.left())); + rperp(o, size) = perp(o, rect.size()) - perp(o, margins); QRect r(pos, size); if (o == Qt::Horizontal) diff --git a/tests/auto/tools/qmake/tst_qmake.cpp b/tests/auto/tools/qmake/tst_qmake.cpp index 99d41d3583..9b434a7b5b 100644 --- a/tests/auto/tools/qmake/tst_qmake.cpp +++ b/tests/auto/tools/qmake/tst_qmake.cpp @@ -711,9 +711,6 @@ void tst_qmake::qinstall() QFile srcfile(src.filePath("main.cpp")); QVERIFY(srcfile.setPermissions(srcfile.permissions() & ~writeFlags)); QDir dst("zort"); -#ifdef Q_OS_WIN - QEXPECT_FAIL("", "QTBUG-77299", Abort); -#endif QVERIFY(qinstall(src.absolutePath(), dst.absolutePath())); QCOMPARE(src.entryList(QDir::Files, QDir::Name), dst.entryList(QDir::Files, QDir::Name)); } diff --git a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp index 1c68a5f752..0cfbc651ad 100644 --- a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp +++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp @@ -4860,6 +4860,7 @@ void tst_QLineEdit::inputRejected() QCOMPARE(spyInputRejected.count(), 0); QTest::keyClicks(testWidget, "fgh"); QCOMPARE(spyInputRejected.count(), 3); +#if QT_CONFIG(clipboard) testWidget->clear(); spyInputRejected.clear(); QApplication::clipboard()->setText("ijklmno"); @@ -4867,6 +4868,7 @@ void tst_QLineEdit::inputRejected() // The first 5 characters are accepted, but // the last 2 are not. QCOMPARE(spyInputRejected.count(), 1); +#endif testWidget->setMaxLength(INT_MAX); testWidget->clear(); @@ -4877,11 +4879,13 @@ void tst_QLineEdit::inputRejected() QCOMPARE(spyInputRejected.count(), 0); QTest::keyClicks(testWidget, "a#"); QCOMPARE(spyInputRejected.count(), 2); +#if QT_CONFIG(clipboard) testWidget->clear(); spyInputRejected.clear(); QApplication::clipboard()->setText("a#"); testWidget->paste(); QCOMPARE(spyInputRejected.count(), 1); +#endif testWidget->clear(); testWidget->setValidator(0); |