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

Conflicts:
	src/corelib/io/qstorageinfo_unix.cpp
	src/network/ssl/qsslsocket_openssl.cpp

Change-Id: Ibc9ce799bef62d60d616beaa9fbde8ebeadfbc20
This commit is contained in:
Liang Qi 2019-06-25 15:37:01 +02:00
commit aedc59b1c3
39 changed files with 586 additions and 221 deletions

View File

@ -82,7 +82,7 @@
"force-pkg-config": { "type": "void", "name": "pkg-config" },
"framework": "boolean",
"gc-binaries": { "type": "boolean", "name": "gc_binaries" },
"gdb-index": { "type": "boolean", "name": "gdb_index" },
"gdb-index": { "type": "boolean", "name": "enable_gdb_index" },
"gcc-sysroot": "boolean",
"gcov": "boolean",
"gnumake": { "type": "boolean", "name": "GNUmake" },

View File

@ -254,7 +254,7 @@ void MingwMakefileGenerator::init()
}
if(project->isActiveConfig("dll")) {
project->values("QMAKE_CLEAN").append(project->first("MINGW_IMPORT_LIB"));
project->values("QMAKE_DISTCLEAN").append(project->first("MINGW_IMPORT_LIB"));
}
}

View File

@ -517,4 +517,9 @@ ProKey ProFile::getHashStr(const ushort *&tPtr)
return ret;
}
QDebug operator<<(QDebug debug, const ProString &str)
{
return debug << str.toQString();
}
QT_END_NAMESPACE

View File

@ -31,6 +31,7 @@
#include "qmake_global.h"
#include <qdebug.h>
#include <qstring.h>
#include <qvector.h>
#include <qhash.h>
@ -468,6 +469,8 @@ struct ProFunctionDefs {
QHash<ProKey, ProFunctionDef> replaceFunctions;
};
QDebug operator<<(QDebug debug, const ProString &str);
QT_END_NAMESPACE
#endif // PROITEMS_H

View File

@ -1063,7 +1063,7 @@ QAbstractAnimation::~QAbstractAnimation()
if (d->state != Stopped) {
QAbstractAnimation::State oldState = d->state;
d->state = Stopped;
emit stateChanged(oldState, d->state);
emit stateChanged(d->state, oldState);
if (oldState == QAbstractAnimation::Running)
QAnimationTimer::unregisterAnimation(this);
}

View File

@ -846,6 +846,9 @@ QList<QStorageInfo> QStorageInfoPrivate::mountedVolumes()
const QString mountDir = it.rootPath();
QStorageInfo info(mountDir);
info.d->device = it.device();
info.d->fileSystemType = it.fileSystemType();
info.d->subvolume = it.subvolume();
if (info.bytesTotal() == 0 && info != root())
continue;
volumes.append(info);

View File

