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

This commit is contained in:
Qt Forward Merge Bot 2019-09-08 11:33:28 +02:00
commit 72a04b132c
17 changed files with 265 additions and 61 deletions

109
dist/changes-5.12.5 vendored Normal file
View File

@ -0,0 +1,109 @@
Qt 5.12.5 is a bug-fix release. It maintains both forward and backward
compatibility (source and binary) with Qt 5.12.0 through 5.12.4.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
https://doc.qt.io/qt-5/index.html
The Qt version 5.12 series is binary compatible with the 5.11.x series.
Applications compiled for 5.11 will continue to run with 5.12.
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* QtCore *
****************************************************************************
- QBitArray:
* Fixed two bugs that caused QBitArrays created using fromBits() not to
compare equal to the equivalent QBitArray created using other methods
if the size was zero or not a multiple of 4. If the size modulus 8 was
5, 6, or 7, the data was actually incorrect.
- QCborStreamReader:
* Fixed a bug that caused the QIODevice that the data was being read
from not to show the entire CBOR message as consumed. This allows the
user to consume data that may follow the CBOR payload.
- QCryptographicHash:
* Fixed a bug that caused the SHA-3 and Keccak algorithms to crash if
passed 256 MB of data or more.
- QObject:
* Fixed a resource leak caused by a race condition if multiple QObjects
were created at the same time, for the first time in an application,
from multiple threads (implies threads not started with QThread).
- QStorageInfo:
* Fixed a bug that caused QStorageInfo to be unable to report all
filesystems if the options to mounted filesystems were too long (over
900 characters, roughly), such as those found in Docker overlay
mounts.
- QTimeZone:
* The IANA timezone database backend now properly follows symlinks even
when they point to variable locations like /run or /var (useful when
/etc is mounted read-only).
****************************************************************************
* QtGui *
****************************************************************************
- QImage:
* Improve loading time when loading png files that have the same size as
the target.
- QPixmapCache:
* [QTBUG-76694][QTBUG-72523] Ignore unsafe access from non-main threads
- Text:
* [QTBUG-76219] Fixed a bug which could cause the font cache to grow
larger than it was supposed to.
* [QTBUG-55096][QTBUG-74761] Fixed bug where regular text rendered with
a color font would always display in black.
* [QTBUG-69546] Fixed a crash bug in
QTextDocument::clearUndoRedoStacks(QTextDocument::UndoStack).
****************************************************************************
* QtNetwork *
****************************************************************************
- QHostInfo:
* Functors used in the lookupHost overloads are now called correctly in
the thread of the context object. When used without context object,
the thread that initiates the lookup will run the functor, and is
required to run an event loop.
- Windows:
* Correctly emit errors when trying to reach unreachable hosts or
services
****************************************************************************
* QtWidgets *
****************************************************************************
- QGraphicsView:
* Ignore disabled items when setting the mouse cursor.
- QSplashScreen:
* On macOS, lower the splash screen when a modal dialog is shown to make
sure the user sees the dialog.
- QSystemTrayIcon:
* On macOS, show the icon passed into showMessage in the notification
popup
****************************************************************************
* Android *
****************************************************************************
- [QTBUG-76293] Fix NDK r20 linking.
- [QTBUG-76036] Fixed an issue where menus would not work on 64 bit
builds.

View File

@ -8,7 +8,7 @@ QMAKE_MAC_SDK = macosx
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.12
QMAKE_APPLE_DEVICE_ARCHS = x86_64
QT_MAC_SDK_VERSION_MIN = 10.13
QT_MAC_SDK_VERSION_MAX = 10.14
QT_MAC_SDK_VERSION_MAX = 10.15
device.sdk = macosx
device.target = device

View File

