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

This commit is contained in:
Liang Qi 2019-04-09 19:43:30 +00:00 committed by The Qt Project
commit ac244dbcf2
14 changed files with 203 additions and 64 deletions

View File

@ -260,25 +260,31 @@ static int installFile(const QString &source, const QString &target, bool exe =
return 3;
}
QFileDevice::Permissions targetPermissions = QFileDevice::ReadOwner | QFileDevice::WriteOwner
| QFileDevice::ReadUser | QFileDevice::WriteUser
| QFileDevice::ReadGroup | QFileDevice::ReadOther;
if (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()));
return 3;
if (!targetFile.setPermissions(sourceFile.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeUser |
QFileDevice::ExeGroup | QFileDevice::ExeOther)) {
fprintf(stderr, "Error setting execute permissions on %s: %s\n",
qPrintable(target), qPrintable(targetFile.errorString()));
return 3;
}
}
// Copy file times
QString error;
#ifdef Q_OS_WIN
const QFile::Permissions permissions = targetFile.permissions();
const bool readOnly = !(permissions & QFile::WriteUser);
if (readOnly)
targetFile.setPermissions(permissions | QFile::WriteUser);
#endif
if (!IoUtils::touchFile(target, sourceFile.fileName(), &error)) {
fprintf(stderr, "%s", qPrintable(error));
return 3;
}
#ifdef Q_OS_WIN
if (readOnly)
targetFile.setPermissions(permissions);
#endif
return 0;
}

2
src/3rdparty/wintab/LICENSE.txt vendored Normal file
View File

@ -0,0 +1,2 @@
The text and information contained in this file may be freely used,
copied, or distributed without compensation or licensing restrictions.

View File

@ -5,9 +5,9 @@
"QtUsage": "Used in the Qt platform plugin for Windows. Configure with -no-feature-tabletevent to avoid.",
"Description": "Wintab is a de facto API for pointing devices on Windows.",
"Version": "Upstream no longer offers updates; treat as final",
"Homepage": "http://www.pointing.com/Wintab.html",
"License": "Public Domain",
"PackageComment": "Upstream http://www.pointing.com/Wintab.html no longer offers updates; treat as final",
"License": "Custom License",
"LicenseFile": "LICENSE.txt",
"LicenseId": "NONE",
"Copyright": "Copyright 1991-1998 by LCS/Telegraphics."
}

View File

@ -140,6 +140,10 @@ public:
// Inlined for its one caller in qdatetime.cpp
inline void setUtcOffsetByTZ(qint64 atMSecsSinceEpoch);
#endif // timezone
// ### Qt 5.14: expose publicly in QDateTime
// The first and last years of which QDateTime can represent some part:
enum class YearRange : qint32 { First = -292275056, Last = +292278994 };
};
QT_END_NAMESPACE

View File

