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; return 3;
} }
QFileDevice::Permissions targetPermissions = QFileDevice::ReadOwner | QFileDevice::WriteOwner
| QFileDevice::ReadUser | QFileDevice::WriteUser
| QFileDevice::ReadGroup | QFileDevice::ReadOther;
if (exe) { if (exe) {
targetPermissions |= QFileDevice::ExeOwner | QFileDevice::ExeUser | if (!targetFile.setPermissions(sourceFile.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeUser |
QFileDevice::ExeGroup | QFileDevice::ExeOther; QFileDevice::ExeGroup | QFileDevice::ExeOther)) {
} fprintf(stderr, "Error setting execute permissions on %s: %s\n",
if (!targetFile.setPermissions(targetPermissions)) {
fprintf(stderr, "Error setting permissions on %s: %s\n",
qPrintable(target), qPrintable(targetFile.errorString())); qPrintable(target), qPrintable(targetFile.errorString()));
return 3; return 3;
} }
}
// Copy file times // Copy file times
QString error; 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)) { if (!IoUtils::touchFile(target, sourceFile.fileName(), &error)) {
fprintf(stderr, "%s", qPrintable(error)); fprintf(stderr, "%s", qPrintable(error));
return 3; return 3;
} }
#ifdef Q_OS_WIN
if (readOnly)
targetFile.setPermissions(permissions);
#endif
return 0; 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.", "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.", "Description": "Wintab is a de facto API for pointing devices on Windows.",
"Version": "Upstream no longer offers updates; treat as final", "PackageComment": "Upstream http://www.pointing.com/Wintab.html no longer offers updates; treat as final",
"Homepage": "http://www.pointing.com/Wintab.html", "License": "Custom License",
"License": "Public Domain", "LicenseFile": "LICENSE.txt",
"LicenseId": "NONE", "LicenseId": "NONE",
"Copyright": "Copyright 1991-1998 by LCS/Telegraphics." "Copyright": "Copyright 1991-1998 by LCS/Telegraphics."
} }

View File

@ -140,6 +140,10 @@ public:
// Inlined for its one caller in qdatetime.cpp // Inlined for its one caller in qdatetime.cpp
inline void setUtcOffsetByTZ(qint64 atMSecsSinceEpoch); inline void setUtcOffsetByTZ(qint64 atMSecsSinceEpoch);
#endif // timezone #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 QT_END_NAMESPACE

View File