@ -514,6 +514,56 @@ static QList<QVariantMap> provisioningTeams()
return flatTeams;
}
bool ProjectBuilderMakefileGenerator::replaceLibrarySuffix(const QString &lib_file,
const ProString &opt,
QString &name, QString &library)
{
/* This isn't real nice, but it is real useful. This looks in a prl
for what the library will ultimately be called so we can stick it
in the ProjectFile. If the prl format ever changes (not likely) then
this will not really work. However, more concerning is that it will
encode the version number in the Project file which might be a bad
things in days to come? --Sam
*/
if (lib_file.isEmpty())
return false;
QMakeMetaInfo libinfo;
if (!libinfo.readLib(lib_file) || libinfo.isEmpty("QMAKE_PRL_TARGET"))
return false;
const QString libDir = fileInfo(lib_file).absolutePath();
library = libDir + Option::dir_sep + libinfo.first("QMAKE_PRL_TARGET");
debug_msg(1, "pbuilder: Found library (%s) via PRL %s (%s)",
opt.toLatin1().constData(), lib_file.toLatin1().constData(), library.toLatin1().constData());
if (project->isActiveConfig("xcode_dynamic_library_suffix")) {
QString suffixSetting = project->first("QMAKE_XCODE_LIBRARY_SUFFIX_SETTING").toQString();
if (!suffixSetting.isEmpty()) {
QString librarySuffix = project->first("QMAKE_XCODE_LIBRARY_SUFFIX").toQString();
suffixSetting = "$(" + suffixSetting + ")";
if (!librarySuffix.isEmpty()) {
int pos = library.lastIndexOf(librarySuffix + '.');
if (pos == -1) {
warn_msg(WarnLogic, "Failed to find expected suffix '%s' for library '%s'.",
qPrintable(librarySuffix), qPrintable(library));
} else {
library.replace(pos, librarySuffix.length(), suffixSetting);
if (name.endsWith(librarySuffix))
name.chop(librarySuffix.length());
}
} else {
int pos = library.lastIndexOf(name);
if (pos != -1)
library.insert(pos + name.length(), suffixSetting);
}
}
}
return true;
}
bool
ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
{
@ -833,6 +883,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
for (int i = 0; libs[i]; i++) {
tmp = project->values(libs[i]);
for(int x = 0; x < tmp.count();) {
bool libSuffixReplaced = false;
bool remove = false;
QString library, name;
ProString opt = tmp[x];
@ -845,49 +896,12 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
QString lib("lib" + name);
for (ProStringList::Iterator lit = libdirs.begin(); lit != libdirs.end(); ++lit) {
if(project->isActiveConfig("link_prl")) {
/* This isn't real nice, but it is real useful. This looks in a prl
for what the library will ultimately be called so we can stick it
in the ProjectFile. If the prl format ever changes (not likely) then
this will not really work. However, more concerning is that it will
encode the version number in the Project file which might be a bad
things in days to come? --Sam
*/
QString lib_file = QMakeMetaInfo::checkLib(Option::normalizePath(
(*lit) + Option::dir_sep + lib + Option::prl_ext));
if (!lib_file.isEmpty()) {
QMakeMetaInfo libinfo;
if(libinfo.readLib(lib_file)) {
if(!libinfo.isEmpty("QMAKE_PRL_TARGET")) {
library = (*lit) + Option::dir_sep + libinfo.first("QMAKE_PRL_TARGET");
debug_msg(1, "pbuilder: Found library (%s) via PRL %s (%s)",
opt.toLatin1().constData(), lib_file.toLatin1().constData(), library.toLatin1().constData());
remove = true;
if (project->isActiveConfig("xcode_dynamic_library_suffix")) {
QString suffixSetting = project->first("QMAKE_XCODE_LIBRARY_SUFFIX_SETTING").toQString();
if (!suffixSetting.isEmpty()) {
QString librarySuffix = project->first("QMAKE_XCODE_LIBRARY_SUFFIX").toQString();
suffixSetting = "$(" + suffixSetting + ")";
if (!librarySuffix.isEmpty()) {
int pos = library.lastIndexOf(librarySuffix + '.');
if (pos == -1) {
warn_msg(WarnLogic, "Failed to find expected suffix '%s' for library '%s'.",
qPrintable(librarySuffix), qPrintable(library));
} else {
library.replace(pos, librarySuffix.length(), suffixSetting);
if (name.endsWith(librarySuffix))
name.chop(librarySuffix.length());
}
} else {
int pos = library.lastIndexOf(name);
if (pos != -1)
library.insert(pos + name.length(), suffixSetting);
}
}
}
}
}
}
const QString prlFilePath = QMakeMetaInfo::checkLib(
Option::normalizePath((*lit) + Option::dir_sep + lib
+ Option::prl_ext));
if (replaceLibrarySuffix(prlFilePath, opt, name, library))
remove = true;
libSuffixReplaced = true;
}
if(!remove) {
QString extns[] = { ".dylib", ".so", ".a", QString() };
@ -937,6 +951,16 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
}
}
if(!library.isEmpty()) {
if (!libSuffixReplaced) {
const QFileInfo fi = fileInfo(library);
const QString prlFilePath = QMakeMetaInfo::checkLib(
Option::normalizePath(fi.absolutePath() + '/' + fi.completeBaseName()
+ Option::prl_ext));
if (!prlFilePath.isEmpty()) {
name = fi.completeBaseName().mid(3);
replaceLibrarySuffix(prlFilePath, opt, name, library);
}
}
const int slsh = library.lastIndexOf(Option::dir_sep);
if(name.isEmpty()) {
if(slsh != -1)

View File

@ -41,6 +41,8 @@ class ProjectBuilderMakefileGenerator : public UnixMakefileGenerator
bool writeSubDirs(QTextStream &);
bool writeMakeParts(QTextStream &);
bool writeMakefile(QTextStream &) override;
bool replaceLibrarySuffix(const QString &lib_file, const ProString &opt, QString &name,
QString &library);
QString pbxbuild();
QHash<QString, QString> keys;

View File

@ -1814,8 +1814,8 @@ static void qt_message_print(QtMsgType msgType, const QMessageLogContext &contex
#ifndef QT_BOOTSTRAPPED
Q_TRACE(qt_message_print, msgType, context.category, context.function, context.file, context.line, message);
// qDebug, qWarning, ... macros do not check whether category is enabled
if (isDefaultCategory(context.category)) {
// qDebug, qWarning, ... macros do not check whether category is enabledgc
if (msgType != QtFatalMsg && isDefaultCategory(context.category)) {
if (QLoggingCategory *defaultCategory = QLoggingCategory::defaultCategory()) {
if (!defaultCategory->isEnabled(msgType))
return;

View File

@ -281,7 +281,7 @@ static quint32 icon_name_hash(const char *p)
QVector<const char *> QIconCacheGtkReader::lookup(const QStringRef &name)
{
QVector<const char *> ret;
if (!isValid())
if (!isValid() || name.isEmpty())
return ret;
QByteArray nameUtf8 = name.toUtf8();

View File

@ -2697,7 +2697,7 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
QWindow *window = e->window.data();
typedef QPair<Qt::TouchPointStates, QList<QTouchEvent::TouchPoint> > StatesAndTouchPoints;
QHash<QWindow *, StatesAndTouchPoints> windowsNeedingEvents;
bool stationaryTouchPointChangedVelocity = false;
bool stationaryTouchPointChangedProperty = false;
for (int i = 0; i < e->points.count(); ++i) {
QTouchEvent::TouchPoint touchPoint = e->points.at(i);
@ -2777,7 +2777,11 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
if (touchPoint.state() == Qt::TouchPointStationary) {
if (touchInfo.touchPoint.velocity() != touchPoint.velocity()) {
touchInfo.touchPoint.setVelocity(touchPoint.velocity());
stationaryTouchPointChangedVelocity = true;
stationaryTouchPointChangedProperty = true;
}
if (!qFuzzyCompare(touchInfo.touchPoint.pressure(), touchPoint.pressure())) {
touchInfo.touchPoint.setPressure(touchPoint.pressure());
stationaryTouchPointChangedProperty = true;
}
} else {
touchInfo.touchPoint = touchPoint;
@ -2818,7 +2822,7 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
break;
case Qt::TouchPointStationary:
// don't send the event if nothing changed
if (!stationaryTouchPointChangedVelocity)
if (!stationaryTouchPointChangedProperty)
continue;
Q_FALLTHROUGH();
default:

View File

@ -55,6 +55,8 @@
#include <QtNetwork/qnetworkproxy.h>
#endif
#include <qcoreapplication.h>
#include <algorithm>
#include <vector>
@ -211,6 +213,29 @@ QHttp2ProtocolHandler::QHttp2ProtocolHandler(QHttpNetworkConnectionChannel *chan
}
}
void QHttp2ProtocolHandler::handleConnectionClosure()
{
// The channel has just received RemoteHostClosedError and since it will
// not try (for HTTP/2) to re-connect, it's time to finish all replies
// with error.
// Maybe we still have some data to read and can successfully finish
// a stream/request?
_q_receiveReply();
// Finish all still active streams. If we previously had GOAWAY frame,
// we probably already closed some (or all) streams with ContentReSend
// error, but for those still active, not having any data to finish,
// we now report RemoteHostClosedError.
const auto errorString = QCoreApplication::translate("QHttp", "Connection closed");
for (auto it = activeStreams.begin(), eIt = activeStreams.end(); it != eIt; ++it)
finishStreamWithError(it.value(), QNetworkReply::RemoteHostClosedError, errorString);
// Make sure we'll never try to read anything later:
activeStreams.clear();
goingAway = true;
}
void QHttp2ProtocolHandler::_q_uploadDataReadyRead()
{
if (!sender()) // QueuedConnection, firing after sender (byte device) was deleted.

View File

@ -90,6 +90,8 @@ public:
QHttp2ProtocolHandler &operator = (const QHttp2ProtocolHandler &rhs) = delete;
QHttp2ProtocolHandler &operator = (QHttp2ProtocolHandler &&rhs) = delete;
Q_INVOKABLE void handleConnectionClosure();
private slots:
void _q_uploadDataReadyRead();
void _q_replyDestroyed(QObject* reply);

View File

@ -850,8 +850,11 @@ void QHttpNetworkConnectionChannel::_q_disconnected()
QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
}
state = QHttpNetworkConnectionChannel::IdleState;
requeueCurrentlyPipelinedRequests();
if (alreadyPipelinedRequests.length()) {
// If nothing was in a pipeline, no need in calling
// _q_startNextRequest (which it does):
requeueCurrentlyPipelinedRequests();
}
pendingEncrypt = false;
}
@ -965,7 +968,18 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
if (!reply && state == QHttpNetworkConnectionChannel::IdleState) {
// Not actually an error, it is normal for Keep-Alive connections to close after some time if no request
// is sent on them. No need to error the other replies below. Just bail out here.
// The _q_disconnected will handle the possibly pipelined replies
// The _q_disconnected will handle the possibly pipelined replies. HTTP/2 is special for now,
// we do not resend, but must report errors if any request is in progress (note, while
// not in its sendRequest(), protocol handler switches the channel to IdleState, thus
// this check is under this condition in 'if'):
if (protocolHandler.data()) {
if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2Direct
|| connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2) {
auto h2Handler = static_cast<QHttp2ProtocolHandler *>(protocolHandler.data());
h2Handler->handleConnectionClosure();
protocolHandler.reset();
}
}
return;
} else if (state != QHttpNetworkConnectionChannel::IdleState && state != QHttpNetworkConnectionChannel::ReadingState) {
// Try to reconnect/resend before sending an error.

View File

@ -532,7 +532,7 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data)
m_currentData.state = Qt::TouchPointReleased;
if (m_typeB)
m_contacts[m_currentSlot].maj = m_currentData.maj;
} else if (data->code == ABS_PRESSURE) {
} else if (data->code == ABS_PRESSURE || data->code == ABS_MT_PRESSURE) {
m_currentData.pressure = qBound(hw_pressure_min, data->value, hw_pressure_max);
if (m_typeB || m_singleTouch)
m_contacts[m_currentSlot].pressure = m_currentData.pressure;

View File

@ -42,6 +42,7 @@
#include "qwindowswindow.h"
#include "qwindowsintegration.h"
#include "qwindowscursor.h"
#include "qwindowstheme.h"
#include <QtCore/qt_windows.h>
@ -547,10 +548,13 @@ bool QWindowsScreenManager::handleScreenChanges()
// Look for changed monitors, add new ones
const WindowsScreenDataList newDataList = monitorData();
const bool lockScreen = newDataList.size() == 1 && (newDataList.front().flags & QWindowsScreenData::LockScreen);
bool primaryScreenChanged = false;
for (const QWindowsScreenData &newData : newDataList) {
const int existingIndex = indexOfMonitor(m_screens, newData.name);
if (existingIndex != -1) {
m_screens.at(existingIndex)->handleChanges(newData);
if (existingIndex == 0)
primaryScreenChanged = true;
} else {
QWindowsScreen *newScreen = new QWindowsScreen(newData);
m_screens.push_back(newScreen);
@ -567,6 +571,8 @@ bool QWindowsScreenManager::handleScreenChanges()
removeScreen(i);
} // for existing screens
} // not lock screen
if (primaryScreenChanged)
QWindowsTheme::instance()->refreshFonts();
return true;
}

View File

@ -85,6 +85,8 @@ public:
static bool useNativeMenus();
void refreshFonts();
static const char *name;
private:
@ -92,7 +94,6 @@ private:
void clearPalettes();
void refreshPalettes();
void clearFonts();
void refreshFonts();
void refreshIconPixmapSizes();
static QWindowsTheme *m_instance;

View File

@ -665,24 +665,22 @@ int QShortcut::id() const
bool QShortcut::event(QEvent *e)
{
Q_D(QShortcut);
bool handled = false;
if (d->sc_enabled && e->type() == QEvent::Shortcut) {
QShortcutEvent *se = static_cast<QShortcutEvent *>(e);
if (se->shortcutId() == d->sc_id && se->key() == d->sc_sequence){
#if QT_CONFIG(whatsthis)
if (QWhatsThis::inWhatsThisMode()) {
QWhatsThis::showText(QCursor::pos(), d->sc_whatsthis);
handled = true;
} else
#endif
if (se->isAmbiguous())
emit activatedAmbiguously();
else
emit activated();
handled = true;
return true;
}
}
return handled;
return QObject::event(e);
}
#endif // QT_NO_SHORTCUT

View File

@ -456,6 +456,9 @@ void tst_Http2::goaway_data()
// - server waits for some time (enough for ur to init several streams on a
// client side); then suddenly it replies with GOAWAY, never processing any
// request.
if (clearTextHTTP2)
QSKIP("This test requires TLS with ALPN to work");
QTest::addColumn<int>("responseTimeoutMS");
QTest::newRow("ImmediateGOAWAY") << 0;
QTest::newRow("DelayedGOAWAY") << 1000;

View File

@ -1010,7 +1010,10 @@ void PaintCommands::command_drawPixmap(QRegularExpressionMatch re)
qPrintable(re.captured(1)), pm.width(), pm.height(), pm.depth(),
tx, ty, tw, th, sx, sy, sw, sh);
m_painter->drawPixmap(QRectF(tx, ty, tw, th), pm, QRectF(sx, sy, sw, sh));
if (!re.capturedLength(4)) // at most two coordinates specified
m_painter->drawPixmap(QPointF(tx, ty), pm);
else
m_painter->drawPixmap(QRectF(tx, ty, tw, th), pm, QRectF(sx, sy, sw, sh));
}
/***************************************************************************************************/
@ -1057,7 +1060,10 @@ void PaintCommands::command_drawImage(QRegularExpressionMatch re)
printf(" -(lance) drawImage('%s' dim=(%d, %d), (%f, %f, %f, %f), (%f, %f, %f, %f)\n",
qPrintable(re.captured(1)), im.width(), im.height(), tx, ty, tw, th, sx, sy, sw, sh);
m_painter->drawImage(QRectF(tx, ty, tw, th), im, QRectF(sx, sy, sw, sh), Qt::OrderedDither | Qt::OrderedAlphaDither);
if (!re.capturedLength(4)) // at most two coordinates specified
m_painter->drawImage(QPointF(tx, ty), im);
else
m_painter->drawImage(QRectF(tx, ty, tw, th), im, QRectF(sx, sy, sw, sh));
}
/***************************************************************************************************/

View File

@ -123,6 +123,7 @@ private slots:
void context();
void duplicatedShortcutOverride();
void shortcutToFocusProxy();
void deleteLater();
protected:
static Qt::KeyboardModifiers toButtons( int key );
@ -1305,5 +1306,14 @@ void tst_QShortcut::shortcutToFocusProxy()
QCOMPARE(le.text(), QString());
}
void tst_QShortcut::deleteLater()
{
QWidget w;
QPointer<QShortcut> sc(new QShortcut(QKeySequence(Qt::Key_1), &w));
sc->deleteLater();
QTRY_VERIFY(!sc);
}
QTEST_MAIN(tst_QShortcut)
#include "tst_qshortcut.moc"