@ -694,6 +694,12 @@ static const char *winPosInsertAfter(quintptr h)
static const char *sessionMgrLogOffOption(uint p)
{
#ifndef ENDSESSION_CLOSEAPP
#define ENDSESSION_CLOSEAPP 0x00000001
#endif
#ifndef ENDSESSION_CRITICAL
#define ENDSESSION_CRITICAL 0x40000000
#endif
static const QWinMessageMapping<uint> values[] = {
{ENDSESSION_CLOSEAPP, "Close application"},
{ENDSESSION_CRITICAL, "Force application end"},
@ -887,12 +893,6 @@ QString decodeMSG(const MSG& msg)
parameters += QLatin1Char(')');
}
break;
#ifndef ENDSESSION_CLOSEAPP
#define ENDSESSION_CLOSEAPP 0x00000001
#endif
#ifndef ENDSESSION_CRITICAL
#define ENDSESSION_CRITICAL 0x40000000
#endif
case WM_QUERYENDSESSION:
parameters = QLatin1String("End session: ");
if (const char *logoffOption = sessionMgrLogOffOption(uint(wParam)))

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2018 Intel Corporation.
** Copyright (C) 2019 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@ -598,10 +598,12 @@ QCborValue QCborValue::fromJsonValue(const QJsonValue &v)
switch (v.type()) {
case QJsonValue::Bool:
return v.b;
case QJsonValue::Double:
if (v.dbl == qint64(v.dbl))
return qint64(v.dbl);
case QJsonValue::Double: {
qint64 i;
if (convertDoubleTo(v.dbl, &i))
return i;
return v.dbl;
}
case QJsonValue::String:
return v.toString();
case QJsonValue::Array:

View File

@ -0,0 +1,3 @@
#! [qt5_add_dbus_adaptor]
qt5_add_dbus_adaptor(GENERATED_SOURCES org.example.chat.xml chat.h ChatMainWindow)
#! [qt5_add_dbus_adaptor]

View File

@ -0,0 +1,224 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\page qtdbus-cmake-qt5-add-dbus-interface.html
\ingroup cmake-commands-qtdbus
\title qt5_add_dbus_interface
\brief Generates C++ sources implementing an interface for a D-Bus interface
description file.
\section1 Synopsis
\badcode
qt5_add_dbus_interface(<VAR> dbus_spec basename)
\endcode
\section1 Description
Generates C++ sources implementing an interface for a D-Bus interface description
file defined in \c{dbus_spec}. The generated files are named after \c{basename}:
\c{basename.h}, \c{basename.cpp}, \c{basename.moc}. The paths of the files
are added to \c{<VAR>}.
The function sets up a call to the \l{Qt D-Bus XML compiler (qdbusxml2cpp)}
in interface (proxy) mode. By default, \c{qdbusxml2cpp} generates a C++
class named after the interface name, with a namespaced alias:
\table
\header
\li D-Bus Interface Name
\li Class name
\li Namespaced name
\row
\li \c{org.example.chat}
\li \c{OrgExampleChatInterface}
\li \c{org.example.chat}
\endtable
\section1 Options
Options can be set using \c set_source_file_property on the \c dbus_spec:
\table
\header
\li Option
\li Value
\li Description
\row
\li \c CLASSNAME
\li \c class_name
\li Override the default interface class name with \c{class_name}.
\row
\li \c NO_NAMESPACE
\li boolean
\li Do not generate the namespaced name if set to \c{ON}.
\row
\li \c INCLUDE
\li \c path
\li Add an \c{#include "path"} in the generated code.
\endtable
*/
/*!
\page qtdbus-cmake-qt5-add-dbus-interfaces.html
\ingroup cmake-commands-qtdbus
\title qt5_add_dbus_interfaces
\brief Generates C++ sources implementing interfaces for D-Bus interface
description files.
\section1 Synopsis
\badcode
qt5_add_dbus_interfaces(<VAR> dbus_spec1 [dbus_spec2 ...])
\endcode
\section1 Description
Generates C++ sources implementing D-Bus interfaces defined in \c{dbus_spec1},
\c{dbus_spec2}, where each argument needs to be the path to a valid D-Bus
interface description file. The paths of the generated files are added to
\c{<VAR>}.
For each argument, a call to the \l{Qt D-Bus XML compiler (qdbusxml2cpp)}
in interface (proxy) mode is set up.
The generated C++ source files are named after the XML file: For the file
\c{org.example.chat.xml} the generated header will be named
\c{orgexamplechatinterface.h}.
\section1 Options
Options can be set using \c set_source_file_property on each of the file
arguments:
\table
\header
\li Option
\li Value
\li Description
\row
\li \c CLASSNAME
\li \c class_name
\li Override the default interface class name with \c{class_name}.
\row
\li \c NO_NAMESPACE
\li boolean
\li Do not generate the namespaced name if set to \c{ON}.
\row
\li \c INCLUDE
\li \c path
\li Add an \c{#include "path"} in the generated code.
\endtable
*/
/*!
\page qtdbus-cmake-qt5-generate-dbus-interface.html
\ingroup cmake-commands-qtdbus
\title qt5_generate_dbus_interface
\brief Generates a D-Bus interface from a header file.
\section1 Synopsis
\badcode
qt5_generate_dbus_interface(header
[customName]
[OPTIONS options]
)
\endcode
\section1 Description
Parses the C++ source or header file containing a QObject-derived class
declaration and generates a file containing the D-BUS Introspection XML.
By default, the generated XML file is stored in the current binary directory,
and has the same base name as the header. You can specify a different name or
path by adding \c{customName} as an optional second argument.
\section1 Options
The function sets up a call to the \c{qdbuscpp2xml} command line tool. Further
arguments to the tool can be set after \c{OPTIONS}.
*/
/*!
\page qtdbus-cmake-qt5-add-dbus-adaptor.html
\ingroup cmake-commands-qtdbus
\title qt5_add_dbus_adaptor
\brief Generates an adaptor class for a D-Bus interface.
\section1 Synopsis
\badcode
qt5_add_dbus_adaptor(<VAR> dbus_spec header parent_class
[basename]
[classname])
\endcode
\section1 Description
Generates a C++ header file implementing an adaptor for a D-Bus interface
description file defined in \c{dbus_spec}. The path of the generated file is
added to \c{<VAR>}. The generated adaptor class takes a pointer to
\c{parent_class} as QObject parent. \c{parent_class} should be declared in
\c{header}, which is included in the generated code as \c{#include "header"}.
The function sets up a call to the \l{Qt D-Bus XML compiler (qdbusxml2cpp)}
in adaptor mode. The default file and class name are generated from the last
segment in the \c{dbus_spec} base name:
\table
\header
\li XML file
\li Header file
\li Class name
\row
\li \c{org.example.chat}
\li \c{chatadaptor.h}
\li \c{ChatAdaptor}
\endtable
You can change the name of the header file to be generated by passing
\c{basename} as the fifth argument. The \c{.h} suffix is always added.
You can change the default class name by passing \c{classname} as the sixth
argument.
\section1 Examples
\snippet cmake/examples.cmake qt5_add_dbus_adaptor
*/

View File

@ -349,6 +349,9 @@ bool QOpenGLTextureBlitterPrivate::buildProgram(ProgramIndex idx, const char *vs
p->glProgram->setUniformValue(p->swizzleUniformPos, false);
// minmize state left set after a create()
p->glProgram->release();
return true;
}

View File

@ -899,11 +899,6 @@ QDistanceField::QDistanceField(int width, int height)
{
}
QDistanceField::QDistanceField(const QDistanceField &other)
{
d = other.d;
}
QDistanceField::QDistanceField(const QRawFont &font, glyph_t glyph, bool doubleResolution)
{
setGlyph(font, glyph, doubleResolution);

View File

@ -94,7 +94,6 @@ public:
QDistanceField(const QRawFont &font, glyph_t glyph, bool doubleResolution = false);
QDistanceField(QFontEngine *fontEngine, glyph_t glyph, bool doubleResolution = false);
QDistanceField(const QPainterPath &path, glyph_t glyph, bool doubleResolution = false);
QDistanceField(const QDistanceField &other);
bool isNull() const;

View File

@ -71,6 +71,10 @@
#include "qwindowscarootfetcher_p.h"
#endif
#if !QT_CONFIG(opensslv11)
#include <openssl/x509_vfy.h>
#endif
#include <QtCore/qdatetime.h>
#include <QtCore/qdebug.h>
#include <QtCore/qdir.h>
@ -394,47 +398,41 @@ bool qt_OCSP_certificate_match(OCSP_SINGLERESP *singleResponse, X509 *peerCert,
#endif // ocsp
// ### This list is shared between all threads, and protected by a
// mutex. Investigate using thread local storage instead. Or better properly
// use OpenSSL's ability to attach application data to an SSL/SSL_CTX
// and extract it in a callback. See how it's done, for example, in PSK
// callback or in DTLS verification callback.
struct QSslErrorList
{
QMutex mutex;
QVector<QSslErrorEntry> errors;
};
Q_GLOBAL_STATIC(QSslErrorList, _q_sslErrorList)
int q_X509Callback(int ok, X509_STORE_CTX *ctx)
{
if (!ok) {
// Store the error and at which depth the error was detected.
_q_sslErrorList()->errors << QSslErrorEntry::fromStoreContext(ctx);
#if !QT_CONFIG(opensslv11)
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << "verification error: dumping bad certificate";
qCDebug(lcSsl) << QSslCertificatePrivate::QSslCertificate_from_X509(q_X509_STORE_CTX_get_current_cert(ctx)).toPem();
qCDebug(lcSsl) << "dumping chain";
const auto certs = QSslSocketBackendPrivate::STACKOFX509_to_QSslCertificates(q_X509_STORE_CTX_get_chain(ctx));
for (const QSslCertificate &cert : certs) {
qCDebug(lcSsl) << "Issuer:" << "O=" << cert.issuerInfo(QSslCertificate::Organization)
<< "CN=" << cert.issuerInfo(QSslCertificate::CommonName)
<< "L=" << cert.issuerInfo(QSslCertificate::LocalityName)
<< "OU=" << cert.issuerInfo(QSslCertificate::OrganizationalUnitName)
<< "C=" << cert.issuerInfo(QSslCertificate::CountryName)
<< "ST=" << cert.issuerInfo(QSslCertificate::StateOrProvinceName);
qCDebug(lcSsl) << "Subject:" << "O=" << cert.subjectInfo(QSslCertificate::Organization)
<< "CN=" << cert.subjectInfo(QSslCertificate::CommonName)
<< "L=" << cert.subjectInfo(QSslCertificate::LocalityName)
<< "OU=" << cert.subjectInfo(QSslCertificate::OrganizationalUnitName)
<< "C=" << cert.subjectInfo(QSslCertificate::CountryName)
<< "ST=" << cert.subjectInfo(QSslCertificate::StateOrProvinceName);
qCDebug(lcSsl) << "Valid:" << cert.effectiveDate() << '-' << cert.expiryDate();
using ErrorListPtr = QVector<QSslErrorEntry>*;
ErrorListPtr errors = nullptr;
// Error list is attached to either 'SSL' or 'X509_STORE'.
if (X509_STORE *store = q_X509_STORE_CTX_get0_store(ctx)) { // We try store first:
#if QT_CONFIG(opensslv11)
errors = ErrorListPtr(q_X509_STORE_get_ex_data(store, 0));
#else
errors = ErrorListPtr(q_CRYPTO_get_ex_data(&store->ex_data, 0));
#endif // opensslv11
}
#endif // QSSLSOCKET_DEBUG
#endif // !QT_CONFIG(opensslv11)
if (!errors) {
// Not found on store? Try SSL and its external data then. According to the OpenSSL's
// documentation:
//
// "Whenever a X509_STORE_CTX object is created for the verification of the peers certificate
// during a handshake, a pointer to the SSL object is stored into the X509_STORE_CTX object
// to identify the connection affected. To retrieve this pointer the X509_STORE_CTX_get_ex_data()
// function can be used with the correct index."
if (SSL *ssl = static_cast<SSL *>(q_X509_STORE_CTX_get_ex_data(ctx, q_SSL_get_ex_data_X509_STORE_CTX_idx())))
errors = ErrorListPtr(q_SSL_get_ex_data(ssl, QSslSocketBackendPrivate::s_indexForSSLExtraData + 1));
}
if (!errors) {
qCWarning(lcSsl, "Neither X509_STORE, nor SSL contains error list, handshake failure");
return 0;
}
errors->append(QSslErrorEntry::fromStoreContext(ctx));
}
// Always return OK to allow verification to continue. We handle the
// errors gracefully after collecting all errors, after verification has
@ -589,11 +587,7 @@ bool QSslSocketBackendPrivate::initSslContext()
else
q_SSL_set_accept_state(ssl);
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
// Save a pointer to this object into the SSL structure.
if (QSslSocket::sslLibraryVersionNumber() >= 0x10001000L)
q_SSL_set_ex_data(ssl, s_indexForSSLExtraData, this);
#endif
q_SSL_set_ex_data(ssl, s_indexForSSLExtraData, this);
#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
// Set the client callback for PSK
@ -1178,14 +1172,14 @@ bool QSslSocketBackendPrivate::startHandshake()
if (inSetAndEmitError)
return false;
QMutexLocker locker(&_q_sslErrorList()->mutex);
_q_sslErrorList()->errors.clear();
QVector<QSslErrorEntry> lastErrors;
q_SSL_set_ex_data(ssl, s_indexForSSLExtraData + 1, &lastErrors);
int result = (mode == QSslSocket::SslClientMode) ? q_SSL_connect(ssl) : q_SSL_accept(ssl);
q_SSL_set_ex_data(ssl, s_indexForSSLExtraData + 1, nullptr);
const auto &lastErrors = _q_sslErrorList()->errors;
if (!lastErrors.isEmpty())
storePeerCertificates();
for (const auto &currentError : lastErrors) {
for (const auto &currentError : qAsConst(lastErrors)) {
emit q->peerVerifyError(_q_OpenSSL_to_QSslError(currentError.code,
configuration.peerCertificateChain.value(currentError.depth)));
if (q->state() != QAbstractSocket::ConnectedState)
@ -1193,7 +1187,6 @@ bool QSslSocketBackendPrivate::startHandshake()
}
errorList << lastErrors;
locker.unlock();
// Connection aborted during handshake phase.
if (q->state() != QAbstractSocket::ConnectedState)
@ -1795,7 +1788,20 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
}
}
QMutexLocker sslErrorListMutexLocker(&_q_sslErrorList()->mutex);
QVector<QSslErrorEntry> lastErrors;
#if QT_CONFIG(opensslv11)
if (!q_X509_STORE_set_ex_data(certStore, 0, &lastErrors)) {
qCWarning(lcSsl) << "Unable to attach external data (error list) to a store";
errors << QSslError(QSslError::UnspecifiedError);
return errors;
}
#else
if (!q_CRYPTO_set_ex_data(&certStore->ex_data, 0, &lastErrors)) {
qCWarning(lcSsl) << "Unable to attach external data (error list) to a store";
errors << QSslError(QSslError::UnspecifiedError);
return errors;
}
#endif // opensslv11
// Register a custom callback to get all verification errors.
q_X509_STORE_set_verify_cb(certStore, q_X509Callback);
@ -1845,12 +1851,7 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
q_OPENSSL_sk_free((OPENSSL_STACK *)intermediates);
// Now process the errors
const auto errorList = std::move(_q_sslErrorList()->errors);
_q_sslErrorList()->errors.clear();
sslErrorListMutexLocker.unlock();
// Translate the errors
if (QSslCertificatePrivate::isBlacklisted(certificateChain[0])) {
QSslError error(QSslError::CertificateBlacklisted, certificateChain[0]);
errors << error;
@ -1864,8 +1865,8 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
}
// Translate errors from the error list into QSslErrors.
errors.reserve(errors.size() + errorList.size());
for (const auto &error : qAsConst(errorList))
errors.reserve(errors.size() + lastErrors.size());
for (const auto &error : qAsConst(lastErrors))
errors << _q_OpenSSL_to_QSslError(error.code, certificateChain.value(error.depth));
q_X509_STORE_free(certStore);

View File

@ -106,6 +106,8 @@ Q_AUTOTEST_EXPORT void q_X509_up_ref(X509 *a);
long q_X509_get_version(X509 *a);
EVP_PKEY *q_X509_get_pubkey(X509 *a);
void q_X509_STORE_set_verify_cb(X509_STORE *ctx, X509_STORE_CTX_verify_cb verify_cb);
int q_X509_STORE_set_ex_data(X509_STORE *ctx, int idx, void *data);
void *q_X509_STORE_get_ex_data(X509_STORE *r, int idx);
STACK_OF(X509) *q_X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx);
void q_DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);
int q_DH_bits(DH *dh);

View File

@ -179,6 +179,8 @@ DEFINEFUNC(ASN1_TIME *, X509_getm_notAfter, X509 *a, a, return nullptr, return)
DEFINEFUNC(long, X509_get_version, X509 *a, a, return -1, return)
DEFINEFUNC(EVP_PKEY *, X509_get_pubkey, X509 *a, a, return nullptr, return)
DEFINEFUNC2(void, X509_STORE_set_verify_cb, X509_STORE *a, a, X509_STORE_CTX_verify_cb verify_cb, verify_cb, return, DUMMYARG)
DEFINEFUNC3(int, X509_STORE_set_ex_data, X509_STORE *a, a, int idx, idx, void *data, data, return 0, return)
DEFINEFUNC2(void *, X509_STORE_get_ex_data, X509_STORE *r, r, int idx, idx, return nullptr, return)
DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get0_chain, X509_STORE_CTX *a, a, return nullptr, return)
DEFINEFUNC3(void, CRYPTO_free, void *str, str, const char *file, file, int line, line, return, DUMMYARG)
DEFINEFUNC(long, OpenSSL_version_num, void, DUMMYARG, return 0, return)
@ -253,6 +255,8 @@ DEFINEFUNC(int, CRYPTO_num_locks, DUMMYARG, DUMMYARG, return 0, return)
DEFINEFUNC(void, CRYPTO_set_locking_callback, void (*a)(int, int, const char *, int), a, return, DUMMYARG)
DEFINEFUNC(void, CRYPTO_set_id_callback, unsigned long (*a)(), a, return, DUMMYARG)
DEFINEFUNC(void, CRYPTO_free, void *a, a, return, DUMMYARG)
DEFINEFUNC3(int, CRYPTO_set_ex_data, CRYPTO_EX_DATA *ad, ad, int idx, idx, void *val, val, return 0, return)
DEFINEFUNC2(void *, CRYPTO_get_ex_data, const CRYPTO_EX_DATA *ad, ad, int idx, idx, return nullptr, return)
DEFINEFUNC(unsigned long, ERR_peek_last_error, DUMMYARG, DUMMYARG, return 0, return)
DEFINEFUNC(void, ERR_free_strings, void, DUMMYARG, return, DUMMYARG)
DEFINEFUNC(void, EVP_CIPHER_CTX_cleanup, EVP_CIPHER_CTX *a, a, return, DUMMYARG)
@ -519,6 +523,7 @@ DEFINEFUNC2(int, X509_STORE_CTX_set_purpose, X509_STORE_CTX *a, a, int b, b, ret
DEFINEFUNC(int, X509_STORE_CTX_get_error, X509_STORE_CTX *a, a, return -1, return)
DEFINEFUNC(int, X509_STORE_CTX_get_error_depth, X509_STORE_CTX *a, a, return -1, return)
DEFINEFUNC(X509 *, X509_STORE_CTX_get_current_cert, X509_STORE_CTX *a, a, return nullptr, return)
DEFINEFUNC(X509_STORE *, X509_STORE_CTX_get0_store, X509_STORE_CTX *ctx, ctx, return nullptr, return)
DEFINEFUNC(X509_STORE_CTX *, X509_STORE_CTX_new, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC2(void *, X509_STORE_CTX_get_ex_data, X509_STORE_CTX *ctx, ctx, int idx, idx, return nullptr, return)
DEFINEFUNC(int, SSL_get_ex_data_X509_STORE_CTX_idx, DUMMYARG, DUMMYARG, return -1, return)
@ -986,6 +991,8 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(X509_get_version)
RESOLVEFUNC(X509_get_pubkey)
RESOLVEFUNC(X509_STORE_set_verify_cb)
RESOLVEFUNC(X509_STORE_set_ex_data)
RESOLVEFUNC(X509_STORE_get_ex_data)
RESOLVEFUNC(CRYPTO_free)
RESOLVEFUNC(OpenSSL_version_num)
RESOLVEFUNC(OpenSSL_version)
@ -1057,6 +1064,8 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(CRYPTO_num_locks)
RESOLVEFUNC(CRYPTO_set_id_callback)
RESOLVEFUNC(CRYPTO_set_locking_callback)
RESOLVEFUNC(CRYPTO_set_ex_data)
RESOLVEFUNC(CRYPTO_get_ex_data)
RESOLVEFUNC(ERR_peek_last_error)
RESOLVEFUNC(ERR_free_strings)
RESOLVEFUNC(EVP_CIPHER_CTX_cleanup)
@ -1312,6 +1321,7 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(X509_STORE_CTX_get_error)
RESOLVEFUNC(X509_STORE_CTX_get_error_depth)
RESOLVEFUNC(X509_STORE_CTX_get_current_cert)
RESOLVEFUNC(X509_STORE_CTX_get0_store)
RESOLVEFUNC(X509_cmp)
RESOLVEFUNC(X509_STORE_CTX_get_ex_data)

View File

@ -458,6 +458,7 @@ int q_X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose);
int q_X509_STORE_CTX_get_error(X509_STORE_CTX *ctx);
int q_X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx);
X509 *q_X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx);
X509_STORE *q_X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx);
// Diffie-Hellman support
DH *q_DH_new();

View File

@ -84,6 +84,8 @@ int q_CRYPTO_num_locks();
void q_CRYPTO_set_locking_callback(void (*a)(int, int, const char *, int));
void q_CRYPTO_set_id_callback(unsigned long (*a)());
void q_CRYPTO_free(void *a);
int q_CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val);
void *q_CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx);
unsigned long q_ERR_peek_last_error();
void q_ERR_free_strings();
void q_EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a);