@ -39,6 +39,7 @@
#include "qtimezone.h"
#include "qtimezoneprivate_p.h"
#include "qdatetime_p.h" // ### Qt 5.14: remove once YearRange is on QDateTime
#include <QtCore/QFile>
#include <QtCore/QHash>
@ -520,19 +521,14 @@ PosixZone PosixZone::parse(const char *&pos, const char *end)
static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArray &posixRule,
int startYear, int endYear,
int lastTranMSecs)
qint64 lastTranMSecs)
{
QVector<QTimeZonePrivate::Data> result;
// Limit year by qint64 max size for msecs
if (startYear > 292278994)
startYear = 292278994;
if (endYear > 292278994)
endYear = 292278994;
// POSIX Format is like "TZ=CST6CDT,M3.2.0/2:00:00,M11.1.0/2:00:00"
// i.e. "std offset dst [offset],start[/time],end[/time]"
// See the section about TZ at http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html
// See the section about TZ at
// http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html
QList<QByteArray> parts = posixRule.split(',');
PosixZone stdZone, dstZone = PosixZone::invalid();
@ -583,6 +579,13 @@ static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArra
else
stdTime = QTime(2, 0, 0);
// Limit year to the range QDateTime can represent:
const int minYear = int(QDateTimePrivate::YearRange::First);
const int maxYear = int(QDateTimePrivate::YearRange::Last);
startYear = qBound(minYear, startYear, maxYear);
endYear = qBound(minYear, endYear, maxYear);
Q_ASSERT(startYear <= endYear);
for (int year = startYear; year <= endYear; ++year) {
QTimeZonePrivate::Data dstData;
QDateTime dst(calculatePosixDate(dstDateRule, year), dstTime, Qt::UTC);
@ -598,13 +601,16 @@ static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArra
stdData.standardTimeOffset = stdZone.offset;
stdData.daylightTimeOffset = 0;
stdData.abbreviation = stdZone.name;
// Part of the high year will overflow
if (year == 292278994 && (dstData.atMSecsSinceEpoch < 0 || stdData.atMSecsSinceEpoch < 0)) {
// Part of maxYear will overflow (likewise for minYear, below):
if (year == maxYear && (dstData.atMSecsSinceEpoch < 0 || stdData.atMSecsSinceEpoch < 0)) {
if (dstData.atMSecsSinceEpoch > 0) {
result << dstData;
} else if (stdData.atMSecsSinceEpoch > 0) {
result << stdData;
}
} else if (year < 1970) { // We ignore DST before the epoch.
if (year > minYear || stdData.atMSecsSinceEpoch != QTimeZonePrivate::invalidMSecs())
result << stdData;
} else if (dst < std) {
result << dstData << stdData;
} else {
@ -794,6 +800,8 @@ void QTzTimeZonePrivate::init(const QByteArray &ianaId)
tran.atMSecsSinceEpoch = tz_tran.tz_time * 1000;
m_tranTimes.append(tran);
}
if (m_tranTimes.isEmpty() && m_posixRule.isEmpty())
return; // Invalid after all !
if (ianaId.isEmpty())
m_id = systemTimeZoneId();
@ -954,22 +962,25 @@ QVector<QTimeZonePrivate::Data> QTzTimeZonePrivate::getPosixTransitions(qint64 m
QTimeZonePrivate::Data QTzTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
{
// If the required time is after the last transition (or there were none)
// and we have a POSIX rule then use it:
if ((m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < forMSecsSinceEpoch)
&& !m_posixRule.isEmpty() && forMSecsSinceEpoch >= 0) {
// and we have a POSIX rule, then use it:
if (!m_posixRule.isEmpty()
&& (m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < forMSecsSinceEpoch)) {
QVector<QTimeZonePrivate::Data> posixTrans = getPosixTransitions(forMSecsSinceEpoch);
auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
[forMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {
return at.atMSecsSinceEpoch <= forMSecsSinceEpoch;
});
if (it > posixTrans.cbegin()) {
QTimeZonePrivate::Data data = *--it;
// Use most recent, if any in the past; or the first if we have no other rules:
if (it > posixTrans.cbegin() || (m_tranTimes.isEmpty() && it < posixTrans.cend())) {
QTimeZonePrivate::Data data = *(it > posixTrans.cbegin() ? it - 1 : it);
data.atMSecsSinceEpoch = forMSecsSinceEpoch;
return data;
}
}
if (m_tranTimes.isEmpty()) // Only possible if !isValid()
return invalidData();
// Otherwise, if we can find a valid tran, then use its rule:
// Otherwise, use the rule for the most recent or first transition:
auto last = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(),
[forMSecsSinceEpoch] (const QTzTransitionTime &at) {
return at.atMSecsSinceEpoch <= forMSecsSinceEpoch;
@ -989,9 +1000,9 @@ bool QTzTimeZonePrivate::hasTransitions() const
QTimeZonePrivate::Data QTzTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch) const
{
// If the required time is after the last transition (or there were none)
// and we have a POSIX rule then use it:
if ((m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < afterMSecsSinceEpoch)
&& !m_posixRule.isEmpty() && afterMSecsSinceEpoch >= 0) {
// and we have a POSIX rule, then use it:
if (!m_posixRule.isEmpty()
&& (m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < afterMSecsSinceEpoch)) {
QVector<QTimeZonePrivate::Data> posixTrans = getPosixTransitions(afterMSecsSinceEpoch);
auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
[afterMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {
@ -1012,9 +1023,9 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::nextTransition(qint64 afterMSecsSince
QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
{
// If the required time is after the last transition (or there were none)
// and we have a POSIX rule then use it:
if ((m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < beforeMSecsSinceEpoch)
&& !m_posixRule.isEmpty() && beforeMSecsSinceEpoch > 0) {
// and we have a POSIX rule, then use it:
if (!m_posixRule.isEmpty()
&& (m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < beforeMSecsSinceEpoch)) {
QVector<QTimeZonePrivate::Data> posixTrans = getPosixTransitions(beforeMSecsSinceEpoch);
auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
[beforeMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {

View File

@ -764,7 +764,8 @@
},
"headers": [ "xkbcommon/xkbcommon.h" ],
"sources": [
{ "type": "pkgConfig", "args": "xkbcommon >= 0.5.0" }
{ "type": "pkgConfig", "args": "xkbcommon >= 0.5.0" },
"-lxkbcommon"
]
},
"xkbcommon_x11": {
@ -774,7 +775,8 @@
},
"headers": [ "xkbcommon/xkbcommon-x11.h" ],
"sources": [
{ "type": "pkgConfig", "args": "xkbcommon-x11" }
{ "type": "pkgConfig", "args": "xkbcommon-x11" },
"-lxkbcommon -lxkbcommon-x11"
]
},
"xrender": {

View File

@ -54,8 +54,8 @@ void Server::initSocket()
udpSocket = new QUdpSocket(this);
udpSocket->bind(QHostAddress::LocalHost, 7755);
connect(udpSocket, SIGNAL(readyRead()),
this, SLOT(readPendingDatagrams()));
connect(udpSocket, &QUdpSocket::readyRead,
this, &Server::readPendingDatagrams);
}
void Server::readPendingDatagrams()

View File

@ -39,8 +39,11 @@ qtConfig(dnslookup) {
unix {
!integrity:qtConfig(dnslookup): SOURCES += kernel/qdnslookup_unix.cpp
SOURCES += kernel/qhostinfo_unix.cpp
qtConfig(dlopen): QMAKE_USE_PRIVATE += libdl
qtConfig(linux-netlink): SOURCES += kernel/qnetworkinterface_linux.cpp
else: SOURCES += kernel/qnetworkinterface_unix.cpp
}

View File

@ -59,6 +59,10 @@
# include <gnu/lib-names.h>
#endif
#if defined(Q_OS_FREEBSD) || QT_CONFIG(dlopen)
# include <dlfcn.h>
#endif
#include <cstring>
QT_BEGIN_NAMESPACE
@ -87,6 +91,18 @@ struct QDnsLookupStateDeleter
}
};
static QFunctionPointer resolveSymbol(QLibrary &lib, const char *sym)
{
if (lib.isLoaded())
return lib.resolve(sym);
#if defined(RTLD_DEFAULT) && (defined(Q_OS_FREEBSD) || QT_CONFIG(dlopen))
return reinterpret_cast<QFunctionPointer>(dlsym(RTLD_DEFAULT, sym));
#else
return nullptr;
#endif
}
static bool resolveLibraryInternal()
{
QLibrary lib;
@ -96,31 +112,30 @@ static bool resolveLibraryInternal()
#endif
{
lib.setFileName(QLatin1String("resolv"));
if (!lib.load())
return false;
lib.load();
}
local_dn_expand = dn_expand_proto(lib.resolve("__dn_expand"));
local_dn_expand = dn_expand_proto(resolveSymbol(lib, "__dn_expand"));
if (!local_dn_expand)
local_dn_expand = dn_expand_proto(lib.resolve("dn_expand"));
local_dn_expand = dn_expand_proto(resolveSymbol(lib, "dn_expand"));
local_res_nclose = res_nclose_proto(lib.resolve("__res_nclose"));
local_res_nclose = res_nclose_proto(resolveSymbol(lib, "__res_nclose"));
if (!local_res_nclose)
local_res_nclose = res_nclose_proto(lib.resolve("res_9_nclose"));
local_res_nclose = res_nclose_proto(resolveSymbol(lib, "res_9_nclose"));
if (!local_res_nclose)
local_res_nclose = res_nclose_proto(lib.resolve("res_nclose"));
local_res_nclose = res_nclose_proto(resolveSymbol(lib, "res_nclose"));
local_res_ninit = res_ninit_proto(lib.resolve("__res_ninit"));
local_res_ninit = res_ninit_proto(resolveSymbol(lib, "__res_ninit"));
if (!local_res_ninit)
local_res_ninit = res_ninit_proto(lib.resolve("res_9_ninit"));
local_res_ninit = res_ninit_proto(resolveSymbol(lib, "res_9_ninit"));
if (!local_res_ninit)
local_res_ninit = res_ninit_proto(lib.resolve("res_ninit"));
local_res_ninit = res_ninit_proto(resolveSymbol(lib, "res_ninit"));
local_res_nquery = res_nquery_proto(lib.resolve("__res_nquery"));
local_res_nquery = res_nquery_proto(resolveSymbol(lib, "__res_nquery"));
if (!local_res_nquery)
local_res_nquery = res_nquery_proto(lib.resolve("res_9_nquery"));
local_res_nquery = res_nquery_proto(resolveSymbol(lib, "res_9_nquery"));
if (!local_res_nquery)
local_res_nquery = res_nquery_proto(lib.resolve("res_nquery"));
local_res_nquery = res_nquery_proto(resolveSymbol(lib, "res_nquery"));
return true;
}

View File

@ -66,6 +66,10 @@
# include <gnu/lib-names.h>
#endif
#if defined(Q_OS_FREEBSD) || QT_CONFIG(dlopen)
# include <dlfcn.h>
#endif
QT_BEGIN_NAMESPACE
// Almost always the same. If not, specify in qplatformdefs.h.
@ -115,6 +119,18 @@ struct LibResolv
};
}
static QFunctionPointer resolveSymbol(QLibrary &lib, const char *sym)
{
if (lib.isLoaded())
return lib.resolve(sym);
#if defined(RTLD_DEFAULT) && (defined(Q_OS_FREEBSD) || QT_CONFIG(dlopen))
return reinterpret_cast<QFunctionPointer>(dlsym(RTLD_DEFAULT, sym));
#else
return nullptr;
#endif
}
LibResolv::LibResolv()
{
QLibrary lib;
@ -124,31 +140,30 @@ LibResolv::LibResolv()
#endif
{
lib.setFileName(QLatin1String("resolv"));
if (!lib.load())
return;
lib.load();
}
// res_ninit is required for localDomainName()
local_res_ninit = res_ninit_proto(lib.resolve("__res_ninit"));
local_res_ninit = res_ninit_proto(resolveSymbol(lib, "__res_ninit"));
if (!local_res_ninit)
local_res_ninit = res_ninit_proto(lib.resolve("res_ninit"));
local_res_ninit = res_ninit_proto(resolveSymbol(lib, "res_ninit"));
if (local_res_ninit) {
// we must now find res_nclose
local_res_nclose = res_nclose_proto(lib.resolve("res_nclose"));
local_res_nclose = res_nclose_proto(resolveSymbol(lib, "res_nclose"));
if (!local_res_nclose)
local_res_nclose = res_nclose_proto(lib.resolve("__res_nclose"));
local_res_nclose = res_nclose_proto(resolveSymbol(lib, "__res_nclose"));
if (!local_res_nclose)
local_res_ninit = nullptr;
}
if (ReinitNecessary || !local_res_ninit) {
local_res_init = res_init_proto(lib.resolve("__res_init"));
local_res_init = res_init_proto(resolveSymbol(lib, "__res_init"));
if (!local_res_init)
local_res_init = res_init_proto(lib.resolve("res_init"));
local_res_init = res_init_proto(resolveSymbol(lib, "res_init"));
if (local_res_init && !local_res_ninit) {
// if we can't get a thread-safe context, we have to use the global _res state
local_res = res_state_ptr(lib.resolve("_res"));
local_res = res_state_ptr(resolveSymbol(lib, "_res"));
}
}
}

View File

@ -381,6 +381,7 @@ qint64 QUdpSocket::writeDatagram(const char *data, qint64 size, const QHostAddre
*/
/*!
\since 5.8
\overload
Sends the datagram \a datagram to the host address and port numbers
@ -431,6 +432,8 @@ qint64 QUdpSocket::writeDatagram(const QNetworkDatagram &datagram)
}
/*!
\since 5.8
Receives a datagram no larger than \a maxSize bytes and returns it in the
QNetworkDatagram object, along with the sender's host address and port. If
possible, this function will also try to determine the datagram's

View File

@ -878,8 +878,6 @@ void QWidgetWindow::handleDragEnterEvent(QDragEnterEvent *event, QWidget *widget
const QPoint mapped = widget->mapFromGlobal(m_widget->mapToGlobal(event->pos()));
QDragEnterEvent translated(mapped, event->possibleActions(), event->mimeData(),
event->mouseButtons(), event->keyboardModifiers());
translated.setDropAction(event->dropAction());
translated.setAccepted(event->isAccepted());
QGuiApplication::forwardEvent(m_dragTarget, &translated, event);
event->setAccepted(translated.isAccepted());
event->setDropAction(translated.dropAction());

View File

@ -539,8 +539,13 @@ void tst_QTimeZone::checkOffset_data()
int year, month, day, hour, min, sec;
int std, dst;
} table[] = {
// Zone with no transitions (QTBUG-74614, when TZ backend uses minimalist data)
// Zone with no transitions (QTBUG-74614, QTBUG-74666, when TZ backend uses minimal data)
{ "Etc/UTC", "epoch", 1970, 1, 1, 0, 0, 0, 0, 0 },
{ "Etc/UTC", "pre_int32", 1901, 12, 13, 20, 45, 51, 0, 0 },
{ "Etc/UTC", "post_int32", 2038, 1, 19, 3, 14, 9, 0, 0 },
{ "Etc/UTC", "post_uint32", 2106, 2, 7, 6, 28, 17, 0, 0 },
{ "Etc/UTC", "initial", -292275056, 5, 16, 16, 47, 5, 0, 0 },
{ "Etc/UTC", "final", 292278994, 8, 17, 7, 12, 55, 0, 0 },
// Kiev: regression test for QTBUG-64122 (on MS):
{ "Europe/Kiev", "summer", 2017, 10, 27, 12, 0, 0, 2 * 3600, 3600 },
{ "Europe/Kiev", "winter", 2017, 10, 29, 12, 0, 0, 2 * 3600, 0 }

View File

@ -46,6 +46,9 @@
#include <private/qwindow_p.h>
#include <private/qguiapplication_p.h>
#include <qpa/qplatformintegration.h>
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatformdrag.h>
#include <private/qhighdpiscaling_p.h>
#include <QtTest/private/qtesthelpers_p.h>
@ -87,6 +90,7 @@ private slots:
#if QT_CONFIG(draganddrop)
void tst_dnd();
void tst_dnd_events();
void tst_dnd_propagation();
#endif
void tst_qtbug35600();
@ -744,6 +748,77 @@ void tst_QWidget_window::tst_dnd_events()
QCOMPARE(dndWidget._dndEvents, expectedDndEvents);
}
class DropTarget : public QWidget
{
public:
explicit DropTarget()
{
setAcceptDrops(true);
const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry();
auto width = availableGeometry.width() / 6;
auto height = availableGeometry.height() / 4;
setGeometry(availableGeometry.x() + 200, availableGeometry.y() + 200, width, height);
QLabel *label = new QLabel(QStringLiteral("Test"), this);
label->setGeometry(40, 40, 60, 60);
label->setAcceptDrops(true);
}
void dragEnterEvent(QDragEnterEvent *event) override
{
event->accept();
mDndEvents.append("enter ");
}
void dragMoveEvent(QDragMoveEvent *event) override
{
event->acceptProposedAction();
}
void dragLeaveEvent(QDragLeaveEvent *) override
{
mDndEvents.append("leave ");
}
void dropEvent(QDropEvent *event) override
{
event->accept();
mDndEvents.append("drop ");
}
QString mDndEvents;
};
void tst_QWidget_window::tst_dnd_propagation()
{
QMimeData mimeData;
mimeData.setText(QLatin1String("testmimetext"));
DropTarget target;
target.show();
QVERIFY(QTest::qWaitForWindowActive(&target));
Qt::DropActions supportedActions = Qt::DropAction::CopyAction;
QWindow *window = target.windowHandle();
auto posInsideDropTarget = QHighDpi::toNativePixels(QPoint(20, 20), window->screen());
auto posInsideLabel = QHighDpi::toNativePixels(QPoint(60, 60), window->screen());
// Enter DropTarget.
QWindowSystemInterface::handleDrag(window, &mimeData, posInsideDropTarget, supportedActions, 0, 0);
// Enter QLabel. This will propagate because default QLabel does
// not accept the drop event in dragEnterEvent().
QWindowSystemInterface::handleDrag(window, &mimeData, posInsideLabel, supportedActions, 0, 0);
// Drop on QLabel. DropTarget will get dropEvent(), because it accepted the event.
QWindowSystemInterface::handleDrop(window, &mimeData, posInsideLabel, supportedActions, 0, 0);
QGuiApplication::processEvents();
QCOMPARE(target.mDndEvents, "enter leave enter drop ");
}
#endif
void tst_QWidget_window::tst_qtbug35600()