@ -39,6 +39,7 @@
#include "qtimezone.h" #include "qtimezone.h"
#include "qtimezoneprivate_p.h" #include "qtimezoneprivate_p.h"
#include "qdatetime_p.h" // ### Qt 5.14: remove once YearRange is on QDateTime
#include <QtCore/QFile> #include <QtCore/QFile>
#include <QtCore/QHash> #include <QtCore/QHash>
@ -520,19 +521,14 @@ PosixZone PosixZone::parse(const char *&pos, const char *end)
static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArray &posixRule, static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArray &posixRule,
int startYear, int endYear, int startYear, int endYear,
int lastTranMSecs) qint64 lastTranMSecs)
{ {
QVector<QTimeZonePrivate::Data> result; 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" // 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]" // 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(','); QList<QByteArray> parts = posixRule.split(',');
PosixZone stdZone, dstZone = PosixZone::invalid(); PosixZone stdZone, dstZone = PosixZone::invalid();
@ -583,6 +579,13 @@ static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArra
else else
stdTime = QTime(2, 0, 0); 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) { for (int year = startYear; year <= endYear; ++year) {
QTimeZonePrivate::Data dstData; QTimeZonePrivate::Data dstData;
QDateTime dst(calculatePosixDate(dstDateRule, year), dstTime, Qt::UTC); QDateTime dst(calculatePosixDate(dstDateRule, year), dstTime, Qt::UTC);
@ -598,13 +601,16 @@ static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArra
stdData.standardTimeOffset = stdZone.offset; stdData.standardTimeOffset = stdZone.offset;
stdData.daylightTimeOffset = 0; stdData.daylightTimeOffset = 0;
stdData.abbreviation = stdZone.name; stdData.abbreviation = stdZone.name;
// Part of the high year will overflow // Part of maxYear will overflow (likewise for minYear, below):
if (year == 292278994 && (dstData.atMSecsSinceEpoch < 0 || stdData.atMSecsSinceEpoch < 0)) { if (year == maxYear && (dstData.atMSecsSinceEpoch < 0 || stdData.atMSecsSinceEpoch < 0)) {
if (dstData.atMSecsSinceEpoch > 0) { if (dstData.atMSecsSinceEpoch > 0) {
result << dstData; result << dstData;
} else if (stdData.atMSecsSinceEpoch > 0) { } else if (stdData.atMSecsSinceEpoch > 0) {
result << stdData; 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) { } else if (dst < std) {
result << dstData << stdData; result << dstData << stdData;
} else { } else {
@ -794,6 +800,8 @@ void QTzTimeZonePrivate::init(const QByteArray &ianaId)
tran.atMSecsSinceEpoch = tz_tran.tz_time * 1000; tran.atMSecsSinceEpoch = tz_tran.tz_time * 1000;
m_tranTimes.append(tran); m_tranTimes.append(tran);
} }
if (m_tranTimes.isEmpty() && m_posixRule.isEmpty())
return; // Invalid after all !
if (ianaId.isEmpty()) if (ianaId.isEmpty())
m_id = systemTimeZoneId(); m_id = systemTimeZoneId();
@ -954,22 +962,25 @@ QVector<QTimeZonePrivate::Data> QTzTimeZonePrivate::getPosixTransitions(qint64 m
QTimeZonePrivate::Data QTzTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const QTimeZonePrivate::Data QTzTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
{ {
// If the required time is after the last transition (or there were none) // If the required time is after the last transition (or there were none)
// and we have a POSIX rule then use it: // and we have a POSIX rule, then use it:
if ((m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < forMSecsSinceEpoch) if (!m_posixRule.isEmpty()
&& !m_posixRule.isEmpty() && forMSecsSinceEpoch >= 0) { && (m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < forMSecsSinceEpoch)) {
QVector<QTimeZonePrivate::Data> posixTrans = getPosixTransitions(forMSecsSinceEpoch); QVector<QTimeZonePrivate::Data> posixTrans = getPosixTransitions(forMSecsSinceEpoch);
auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(), auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
[forMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) { [forMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {
return at.atMSecsSinceEpoch <= forMSecsSinceEpoch; return at.atMSecsSinceEpoch <= forMSecsSinceEpoch;
}); });
if (it > posixTrans.cbegin()) { // Use most recent, if any in the past; or the first if we have no other rules:
QTimeZonePrivate::Data data = *--it; if (it > posixTrans.cbegin() || (m_tranTimes.isEmpty() && it < posixTrans.cend())) {
QTimeZonePrivate::Data data = *(it > posixTrans.cbegin() ? it - 1 : it);
data.atMSecsSinceEpoch = forMSecsSinceEpoch; data.atMSecsSinceEpoch = forMSecsSinceEpoch;
return data; 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(), auto last = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(),
[forMSecsSinceEpoch] (const QTzTransitionTime &at) { [forMSecsSinceEpoch] (const QTzTransitionTime &at) {
return at.atMSecsSinceEpoch <= forMSecsSinceEpoch; return at.atMSecsSinceEpoch <= forMSecsSinceEpoch;
@ -989,9 +1000,9 @@ bool QTzTimeZonePrivate::hasTransitions() const
QTimeZonePrivate::Data QTzTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch) const QTimeZonePrivate::Data QTzTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch) const
{ {
// If the required time is after the last transition (or there were none) // If the required time is after the last transition (or there were none)
// and we have a POSIX rule then use it: // and we have a POSIX rule, then use it:
if ((m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < afterMSecsSinceEpoch) if (!m_posixRule.isEmpty()
&& !m_posixRule.isEmpty() && afterMSecsSinceEpoch >= 0) { && (m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < afterMSecsSinceEpoch)) {
QVector<QTimeZonePrivate::Data> posixTrans = getPosixTransitions(afterMSecsSinceEpoch); QVector<QTimeZonePrivate::Data> posixTrans = getPosixTransitions(afterMSecsSinceEpoch);
auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(), auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
[afterMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) { [afterMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {
@ -1012,9 +1023,9 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::nextTransition(qint64 afterMSecsSince
QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
{ {
// If the required time is after the last transition (or there were none) // If the required time is after the last transition (or there were none)
// and we have a POSIX rule then use it: // and we have a POSIX rule, then use it:
if ((m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < beforeMSecsSinceEpoch) if (!m_posixRule.isEmpty()
&& !m_posixRule.isEmpty() && beforeMSecsSinceEpoch > 0) { && (m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < beforeMSecsSinceEpoch)) {
QVector<QTimeZonePrivate::Data> posixTrans = getPosixTransitions(beforeMSecsSinceEpoch); QVector<QTimeZonePrivate::Data> posixTrans = getPosixTransitions(beforeMSecsSinceEpoch);
auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(), auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
[beforeMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) { [beforeMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {

View File

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

View File

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

View File

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

View File

@ -59,6 +59,10 @@
# include <gnu/lib-names.h> # include <gnu/lib-names.h>
#endif #endif
#if defined(Q_OS_FREEBSD) || QT_CONFIG(dlopen)
# include <dlfcn.h>
#endif
#include <cstring> #include <cstring>
QT_BEGIN_NAMESPACE 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() static bool resolveLibraryInternal()
{ {
QLibrary lib; QLibrary lib;
@ -96,31 +112,30 @@ static bool resolveLibraryInternal()
#endif #endif
{ {
lib.setFileName(QLatin1String("resolv")); lib.setFileName(QLatin1String("resolv"));
if (!lib.load()) lib.load();
return false;
} }
local_dn_expand = dn_expand_proto(lib.resolve("__dn_expand")); local_dn_expand = dn_expand_proto(resolveSymbol(lib, "__dn_expand"));
if (!local_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) 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) 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) 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) 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) 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) 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; return true;
} }

View File

@ -66,6 +66,10 @@
# include <gnu/lib-names.h> # include <gnu/lib-names.h>
#endif #endif
#if defined(Q_OS_FREEBSD) || QT_CONFIG(dlopen)
# include <dlfcn.h>
#endif
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
// Almost always the same. If not, specify in qplatformdefs.h. // 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() LibResolv::LibResolv()
{ {
QLibrary lib; QLibrary lib;
@ -124,31 +140,30 @@ LibResolv::LibResolv()
#endif #endif
{ {
lib.setFileName(QLatin1String("resolv")); lib.setFileName(QLatin1String("resolv"));
if (!lib.load()) lib.load();
return;
} }
// res_ninit is required for localDomainName() // 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) 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) { if (local_res_ninit) {
// we must now find res_nclose // 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) 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) if (!local_res_nclose)
local_res_ninit = nullptr; local_res_ninit = nullptr;
} }
if (ReinitNecessary || !local_res_ninit) { 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) 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 (local_res_init && !local_res_ninit) {
// if we can't get a thread-safe context, we have to use the global _res state // 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 \overload
Sends the datagram \a datagram to the host address and port numbers 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 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 QNetworkDatagram object, along with the sender's host address and port. If
possible, this function will also try to determine the datagram's 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())); const QPoint mapped = widget->mapFromGlobal(m_widget->mapToGlobal(event->pos()));
QDragEnterEvent translated(mapped, event->possibleActions(), event->mimeData(), QDragEnterEvent translated(mapped, event->possibleActions(), event->mimeData(),
event->mouseButtons(), event->keyboardModifiers()); event->mouseButtons(), event->keyboardModifiers());
translated.setDropAction(event->dropAction());
translated.setAccepted(event->isAccepted());
QGuiApplication::forwardEvent(m_dragTarget, &translated, event); QGuiApplication::forwardEvent(m_dragTarget, &translated, event);
event->setAccepted(translated.isAccepted()); event->setAccepted(translated.isAccepted());
event->setDropAction(translated.dropAction()); event->setDropAction(translated.dropAction());

View File

@ -539,8 +539,13 @@ void tst_QTimeZone::checkOffset_data()
int year, month, day, hour, min, sec; int year, month, day, hour, min, sec;
int std, dst; int std, dst;
} table[] = { } 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", "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): // Kiev: regression test for QTBUG-64122 (on MS):
{ "Europe/Kiev", "summer", 2017, 10, 27, 12, 0, 0, 2 * 3600, 3600 }, { "Europe/Kiev", "summer", 2017, 10, 27, 12, 0, 0, 2 * 3600, 3600 },
{ "Europe/Kiev", "winter", 2017, 10, 29, 12, 0, 0, 2 * 3600, 0 } { "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/qwindow_p.h>
#include <private/qguiapplication_p.h> #include <private/qguiapplication_p.h>
#include <qpa/qplatformintegration.h> #include <qpa/qplatformintegration.h>
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatformdrag.h>
#include <private/qhighdpiscaling_p.h>
#include <QtTest/private/qtesthelpers_p.h> #include <QtTest/private/qtesthelpers_p.h>
@ -87,6 +90,7 @@ private slots:
#if QT_CONFIG(draganddrop) #if QT_CONFIG(draganddrop)
void tst_dnd(); void tst_dnd();
void tst_dnd_events(); void tst_dnd_events();
void tst_dnd_propagation();
#endif #endif
void tst_qtbug35600(); void tst_qtbug35600();
@ -744,6 +748,77 @@ void tst_QWidget_window::tst_dnd_events()
QCOMPARE(dndWidget._dndEvents, expectedDndEvents); 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 #endif
void tst_QWidget_window::tst_qtbug35600() void tst_QWidget_window::tst_qtbug35600()