View File

@ -92,6 +92,9 @@ public:
bool isOpen() const;
void setIsOpen(bool isOpen);
bool isAboutToShow() const;
void setIsAboutToShow(bool isAbout);
void timerEvent(QTimerEvent *e) override;
void syncMenuItem_helper(QPlatformMenuItem *menuItem, bool menubarUpdate);
@ -111,6 +114,7 @@ private:
bool m_parentEnabled:1;
bool m_visible:1;
bool m_isOpen:1;
bool m_isAboutToShow:1;
};
QT_END_NAMESPACE

View File

@ -178,6 +178,16 @@ void QCocoaMenu::setIsOpen(bool isOpen)
m_isOpen = isOpen;
}
bool QCocoaMenu::isAboutToShow() const
{
return m_isAboutToShow;
}
void QCocoaMenu::setIsAboutToShow(bool isAbout)
{
m_isAboutToShow = isAbout;
}
void QCocoaMenu::removeMenuItem(QPlatformMenuItem *menuItem)
{
QMacAutoReleasePool pool;

View File

@ -140,6 +140,12 @@ void QCocoaMenuItem::setMenu(QPlatformMenu *menu)
if (menu == m_menu)
return;
bool setAttached = false;
if ([m_native.menu isKindOfClass:[QCocoaNSMenu class]]) {
auto parentMenu = static_cast<QCocoaNSMenu *>(m_native.menu);
setAttached = parentMenu.platformMenu && parentMenu.platformMenu->isAboutToShow();
}
if (m_menu && m_menu->menuParent() == this) {
m_menu->setMenuParent(nullptr);
// Free the menu from its parent's influence
@ -153,6 +159,8 @@ void QCocoaMenuItem::setMenu(QPlatformMenu *menu)
if (m_menu) {
m_menu->setMenuParent(this);
m_menu->propagateEnabledState(isEnabled());
if (setAttached)
m_menu->setAttachedItem(m_native);
} else {
// we previously had a menu, but no longer
// clear out our item so the nexy sync() call builds a new one

View File

@ -195,7 +195,9 @@ static NSString *qt_mac_removePrivateUnicode(NSString *string)
return;
platformMenu->setIsOpen(true);
platformMenu->setIsAboutToShow(true);
emit platformMenu->aboutToShow();
platformMenu->setIsAboutToShow(false);
}
- (void)menuDidClose:(NSMenu *)menu

View File

@ -658,16 +658,24 @@ QImage::Format QXcbScreen::format() const
return format;
}
QDpi QXcbScreen::logicalDpi() const
int QXcbScreen::forcedDpi() const
{
static const int overrideDpi = qEnvironmentVariableIntValue("QT_FONT_DPI");
if (overrideDpi)
return QDpi(overrideDpi, overrideDpi);
return overrideDpi;
const int forcedDpi = m_virtualDesktop->forcedDpi();
if (forcedDpi > 0) {
if (forcedDpi > 0)
return forcedDpi;
return 0;
}
QDpi QXcbScreen::logicalDpi() const
{
const int forcedDpi = this->forcedDpi();
if (forcedDpi > 0)
return QDpi(forcedDpi, forcedDpi);
}
return m_virtualDesktop->dpi();
}
@ -739,7 +747,9 @@ void QXcbScreen::updateGeometry(const QRect &geometry, uint8_t rotation)
if (m_sizeMillimeters.isEmpty())
m_sizeMillimeters = sizeInMillimeters(geometry.size(), m_virtualDesktop->dpi());
qreal dpi = geometry.width() / physicalSize().width() * qreal(25.4);
qreal dpi = forcedDpi();
if (dpi <= 0)
dpi = geometry.width() / physicalSize().width() * qreal(25.4);
// Use 128 as a reference DPI on small screens. This favors "small UI" over "large UI".
qreal referenceDpi = physicalSize().width() <= 320 ? 128 : 96;

View File

@ -208,6 +208,7 @@ public:
private:
void sendStartupMessage(const QByteArray &message) const;
int forcedDpi() const;
QByteArray getOutputProperty(xcb_atom_t atom) const;
QByteArray getEdid() const;

View File

@ -2061,7 +2061,8 @@ QMacStyle::QMacStyle()
Q_D(QMacStyle);
// FIXME: Tie this logic into theme change, or even polish/unpolish
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave) {
d->appearanceObserver = QMacKeyValueObserver(NSApp, @"effectiveAppearance", [&d] {
d->appearanceObserver = QMacKeyValueObserver(NSApp, @"effectiveAppearance", [this] {
Q_D(QMacStyle);
for (NSView *b : d->cocoaControls)
[b release];
d->cocoaControls.clear();

View File

@ -381,8 +381,6 @@ QWidget *QApplication::topLevelAt(const QPoint &pos)
0 if there is no such widget.
*/
void qt_init(QApplicationPrivate *priv, int type
);
void qt_init_tooltip_palette();
void qt_cleanup();
@ -428,16 +426,10 @@ bool Q_WIDGETS_EXPORT qt_tab_all_widgets()
// ######## move to QApplicationPrivate
// Default application palettes and fonts (per widget type)
Q_GLOBAL_STATIC(PaletteHash, app_palettes)
PaletteHash *qt_app_palettes_hash()
{
return app_palettes();
}
Q_GLOBAL_STATIC(FontHash, app_fonts)
FontHash *qt_app_fonts_hash()
{
return app_fonts();
}
// Exported accessors for use outside of this file
PaletteHash *qt_app_palettes_hash() { return app_palettes(); }
FontHash *qt_app_fonts_hash() { return app_fonts(); }
QWidgetList *QApplicationPrivate::popupWidgets = 0; // has keyboard input focus
@ -571,7 +563,10 @@ void QApplicationPrivate::init()
process_cmdline();
// Must be called before initialize()
qt_init(this, application_type);
QColormap::initialize();
qt_init_tooltip_palette();
QApplicationPrivate::initializeWidgetFontHash();
initialize();
eventDispatcher->startingUp();
@ -586,18 +581,6 @@ void QApplicationPrivate::init()
}
void qt_init(QApplicationPrivate *priv, int type)
{
Q_UNUSED(priv);
Q_UNUSED(type);
QColormap::initialize();
qt_init_tooltip_palette();
QApplicationPrivate::initializeWidgetFontHash();
}
void qt_init_tooltip_palette()
{
#ifndef QT_NO_TOOLTIP
@ -663,7 +646,7 @@ void QApplicationPrivate::initializeWidgetPaletteHash()
QPlatformTheme *platformTheme = QGuiApplicationPrivate::platformTheme();
if (!platformTheme)
return;
qt_app_palettes_hash()->clear();
app_palettes()->clear();
setPossiblePalette(platformTheme->palette(QPlatformTheme::ToolButtonPalette), "QToolButton");
setPossiblePalette(platformTheme->palette(QPlatformTheme::ButtonPalette), "QAbstractButton");
@ -687,7 +670,7 @@ void QApplicationPrivate::initializeWidgetFontHash()
const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
if (!theme)
return;
FontHash *fontHash = qt_app_fonts_hash();
FontHash *fontHash = app_fonts();
fontHash->clear();
if (const QFont *font = theme->font(QPlatformTheme::MenuFont))
@ -1166,9 +1149,7 @@ void QApplication::setStyle(QStyle *style)
} else if (QApplicationPrivate::sys_pal) {
clearSystemPalette();
initSystemPalette();
QApplicationPrivate::initializeWidgetPaletteHash();
QApplicationPrivate::initializeWidgetFontHash();
QApplicationPrivate::setPalette_helper(*QApplicationPrivate::sys_pal, /*className=*/0, /*clearWidgetPaletteHash=*/false);
} else if (!QApplicationPrivate::sys_pal) {
// Initialize the sys_pal if it hasn't happened yet...
QApplicationPrivate::setSystemPalette(QApplicationPrivate::app_style->standardPalette());
@ -1466,28 +1447,10 @@ void QApplication::setPalette(const QPalette &palette, const char* className)
void QApplicationPrivate::setSystemPalette(const QPalette &pal)
{
QPalette adjusted;
#if 0
// adjust the system palette to avoid dithering
QColormap cmap = QColormap::instance();
if (cmap.depths() > 4 && cmap.depths() < 24) {
for (int g = 0; g < QPalette::NColorGroups; g++)
for (int i = 0; i < QPalette::NColorRoles; i++) {
QColor color = pal.color((QPalette::ColorGroup)g, (QPalette::ColorRole)i);
color = cmap.colorAt(cmap.pixel(color));
adjusted.setColor((QPalette::ColorGroup)g, (QPalette::ColorRole) i, color);
}
}
#else
adjusted = pal;
#endif
if (!sys_pal)
sys_pal = new QPalette(adjusted);
sys_pal = new QPalette(pal);
else
*sys_pal = adjusted;
*sys_pal = pal;
if (!QApplicationPrivate::set_pal)
QApplication::setPalette(*sys_pal);

View File

@ -1,4 +1,4 @@
/****************************************************************************
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
@ -2592,14 +2592,27 @@ bool QWidgetPrivate::setScreenForPoint(const QPoint &pos)
Q_Q(QWidget);
if (!q->isWindow())
return false;
// Find the screen for pos and make the widget undertand it is on that screen.
// Find the screen for pos and make the widget understand it is on that screen.
return setScreen(QGuiApplication::screenAt(pos));
}
/*!
\internal
Ensures that the widget's QWindow is set to be on the given \a screen.
Returns true if the screen was changed.
*/
bool QWidgetPrivate::setScreen(QScreen *screen)
{
Q_Q(QWidget);
if (!screen || !q->isWindow())
return false;
const QScreen *currentScreen = windowHandle() ? windowHandle()->screen() : nullptr;
QScreen *actualScreen = QGuiApplication::screenAt(pos);
if (actualScreen && currentScreen != actualScreen) {
if (currentScreen != screen) {
if (!windowHandle()) // Try to create a window handle if not created.
createWinId();
if (windowHandle())
windowHandle()->setScreen(actualScreen);
windowHandle()->setScreen(screen);
return true;
}
return false;
@ -7006,37 +7019,41 @@ void QWidget::setTabOrder(QWidget* first, QWidget *second)
lastFocusChild = focusNext;
}
};
auto setPrev = [](QWidget *w, QWidget *prev)
{
w->d_func()->focus_prev = prev;
};
auto setNext = [](QWidget *w, QWidget *next)
{
w->d_func()->focus_next = next;
};
QWidget *lastFocusChildOfFirst, *lastFocusChildOfSecond;
determineLastFocusChild(first, lastFocusChildOfFirst);
// remove the second widget from the chain
QWidget *lastFocusChildOfSecond;
determineLastFocusChild(second, lastFocusChildOfSecond);
// If the tab order is already correct, exit early
if (lastFocusChildOfFirst == second ||
lastFocusChildOfFirst->d_func()->focus_next == second) {
return;
{
QWidget *oldPrev = second->d_func()->focus_prev;
QWidget *prevWithFocus = oldPrev;
while (prevWithFocus->focusPolicy() == Qt::NoFocus)
prevWithFocus = prevWithFocus->d_func()->focus_prev;
// only widgets between first and second -> all is fine
if (prevWithFocus == first)
return;
QWidget *oldNext = lastFocusChildOfSecond->d_func()->focus_next;
setPrev(oldNext, oldPrev);
setNext(oldPrev, oldNext);
}
// Note that we need to handle two different sections in the tab chain; The section
// that 'first' belongs to (firstSection), where we are about to insert 'second', and
// the section that 'second' used be a part of (secondSection). When we pull 'second'
// out of the second section and insert it into the first, we also need to ensure
// that we leave the second section in a connected state.
QWidget *firstChainOldSecond = lastFocusChildOfFirst->d_func()->focus_next;
QWidget *secondChainNewFirst = second->d_func()->focus_prev;
QWidget *secondChainNewSecond = lastFocusChildOfSecond->d_func()->focus_next;
// Insert 'second' after 'first'
lastFocusChildOfFirst->d_func()->focus_next = second;
second->d_func()->focus_prev = lastFocusChildOfFirst;
// The widget that used to be 'second' in the first section, should now become 'third'
lastFocusChildOfSecond->d_func()->focus_next = firstChainOldSecond;
firstChainOldSecond->d_func()->focus_prev = lastFocusChildOfSecond;
// Repair the second section after we pulled 'second' out of it
secondChainNewFirst->d_func()->focus_next = secondChainNewSecond;
secondChainNewSecond->d_func()->focus_prev = secondChainNewFirst;
// insert the second widget into the chain
QWidget *lastFocusChildOfFirst;
determineLastFocusChild(first, lastFocusChildOfFirst);
{
QWidget *oldNext = lastFocusChildOfFirst->d_func()->focus_next;
setPrev(second, lastFocusChildOfFirst);
setNext(lastFocusChildOfFirst, second);
setPrev(oldNext, lastFocusChildOfSecond);
setNext(lastFocusChildOfSecond, oldNext);
}
}
/*!\internal

View File

@ -181,6 +181,7 @@ struct QTLWExtra {
QRect frameStrut;
QRect normalGeometry; // used by showMin/maximized/FullScreen
Qt::WindowFlags savedFlags; // Save widget flags while showing fullscreen
// ### TODO replace initialScreenIndex with QScreen *, in case the screens change at runtime
int initialScreenIndex; // Screen number when passing a QDesktop[Screen]Widget as parent.
QVector<QPlatformTextureList *> widgetTextures;
@ -356,6 +357,7 @@ public:
void createWinId();
bool setScreenForPoint(const QPoint &pos);
bool setScreen(QScreen *screen);
void createTLExtra();
void createExtra();

View File

@ -3141,8 +3141,6 @@ void QMdiSubWindow::paintEvent(QPaintEvent *paintEvent)
}
Q_D(QMdiSubWindow);
if (isMaximized() && !d->drawTitleBarWhenMaximized())
return;
if (d->resizeTimerId != -1) {
// Only update the style option rect and the window title.
@ -3162,6 +3160,17 @@ void QMdiSubWindow::paintEvent(QPaintEvent *paintEvent)
}
QStylePainter painter(this);
QStyleOptionFrame frameOptions;
frameOptions.initFrom(this);
frameOptions.state.setFlag(QStyle::State_Active, d->isActive);
if (isMaximized() && !d->drawTitleBarWhenMaximized()) {
if (!autoFillBackground() && (!widget() || !qt_widget_private(widget())->isOpaque)) {
// make sure we paint all pixels of a maximized QMdiSubWindow if no-one else does
painter.drawPrimitive(QStyle::PE_FrameWindow, frameOptions);
}
return;
}
if (!d->windowTitle.isEmpty())
painter.setFont(d->font);
painter.drawComplexControl(QStyle::CC_TitleBar, d->cachedStyleOptions);
@ -3169,10 +3178,7 @@ void QMdiSubWindow::paintEvent(QPaintEvent *paintEvent)
if (isMinimized() && !d->hasBorder(d->cachedStyleOptions))
return;
QStyleOptionFrame frameOptions;
frameOptions.initFrom(this);
frameOptions.lineWidth = style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth, 0, this);
frameOptions.state.setFlag(QStyle::State_Active, d->isActive);
// ### Ensure that we do not require setting the cliprect for 4.4
if (!isMinimized() && !d->hasBorder(d->cachedStyleOptions))

View File

@ -2331,8 +2331,18 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
d->updateLayoutDirection();
// Ensure that we get correct sizeHints by placing this window on the correct screen.
if (d->setScreenForPoint(p))
// However if the QMenu was constructed with a QDesktopScreenWidget as its parent,
// then initialScreenIndex was set, so we should respect that for the lifetime of this menu.
// Use d->popupScreen to remember, because initialScreenIndex will be reset after the first showing.
const int screenIndex = d->topData()->initialScreenIndex;
if (screenIndex >= 0)
d->popupScreen = screenIndex;
if (auto s = QGuiApplication::screens().value(d->popupScreen)) {
if (d->setScreen(s))
d->itemsDirty = true;
} else if (d->setScreenForPoint(p)) {
d->itemsDirty = true;
}
const bool contextMenu = d->isContextMenu();
if (d->lastContextMenu != contextMenu) {

View File

@ -515,6 +515,8 @@ public:
bool tearoffHighlighted : 1;
//menu fading/scrolling effects
bool doChildEffects : 1;
int popupScreen = -1;
};
QT_END_NAMESPACE

View File

@ -68,6 +68,7 @@
#include "qmenu_p.h"
#include "qmenubar_p.h"
#include <private/qscreen_p.h>
#include "qdebug.h"
QT_BEGIN_NAMESPACE
@ -322,11 +323,18 @@ void QMenuBarPrivate::popupAction(QAction *action, bool activateFirst)
QRect adjustedActionRect = actionRect(action);
QPoint pos(q->mapToGlobal(QPoint(adjustedActionRect.left(), adjustedActionRect.bottom() + 1)));
QSize popup_size = activeMenu->sizeHint();
//we put the popup menu on the screen containing the bottom-center of the action rect
QRect screenRect = QDesktopWidgetPrivate::screenGeometry(pos + QPoint(adjustedActionRect.width() / 2, 0));
QScreen *popupScreen = q->window()->windowHandle()->screen();
QPoint bottomMiddlePos = pos + QPoint(adjustedActionRect.width() / 2, 0);
const auto &siblings = popupScreen->virtualSiblings();
for (QScreen *sibling : siblings) {
if (sibling->geometry().contains(bottomMiddlePos)) {
popupScreen = sibling;
break;
}
}
QRect screenRect = popupScreen->geometry();
pos = QPoint(qMax(pos.x(), screenRect.x()), qMax(pos.y(), screenRect.y()));
const bool fitUp = (pos.y() - popup_size.height() >= screenRect.top());
const bool fitDown = (pos.y() + popup_size.height() <= screenRect.bottom());
const bool rtl = q->isRightToLeft();
@ -352,6 +360,7 @@ void QMenuBarPrivate::popupAction(QAction *action, bool activateFirst)
if(!defaultPopDown || (fitUp && !fitDown))
pos.setY(qMax(screenRect.y(), q->mapToGlobal(QPoint(0, adjustedActionRect.top()-popup_size.height())).y()));
QMenuPrivate::get(activeMenu)->topData()->initialScreenIndex = QGuiApplication::screens().indexOf(popupScreen);
activeMenu->popup(pos);
if(activateFirst)
activeMenu->d_func()->setFirstActionActive();

View File

@ -83,6 +83,21 @@ void tst_QAbstractAnimation::destruction()
{
TestableQAbstractAnimation *anim = new TestableQAbstractAnimation;
delete anim;
// Animations should stop when deleted
auto *stopWhenDeleted = new TestableQAbstractAnimation;
QAbstractAnimation::State lastOldState, lastNewState;
QObject::connect(stopWhenDeleted, &QAbstractAnimation::stateChanged,
[&](QAbstractAnimation::State newState, QAbstractAnimation::State oldState) {
lastNewState = newState;
lastOldState = oldState;
});
stopWhenDeleted->start();
QCOMPARE(lastOldState, QAbstractAnimation::Stopped);
QCOMPARE(lastNewState, QAbstractAnimation::Running);
delete stopWhenDeleted;
QCOMPARE(lastOldState, QAbstractAnimation::Running);
QCOMPARE(lastNewState, QAbstractAnimation::Stopped);
}
void tst_QAbstractAnimation::currentLoop()

View File

@ -1,17 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICrTCCAhYCCQCdDn5rci6VDjANBgkqhkiG9w0BAQQFADCBmjEOMAwGA1UEChMF
Tm9raWExFDASBgNVBAsTC1F0IFNvZnR3YXJlMSIwIAYJKoZIhvcNAQkBFhNub2Jv
ZHlAbm9kb21haW4ub3JnMQ0wCwYDVQQHEwRPc2xvMQ0wCwYDVQQIEwRPc2xvMQsw
CQYDVQQGEwJOTzEjMCEGA1UEAxMacXQtdGVzdC1zZXJ2ZXIucXQtdGVzdC1uZXQw
HhcNMDkwNzEwMDc0MTIzWhcNMTkwNzA4MDc0MTIzWjCBmjEOMAwGA1UEChMFTm9r
aWExFDASBgNVBAsTC1F0IFNvZnR3YXJlMSIwIAYJKoZIhvcNAQkBFhNub2JvZHlA
bm9kb21haW4ub3JnMQ0wCwYDVQQHEwRPc2xvMQ0wCwYDVQQIEwRPc2xvMQswCQYD
VQQGEwJOTzEjMCEGA1UEAxMacXQtdGVzdC1zZXJ2ZXIucXQtdGVzdC1uZXQwgZ8w
DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM2q22/WNMmn8cC+5EEYGeICySLmp9W6
Ay6eKHr0Xxp3X3epETuPfvAuxp7rOtkS18EMUegkUj8jw0IMEcbyHKFC/rTCaYOt
93CxGBXMIChiMPAsFeYzGa/D6xzAkfcRaJRQ+Ek3CDLXPnXfo7xpABXezYcPXAJr
gsgBfWrwHdxzAgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAy7YOLCZABQy2Ygkchq1I
+TUpvMn+gLwAyW8TNErM1V4lNY2+K78RawzKx3SqM97ymCy4TD45EA3A2gmi32NI
xSKBNjFyzngUqsXBdcSasALiowlZCiJrGwlGX5qCkBlxXvJeUEbuJLPYVl5FBjXZ
6o00K4cSPCqtqUez7WSmDZU=
MIICpzCCAhACCQCzAF1hyRVzAjANBgkqhkiG9w0BAQUFADCBlzELMAkGA1UEBhMC
Tk8xDTALBgNVBAgTBE9zbG8xDTALBgNVBAcTBE9zbG8xDjAMBgNVBAoTBU5va2lh
MTUwMwYDVQQLFCxRdCBTb2Z0d2FyZS9lbWFpbEFkZHJlc3M9bm9ib2R5QG5vZG9t
YWluLm9yZzEjMCEGA1UEAxMacXQtdGVzdC1zZXJ2ZXIucXQtdGVzdC1uZXQwHhcN
MTkwNjI0MTI0OTIxWhcNMjIwNjIzMTI0OTIxWjCBlzELMAkGA1UEBhMCTk8xDTAL
BgNVBAgTBE9zbG8xDTALBgNVBAcTBE9zbG8xDjAMBgNVBAoTBU5va2lhMTUwMwYD
VQQLFCxRdCBTb2Z0d2FyZS9lbWFpbEFkZHJlc3M9bm9ib2R5QG5vZG9tYWluLm9y
ZzEjMCEGA1UEAxMacXQtdGVzdC1zZXJ2ZXIucXQtdGVzdC1uZXQwgZ8wDQYJKoZI
hvcNAQEBBQADgY0AMIGJAoGBAM2q22/WNMmn8cC+5EEYGeICySLmp9W6Ay6eKHr0
Xxp3X3epETuPfvAuxp7rOtkS18EMUegkUj8jw0IMEcbyHKFC/rTCaYOt93CxGBXM
IChiMPAsFeYzGa/D6xzAkfcRaJRQ+Ek3CDLXPnXfo7xpABXezYcPXAJrgsgBfWrw
HdxzAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEASCKbqEX5ysC549mq90ydk4jyDW3m
PUyet01fKpcRqVs+OJxdExFBTra3gho6WzzpTSPsuX2ZKOLF5k6KkCvdCGvhC1Kv
HHPIExurfzvdlSRzj6HbKyPuSfxyOloH0bBp7/Gg5RIuBPKlbmfbnTLtwEjhhbMU
SoYI8HZd3HfY87c=
-----END CERTIFICATE-----

View File

@ -5031,9 +5031,6 @@ public:
// very similar to ioPostToHttpUploadProgress but for SSL
void tst_QNetworkReply::ioPostToHttpsUploadProgress()
{
#ifdef Q_OS_WIN
QSKIP("QTBUG-76157: get rid of locking in TLS handshake (QSslSocket)");
#endif
//QFile sourceFile(testDataDir + "/bigfile");
//QVERIFY(sourceFile.open(QIODevice::ReadOnly));
qint64 wantedSize = 2*1024*1024; // 2 MB
@ -6415,10 +6412,6 @@ void tst_QNetworkReply::encrypted()
void tst_QNetworkReply::abortOnEncrypted()
{
#ifdef Q_OS_WIN
QSKIP("QTBUG-76157: get rid of locking in TLS handshake (QSslSocket)");
#endif
SslServer server;
server.listen();
if (!server.isListening())
@ -8496,9 +8489,7 @@ void tst_QNetworkReply::ioHttpRedirectErrors_data()
QTest::newRow("too-many-redirects") << "http://localhost" << tempRedirectReply << QNetworkReply::TooManyRedirectsError;
#if QT_CONFIG(ssl)
#ifndef Q_OS_WIN // QTBUG-76157
QTest::newRow("insecure-redirect") << "https://localhost" << tempRedirectReply << QNetworkReply::InsecureRedirectError;
#endif // Q_OS_WIN
#endif
QTest::newRow("unknown-redirect") << "http://localhost"<< tempRedirectReply.replace("http", "bad_protocol") << QNetworkReply::ProtocolUnknownError;
}
@ -8575,11 +8566,9 @@ void tst_QNetworkReply::ioHttpRedirectPolicy_data()
QTest::newRow("nolesssafe-nossl") << QNetworkRequest::NoLessSafeRedirectPolicy << false << 1 << 200;
QTest::newRow("same-origin-nossl") << QNetworkRequest::SameOriginRedirectPolicy << false << 1 << 200;
#if QT_CONFIG(ssl)
#ifndef Q_OS_WIN // QTBUG-76157
QTest::newRow("manual-ssl") << QNetworkRequest::ManualRedirectPolicy << true << 0 << 307;
QTest::newRow("nolesssafe-ssl") << QNetworkRequest::NoLessSafeRedirectPolicy << true << 1 << 200;
QTest::newRow("same-origin-ssl") << QNetworkRequest::SameOriginRedirectPolicy << true << 1 << 200;
#endif // Q_OS_WIN
#endif
}
@ -8633,41 +8622,33 @@ void tst_QNetworkReply::ioHttpRedirectPolicyErrors_data()
QTest::newRow("nolesssafe-nossl-nossl-too-many") << QNetworkRequest::NoLessSafeRedirectPolicy
<< false << QString("http://localhost:%1") << 0 << QNetworkReply::TooManyRedirectsError;
#if QT_CONFIG(ssl)
#ifndef Q_OS_WIN // QTBUG-76157
QTest::newRow("nolesssafe-ssl-ssl-too-many") << QNetworkRequest::NoLessSafeRedirectPolicy
<< true << QString("https:/localhost:%1") << 0 << QNetworkReply::TooManyRedirectsError;
QTest::newRow("nolesssafe-ssl-nossl-insecure-redirect") << QNetworkRequest::NoLessSafeRedirectPolicy
<< true << QString("http://localhost:%1") << 50 << QNetworkReply::InsecureRedirectError;
#endif // Q_OS_WIN
#endif
// 2. SameOriginRedirectsPolicy
QTest::newRow("same-origin-nossl-nossl-too-many") << QNetworkRequest::SameOriginRedirectPolicy
<< false << QString("http://localhost:%1") << 0 << QNetworkReply::TooManyRedirectsError;
#if QT_CONFIG(ssl)
#ifndef Q_OS_WIN // QTBUG-76157
QTest::newRow("same-origin-ssl-ssl-too-many") << QNetworkRequest::SameOriginRedirectPolicy
<< true << QString("https://localhost:%1") << 0 << QNetworkReply::TooManyRedirectsError;
QTest::newRow("same-origin-https-http-wrong-protocol") << QNetworkRequest::SameOriginRedirectPolicy
<< true << QString("http://localhost:%1") << 50 << QNetworkReply::InsecureRedirectError;
#endif // Q_OS_WIN
#endif
QTest::newRow("same-origin-http-https-wrong-protocol") << QNetworkRequest::SameOriginRedirectPolicy
<< false << QString("https://localhost:%1") << 50 << QNetworkReply::InsecureRedirectError;
QTest::newRow("same-origin-http-http-wrong-host") << QNetworkRequest::SameOriginRedirectPolicy
<< false << QString("http://not-so-localhost:%1") << 50 << QNetworkReply::InsecureRedirectError;
#if QT_CONFIG(ssl)
#ifndef Q_OS_WIN // QTBUG-76157
QTest::newRow("same-origin-https-https-wrong-host") << QNetworkRequest::SameOriginRedirectPolicy
<< true << QString("https://not-so-localhost:%1") << 50 << QNetworkReply::InsecureRedirectError;
#endif // Q_OS_WIN
#endif
QTest::newRow("same-origin-http-http-wrong-port") << QNetworkRequest::SameOriginRedirectPolicy
<< false << QString("http://localhost/%1") << 50 << QNetworkReply::InsecureRedirectError;
#if QT_CONFIG(ssl)
#ifndef Q_OS_WIN // QTBUG-76157
QTest::newRow("same-origin-https-https-wrong-port") << QNetworkRequest::SameOriginRedirectPolicy
<< true << QString("https://localhost/%1") << 50 << QNetworkReply::InsecureRedirectError;
#endif // Q_OS_WIN
#endif
}
@ -9142,10 +9123,6 @@ void tst_QNetworkReply::putWithServerClosingConnectionImmediately()
for (int s = 0; s <= 1; s++) {
withSsl = (s == 1);
#ifdef Q_OS_WIN
if (withSsl)
QSKIP("QTBUG-76157: get rid of locking in TLS handshake (QSslSocket)");
#endif // Q_OS_WIN
// Test also needs to run several times because of 9c2ecf89
for (int j = 0; j < 20; j++) {
// emulate a minimal https server

View File

@ -1,17 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICrTCCAhYCCQCdDn5rci6VDjANBgkqhkiG9w0BAQQFADCBmjEOMAwGA1UEChMF
Tm9raWExFDASBgNVBAsTC1F0IFNvZnR3YXJlMSIwIAYJKoZIhvcNAQkBFhNub2Jv
ZHlAbm9kb21haW4ub3JnMQ0wCwYDVQQHEwRPc2xvMQ0wCwYDVQQIEwRPc2xvMQsw
CQYDVQQGEwJOTzEjMCEGA1UEAxMacXQtdGVzdC1zZXJ2ZXIucXQtdGVzdC1uZXQw
HhcNMDkwNzEwMDc0MTIzWhcNMTkwNzA4MDc0MTIzWjCBmjEOMAwGA1UEChMFTm9r
aWExFDASBgNVBAsTC1F0IFNvZnR3YXJlMSIwIAYJKoZIhvcNAQkBFhNub2JvZHlA
bm9kb21haW4ub3JnMQ0wCwYDVQQHEwRPc2xvMQ0wCwYDVQQIEwRPc2xvMQswCQYD
VQQGEwJOTzEjMCEGA1UEAxMacXQtdGVzdC1zZXJ2ZXIucXQtdGVzdC1uZXQwgZ8w
DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM2q22/WNMmn8cC+5EEYGeICySLmp9W6
Ay6eKHr0Xxp3X3epETuPfvAuxp7rOtkS18EMUegkUj8jw0IMEcbyHKFC/rTCaYOt
93CxGBXMIChiMPAsFeYzGa/D6xzAkfcRaJRQ+Ek3CDLXPnXfo7xpABXezYcPXAJr
gsgBfWrwHdxzAgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAy7YOLCZABQy2Ygkchq1I
+TUpvMn+gLwAyW8TNErM1V4lNY2+K78RawzKx3SqM97ymCy4TD45EA3A2gmi32NI
xSKBNjFyzngUqsXBdcSasALiowlZCiJrGwlGX5qCkBlxXvJeUEbuJLPYVl5FBjXZ
6o00K4cSPCqtqUez7WSmDZU=
MIICpzCCAhACCQCzAF1hyRVzAjANBgkqhkiG9w0BAQUFADCBlzELMAkGA1UEBhMC
Tk8xDTALBgNVBAgTBE9zbG8xDTALBgNVBAcTBE9zbG8xDjAMBgNVBAoTBU5va2lh
MTUwMwYDVQQLFCxRdCBTb2Z0d2FyZS9lbWFpbEFkZHJlc3M9bm9ib2R5QG5vZG9t
YWluLm9yZzEjMCEGA1UEAxMacXQtdGVzdC1zZXJ2ZXIucXQtdGVzdC1uZXQwHhcN
MTkwNjI0MTI0OTIxWhcNMjIwNjIzMTI0OTIxWjCBlzELMAkGA1UEBhMCTk8xDTAL
BgNVBAgTBE9zbG8xDTALBgNVBAcTBE9zbG8xDjAMBgNVBAoTBU5va2lhMTUwMwYD
VQQLFCxRdCBTb2Z0d2FyZS9lbWFpbEFkZHJlc3M9bm9ib2R5QG5vZG9tYWluLm9y
ZzEjMCEGA1UEAxMacXQtdGVzdC1zZXJ2ZXIucXQtdGVzdC1uZXQwgZ8wDQYJKoZI
hvcNAQEBBQADgY0AMIGJAoGBAM2q22/WNMmn8cC+5EEYGeICySLmp9W6Ay6eKHr0
Xxp3X3epETuPfvAuxp7rOtkS18EMUegkUj8jw0IMEcbyHKFC/rTCaYOt93CxGBXM
IChiMPAsFeYzGa/D6xzAkfcRaJRQ+Ek3CDLXPnXfo7xpABXezYcPXAJrgsgBfWrw
HdxzAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEASCKbqEX5ysC549mq90ydk4jyDW3m
PUyet01fKpcRqVs+OJxdExFBTra3gho6WzzpTSPsuX2ZKOLF5k6KkCvdCGvhC1Kv
HHPIExurfzvdlSRzj6HbKyPuSfxyOloH0bBp7/Gg5RIuBPKlbmfbnTLtwEjhhbMU
SoYI8HZd3HfY87c=
-----END CERTIFICATE-----

View File

@ -2711,6 +2711,7 @@ void tst_QSslSocket::encryptWithoutConnecting()
void tst_QSslSocket::resume_data()
{
QSKIP("Temporary skip while updating certificates");
QTest::addColumn<bool>("ignoreErrorsAfterPause");
QTest::addColumn<QList<QSslError> >("errorsToIgnore");
QTest::addColumn<bool>("expectSuccess");

View File

@ -180,6 +180,7 @@ private slots:
void tabOrderWithProxy();
void tabOrderWithCompoundWidgets();
void tabOrderNoChange();
void tabOrderNoChange2();
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
void activation();
#endif
@ -1942,6 +1943,24 @@ static QVector<QWidget*> getFocusChain(QWidget *start, bool bForward)
return ret;
}
//#define DEBUG_FOCUS_CHAIN
static void dumpFocusChain(QWidget *start, bool bForward, const char *desc = nullptr)
{
#ifdef DEBUG_FOCUS_CHAIN
qDebug() << "Dump focus chain, start:" << start << "isForward:" << bForward << desc;
QWidget *cur = start;
do {
qDebug() << cur;
auto widgetPrivate = static_cast<QWidgetPrivate *>(qt_widget_private(cur));
cur = bForward ? widgetPrivate->focus_next : widgetPrivate->focus_prev;
} while (cur != start);
#else
Q_UNUSED(start)
Q_UNUSED(bForward)
Q_UNUSED(desc)
#endif
}
void tst_QWidget::tabOrderNoChange()
{
QWidget w;
@ -1953,7 +1972,61 @@ void tst_QWidget::tabOrderNoChange()
const auto focusChainForward = getFocusChain(&w, true);
const auto focusChainBackward = getFocusChain(&w, false);
dumpFocusChain(&w, true);
QWidget::setTabOrder(tabWidget, tv);
dumpFocusChain(&w, true);
QCOMPARE(focusChainForward, getFocusChain(&w, true));
QCOMPARE(focusChainBackward, getFocusChain(&w, false));
}
void tst_QWidget::tabOrderNoChange2()
{
QWidget w;
auto *verticalLayout = new QVBoxLayout(&w);
auto *tabWidget = new QTabWidget(&w);
tabWidget->setObjectName("tabWidget");
verticalLayout->addWidget(tabWidget);
auto *tab1 = new QWidget(tabWidget);
tab1->setObjectName("tab1");
auto *vLay1 = new QVBoxLayout(tab1);
auto *le1 = new QLineEdit(tab1);
le1->setObjectName("le1");
auto *le2 = new QLineEdit(tab1);
le2->setObjectName("le2");
vLay1->addWidget(le1);
vLay1->addWidget(le2);
tabWidget->addTab(tab1, QStringLiteral("Tab 1"));
auto *tab2 = new QWidget(tabWidget);
tab2->setObjectName("tab2");
auto *vLay2 = new QVBoxLayout(tab2);
auto *le3 = new QLineEdit(tab2);
le3->setObjectName("le3");
auto *le4 = new QLineEdit(tab2);
le4->setObjectName("le4");
vLay2->addWidget(le3);
vLay2->addWidget(le4);
tabWidget->addTab(tab2, QStringLiteral("Tab 2"));
const auto focusChainForward = getFocusChain(&w, true);
const auto focusChainBackward = getFocusChain(&w, false);
dumpFocusChain(&w, true);
dumpFocusChain(&w, false);
// this will screw up the focus chain order without visible changes,
// so don't call it here for the simplicity of the test
//QWidget::setTabOrder(tabWidget, le1);
QWidget::setTabOrder(le1, le2);
dumpFocusChain(&w, true, "QWidget::setTabOrder(le1, le2)");
QWidget::setTabOrder(le2, le3);
dumpFocusChain(&w, true, "QWidget::setTabOrder(le2, le3)");
QWidget::setTabOrder(le3, le4);
dumpFocusChain(&w, true, "QWidget::setTabOrder(le3, le4)");
QWidget::setTabOrder(le4, tabWidget);
dumpFocusChain(&w, true, "QWidget::setTabOrder(le4, tabWidget)");
dumpFocusChain(&w, false);
QCOMPARE(focusChainForward, getFocusChain(&w, true));
QCOMPARE(focusChainBackward, getFocusChain(&w, false));
}

View File

@ -735,6 +735,7 @@ void tst_QSplitter::replaceWidget()
// Configure splitter
QWidget *oldWidget = sp.widget(index);
QTest::qWait(100); // Make sure we record the right original size (after the window manager adds the frame)
const QRect oldGeom = oldWidget ? oldWidget->geometry() : QRect();
if (oldWidget) {
// Collapse first, then hide, if necessary