From 02e448784543df2d81135ac583c39df6237dac69 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 10 Apr 2015 23:18:23 -0700 Subject: Correct calculation of filesystem data on unusual filesystems POSIX.1 says f_blocks, f_bfree, f_bavail are calculated in terms of f_frsize, not of the regular block size f_bsize. On most systems, it's the same, which is why we didn't catch it. I don't have any filesystem to test this on to confirm. Reference: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_statvfs.h.html Task-number: QTBUG-45137 Change-Id: I27eaacb532114dd188c4ffff13d3e13016bed4e6 Reviewed-by: Dmitry Shachnev Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Ivan Komissarov --- src/corelib/io/qstorageinfo_unix.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp index 2a83e87b0c..cd3c60650e 100644 --- a/src/corelib/io/qstorageinfo_unix.cpp +++ b/src/corelib/io/qstorageinfo_unix.cpp @@ -416,9 +416,9 @@ void QStorageInfoPrivate::retreiveVolumeInfo() valid = true; ready = true; - bytesTotal = statfs_buf.f_blocks * statfs_buf.f_bsize; - bytesFree = statfs_buf.f_bfree * statfs_buf.f_bsize; - bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_bsize; + bytesTotal = statfs_buf.f_blocks * statfs_buf.f_frsize; + bytesFree = statfs_buf.f_bfree * statfs_buf.f_frsize; + bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_frsize; #if defined(Q_OS_ANDROID) #if defined(_STATFS_F_FLAGS) readOnly = (statfs_buf.f_flags & ST_RDONLY) != 0; -- cgit v1.2.3 From 18a3b431678e3b456c33a9f7ae21d8653dd2ef85 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Mon, 27 Apr 2015 01:22:36 +0200 Subject: Update QProcess doc to use non-deprecated setProcessEnvironment Currently the documentation still mentions the use of the deprected setEnvironment function. This patch aims to correct that Task-number: QTBUG-45235 Change-Id: Iab35754b39f025c7493a6f061eb72e23bc4cf308 Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qprocess.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index baba9a0f9e..4d2a75c0fa 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -373,8 +373,8 @@ QString QProcessEnvironment::value(const QString &name, const QString &defaultVa Use with the QProcess::setEnvironment function is not recommended due to potential encoding problems under Unix, and worse performance. - \sa systemEnvironment(), QProcess::systemEnvironment(), QProcess::environment(), - QProcess::setEnvironment() + \sa systemEnvironment(), QProcess::systemEnvironment(), + QProcess::setProcessEnvironment() */ QStringList QProcessEnvironment::toStringList() const { @@ -534,7 +534,7 @@ void QProcessPrivate::Channel::clear() Certain processes need special environment settings in order to operate. You can set environment variables for your process by - calling setEnvironment(). To set a working directory, call + calling setProcessEnvironment(). To set a working directory, call setWorkingDirectory(). By default, processes are run in the current working directory of the calling process. @@ -2471,7 +2471,7 @@ QT_END_INCLUDE_NAMESPACE \note For new code, it is recommended to use QProcessEnvironment::systemEnvironment() - \sa QProcessEnvironment::systemEnvironment(), environment(), setEnvironment() + \sa QProcessEnvironment::systemEnvironment(), setProcessEnvironment() */ QStringList QProcess::systemEnvironment() { -- cgit v1.2.3 From 2cb17c1fb903434274e58692c9f0df619affdab0 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 18 May 2015 11:29:31 +0200 Subject: Improve documentation for Qt::ItemNeverHasChildren. Change-Id: Ied817314d6e72f08a81138bd817c8570d586fa30 Reviewed-by: Oswald Buddenhagen Reviewed-by: David Faure Reviewed-by: Martin Smith Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/global/qnamespace.qdoc | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 3f9526c788..87056b79f0 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -2562,6 +2562,7 @@ \value ItemIsEnabled The user can interact with the item. \value ItemIsTristate The item is checkable with three separate states. \value ItemNeverHasChildren The item never has child items. + This is used for optimization purposes only. Note that checkable items need to be given both a suitable set of flags and an initial state, indicating whether the item is checked or not. -- cgit v1.2.3 From d1ce29557cea3a4f23c400a5cb03254f6cf31dc5 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Tue, 24 Feb 2015 12:36:54 +0100 Subject: Make QStyle::itemPixmapRect handle devicePixelRatio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Layout sizes for images should be in the form QSize layoutSize = image.size() / image.devicePixelRatio() to be in device independent pixels Change-Id: Ic149144c45c8fa5c45ac5cbe2c82c35d721549cd Reviewed-by: Morten Johan Sørvig --- src/widgets/styles/qstyle.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp index 6072842fc9..5c0064c7a4 100644 --- a/src/widgets/styles/qstyle.cpp +++ b/src/widgets/styles/qstyle.cpp @@ -541,17 +541,21 @@ QRect QStyle::itemPixmapRect(const QRect &rect, int alignment, const QPixmap &pi QRect result; int x, y, w, h; rect.getRect(&x, &y, &w, &h); + + const int pixmapWidth = pixmap.width()/pixmap.devicePixelRatio(); + const int pixmapHeight = pixmap.height()/pixmap.devicePixelRatio(); + if ((alignment & Qt::AlignVCenter) == Qt::AlignVCenter) - y += h/2 - pixmap.height()/2; + y += h/2 - pixmapHeight/2; else if ((alignment & Qt::AlignBottom) == Qt::AlignBottom) - y += h - pixmap.height(); + y += h - pixmapHeight; if ((alignment & Qt::AlignRight) == Qt::AlignRight) - x += w - pixmap.width(); + x += w - pixmapWidth; else if ((alignment & Qt::AlignHCenter) == Qt::AlignHCenter) - x += w/2 - pixmap.width()/2; + x += w/2 - pixmapWidth/2; else if ((alignment & Qt::AlignLeft) != Qt::AlignLeft && QApplication::isRightToLeft()) - x += w - pixmap.width(); - result = QRect(x, y, pixmap.width(), pixmap.height()); + x += w - pixmapWidth; + result = QRect(x, y, pixmapWidth, pixmapHeight); return result; } -- cgit v1.2.3 From 34014406baaeac3e9d49d5654ef57ac6540a17a8 Mon Sep 17 00:00:00 2001 From: Evgeniy Fominov Date: Mon, 16 Feb 2015 14:36:54 +0100 Subject: quote QUuid values Task-number: QTBUG-44480 Change-Id: I125ab913c867758d958a2774ad125533d6a07a83 Reviewed-by: Evgeniy Fominov Reviewed-by: Mark Brand --- src/sql/drivers/psql/qsql_psql.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/sql/drivers/psql/qsql_psql.cpp b/src/sql/drivers/psql/qsql_psql.cpp index 4268ea06f6..32f6e317d8 100644 --- a/src/sql/drivers/psql/qsql_psql.cpp +++ b/src/sql/drivers/psql/qsql_psql.cpp @@ -1320,6 +1320,9 @@ QString QPSQLDriver::formatValue(const QSqlField &field, bool trimStrings) const } break; } + case QVariant::Uuid: + r = QLatin1Char('\'') + field.value().toString() + QLatin1Char('\''); + break; default: r = QSqlDriver::formatValue(field, trimStrings); break; -- cgit v1.2.3 From d82d5b1c43b270ef6f4f0d90ce5d7d96ea0b7a97 Mon Sep 17 00:00:00 2001 From: Mikhail Lappo Date: Wed, 3 Jun 2015 10:09:42 +0300 Subject: Check for integer overflows in places where qAllocMore is used Task-number: QTBUG-41230 Change-Id: Ic2167364e326092482657f2d2b4ab6ad3e5af631 (partially cherry-picked from 880986be2357a1f80827d038d770dc2f80300201) Reviewed-by: Thiago Macieira --- src/corelib/tools/qarraydata.cpp | 16 ++++++++++++++-- src/corelib/tools/qbytearray.cpp | 7 +++++-- src/corelib/tools/qlist.cpp | 2 ++ src/corelib/tools/qstring.cpp | 5 ++++- src/corelib/tools/qtools_p.h | 6 ++++++ src/gui/text/qfragmentmap_p.h | 2 ++ 6 files changed, 33 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp index 98c484c1dd..d060ff84f2 100644 --- a/src/corelib/tools/qarraydata.cpp +++ b/src/corelib/tools/qarraydata.cpp @@ -85,8 +85,20 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment, headerSize += (alignment - Q_ALIGNOF(QArrayData)); // Allocate additional space if array is growing - if (options & Grow) - capacity = qAllocMore(int(objectSize * capacity), int(headerSize)) / int(objectSize); + if (options & Grow) { + + // Guard against integer overflow when multiplying. + if (capacity > std::numeric_limits::max() / objectSize) + return 0; + + size_t alloc = objectSize * capacity; + + // Make sure qAllocMore won't overflow. + if (headerSize > size_t(MaxAllocSize) || alloc > size_t(MaxAllocSize) - headerSize) + return 0; + + capacity = qAllocMore(int(alloc), int(headerSize)) / int(objectSize); + } size_t allocSize = headerSize + objectSize * capacity; diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 5ec8c317e8..1e87f7b023 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -64,7 +64,7 @@ int qFindByteArray( int qAllocMore(int alloc, int extra) Q_DECL_NOTHROW { Q_ASSERT(alloc >= 0 && extra >= 0); - Q_ASSERT_X(uint(alloc) < QByteArray::MaxSize, "qAllocMore", "Requested size is too large!"); + Q_ASSERT_X(alloc <= MaxAllocSize - extra, "qAllocMore", "Requested size is too large!"); unsigned nalloc = qNextPowerOfTwo(alloc + extra); @@ -1495,8 +1495,11 @@ void QByteArray::reallocData(uint alloc, Data::AllocationOptions options) Data::deallocate(d); d = x; } else { - if (options & Data::Grow) + if (options & Data::Grow) { + if (alloc > uint(MaxAllocSize) - uint(sizeof(Data))) + qBadAlloc(); alloc = qAllocMore(alloc, sizeof(Data)); + } Data *x = static_cast(::realloc(d, sizeof(Data) + alloc)); Q_CHECK_PTR(x); x->alloc = alloc; diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index fe5e0f33b4..b91fd38a5f 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -55,6 +55,8 @@ const QListData::Data QListData::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0 static int grow(int size) { + if (size_t(size) > (MaxAllocSize - QListData::DataHeaderSize) / sizeof(void *)) + qBadAlloc(); // dear compiler: don't optimize me out. volatile int x = qAllocMore(size * sizeof(void *), QListData::DataHeaderSize) / sizeof(void *); return x; diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 189caf8bd7..96f3c4147c 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -1656,8 +1656,11 @@ void QString::resize(int size) void QString::reallocData(uint alloc, bool grow) { - if (grow) + if (grow) { + if (alloc > (uint(MaxAllocSize) - sizeof(Data)) / sizeof(QChar)) + qBadAlloc(); alloc = qAllocMore(alloc * sizeof(QChar), sizeof(Data)) / sizeof(QChar); + } if (d->ref.isShared() || IS_RAW_DATA(d)) { Data::AllocationOptions allocOptions(d->capacityReserved ? Data::CapacityReserved : 0); diff --git a/src/corelib/tools/qtools_p.h b/src/corelib/tools/qtools_p.h index 3876d3822c..1e72db1d87 100644 --- a/src/corelib/tools/qtools_p.h +++ b/src/corelib/tools/qtools_p.h @@ -46,9 +46,15 @@ // #include "QtCore/qglobal.h" +#include QT_BEGIN_NAMESPACE +// We typically need an extra bit for qNextPowerOfTwo when determining the next allocation size. +enum { + MaxAllocSize = (1 << (std::numeric_limits::digits - 1)) - 1 +}; + // implemented in qbytearray.cpp int Q_CORE_EXPORT qAllocMore(int alloc, int extra) Q_DECL_NOTHROW; diff --git a/src/gui/text/qfragmentmap_p.h b/src/gui/text/qfragmentmap_p.h index 012d3c25ce..a19e3d9ea3 100644 --- a/src/gui/text/qfragmentmap_p.h +++ b/src/gui/text/qfragmentmap_p.h @@ -249,6 +249,8 @@ uint QFragmentMapData::createFragment() uint freePos = head->freelist; if (freePos == head->allocated) { // need to create some free space + if (freePos >= uint(MaxAllocSize) / fragmentSize) + qBadAlloc(); uint needed = qAllocMore((freePos+1)*fragmentSize, 0); Q_ASSERT(needed/fragmentSize > head->allocated); Fragment *newFragments = (Fragment *)realloc(fragments, needed); -- cgit v1.2.3 From eae0cb09f1310e755c2aff7c1112f7a6c09d7a53 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Fri, 19 Jun 2015 15:35:34 +0200 Subject: Network: Fix up previous corruption patch This is a fix-up for cff39fba10ffc10ee4dcfdc66ff6528eb26462d3. That patch lead to some internal state issues that lead to the QTBUG-47048 or to QNetworkReply objects erroring with "Connection Closed" when the server closed the Keep-Alive connection. This patch changes the QNAM socket slot connections to be DirectConnection. We don't close the socket anymore in slots where it is anyway in a closed state afterwards. This prevents event/stack recursions. We also flush QSslSocket/QTcpSocket receive buffers when receiving a disconnect so that the developer always gets the full decrypted data from the buffers. [ChangeLog][QtNetwork] Fix HTTP issues with "Unknown Error" and "Connection Closed" [ChangeLog][QtNetwork][Sockets] Read OS/encrypted read buffers when connection closed by server. Change-Id: Ib4d6a2d0d988317e3a5356f36e8dbcee4590beed Task-number: QTBUG-47048 Reviewed-by: Kai Koehne Reviewed-by: Richard J. Moore --- src/network/access/qhttpnetworkconnection.cpp | 1 - .../access/qhttpnetworkconnectionchannel.cpp | 108 +++++++++++++-------- .../access/qhttpnetworkconnectionchannel_p.h | 1 + src/network/access/qhttpnetworkreply.cpp | 2 +- src/network/access/qhttpprotocolhandler.cpp | 1 - src/network/socket/qabstractsocket.cpp | 7 +- src/network/ssl/qsslsocket.cpp | 8 ++ src/network/ssl/qsslsocket_openssl.cpp | 7 ++ 8 files changed, 89 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 365ce55f2b..543c70e8b7 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -917,7 +917,6 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest() for (int i = 0; i < channelCount; ++i) { if (channels[i].resendCurrent && (channels[i].state != QHttpNetworkConnectionChannel::ClosingState)) { channels[i].resendCurrent = false; - channels[i].state = QHttpNetworkConnectionChannel::IdleState; // if this is not possible, error will be emitted and connection terminated if (!channels[i].resetUploadData()) diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 49c6793b1f..e2f63071e1 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -58,6 +58,11 @@ QT_BEGIN_NAMESPACE // TODO: Put channel specific stuff here so it does not polute qhttpnetworkconnection.cpp +// Because in-flight when sending a request, the server might close our connection (because the persistent HTTP +// connection times out) +// We use 3 because we can get a _q_error 3 times depending on the timing: +static const int reconnectAttemptsDefault = 3; + QHttpNetworkConnectionChannel::QHttpNetworkConnectionChannel() : socket(0) , ssl(false) @@ -69,7 +74,7 @@ QHttpNetworkConnectionChannel::QHttpNetworkConnectionChannel() , resendCurrent(false) , lastStatus(0) , pendingEncrypt(false) - , reconnectAttempts(2) + , reconnectAttempts(reconnectAttemptsDefault) , authMethod(QAuthenticatorPrivate::None) , proxyAuthMethod(QAuthenticatorPrivate::None) , authenticationCredentialsSent(false) @@ -106,19 +111,18 @@ void QHttpNetworkConnectionChannel::init() socket->setProxy(QNetworkProxy::NoProxy); #endif - // We want all signals (except the interactive ones) be connected as QueuedConnection - // because else we're falling into cases where we recurse back into the socket code - // and mess up the state. Always going to the event loop (and expecting that when reading/writing) - // is safer. + // After some back and forth in all the last years, this is now a DirectConnection because otherwise + // the state inside the *Socket classes gets messed up, also in conjunction with the socket notifiers + // which behave slightly differently on Windows vs Linux QObject::connect(socket, SIGNAL(bytesWritten(qint64)), this, SLOT(_q_bytesWritten(qint64)), - Qt::QueuedConnection); + Qt::DirectConnection); QObject::connect(socket, SIGNAL(connected()), this, SLOT(_q_connected()), - Qt::QueuedConnection); + Qt::DirectConnection); QObject::connect(socket, SIGNAL(readyRead()), this, SLOT(_q_readyRead()), - Qt::QueuedConnection); + Qt::DirectConnection); // The disconnected() and error() signals may already come // while calling connectToHost(). @@ -129,10 +133,10 @@ void QHttpNetworkConnectionChannel::init() qRegisterMetaType(); QObject::connect(socket, SIGNAL(disconnected()), this, SLOT(_q_disconnected()), - Qt::QueuedConnection); + Qt::DirectConnection); QObject::connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(_q_error(QAbstractSocket::SocketError)), - Qt::QueuedConnection); + Qt::DirectConnection); #ifndef QT_NO_NETWORKPROXY @@ -147,13 +151,13 @@ void QHttpNetworkConnectionChannel::init() // won't be a sslSocket if encrypt is false QObject::connect(sslSocket, SIGNAL(encrypted()), this, SLOT(_q_encrypted()), - Qt::QueuedConnection); + Qt::DirectConnection); QObject::connect(sslSocket, SIGNAL(sslErrors(QList)), this, SLOT(_q_sslErrors(QList)), Qt::DirectConnection); QObject::connect(sslSocket, SIGNAL(encryptedBytesWritten(qint64)), this, SLOT(_q_encryptedBytesWritten(qint64)), - Qt::QueuedConnection); + Qt::DirectConnection); if (ignoreAllSslErrors) sslSocket->ignoreSslErrors(); @@ -397,7 +401,7 @@ void QHttpNetworkConnectionChannel::allDone() // reset the reconnection attempts after we receive a complete reply. // in case of failures, each channel will attempt two reconnects before emitting error. - reconnectAttempts = 2; + reconnectAttempts = reconnectAttemptsDefault; // now the channel can be seen as free/idle again, all signal emissions for the reply have been done if (state != QHttpNetworkConnectionChannel::ClosingState) @@ -651,6 +655,15 @@ void QHttpNetworkConnectionChannel::closeAndResendCurrentRequest() QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); } +void QHttpNetworkConnectionChannel::resendCurrentRequest() +{ + requeueCurrentlyPipelinedRequests(); + if (reply) + resendCurrent = true; + if (qobject_cast(connection)) + QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); +} + bool QHttpNetworkConnectionChannel::isSocketBusy() const { return (state & QHttpNetworkConnectionChannel::BusyState); @@ -694,8 +707,8 @@ void QHttpNetworkConnectionChannel::_q_disconnected() return; } - // read the available data before closing - if (isSocketWaiting() || isSocketReading()) { + // read the available data before closing (also done in _q_error for other codepaths) + if ((isSocketWaiting() || isSocketReading()) && socket->bytesAvailable()) { if (reply) { state = QHttpNetworkConnectionChannel::ReadingState; _q_receiveReply(); @@ -707,7 +720,8 @@ void QHttpNetworkConnectionChannel::_q_disconnected() state = QHttpNetworkConnectionChannel::IdleState; requeueCurrentlyPipelinedRequests(); - close(); + + pendingEncrypt = false; } @@ -789,11 +803,19 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket errorCode = QNetworkReply::ConnectionRefusedError; break; case QAbstractSocket::RemoteHostClosedError: - // try to reconnect/resend before sending an error. - // while "Reading" the _q_disconnected() will handle this. - if (state != QHttpNetworkConnectionChannel::IdleState && state != QHttpNetworkConnectionChannel::ReadingState) { + // This error for SSL comes twice in a row, first from SSL layer ("The TLS/SSL connection has been closed") then from TCP layer. + // Depending on timing it can also come three times in a row (first time when we try to write into a closing QSslSocket). + // The reconnectAttempts handling catches the cases where we can re-send the request. + 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 + return; + } else if (state != QHttpNetworkConnectionChannel::IdleState && state != QHttpNetworkConnectionChannel::ReadingState) { + // Try to reconnect/resend before sending an error. + // While "Reading" the _q_disconnected() will handle this. if (reconnectAttempts-- > 0) { - closeAndResendCurrentRequest(); + resendCurrentRequest(); return; } else { errorCode = QNetworkReply::RemoteHostClosedError; @@ -818,24 +840,15 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket // we can ignore the readbuffersize as the data is already // in memory and we will not receive more data on the socket. reply->setReadBufferSize(0); + reply->setDownstreamLimited(false); _q_receiveReply(); -#ifndef QT_NO_SSL - if (ssl) { - // QT_NO_OPENSSL. The QSslSocket can still have encrypted bytes in the plainsocket. - // So we need to check this if the socket is a QSslSocket. When the socket is flushed - // it will force a decrypt of the encrypted data in the plainsocket. - QSslSocket *sslSocket = static_cast(socket); - qint64 beforeFlush = sslSocket->encryptedBytesAvailable(); - while (sslSocket->encryptedBytesAvailable()) { - sslSocket->flush(); - _q_receiveReply(); - qint64 afterFlush = sslSocket->encryptedBytesAvailable(); - if (afterFlush == beforeFlush) - break; - beforeFlush = afterFlush; - } + if (!reply) { + // No more reply assigned after the previous call? Then it had been finished successfully. + requeueCurrentlyPipelinedRequests(); + state = QHttpNetworkConnectionChannel::IdleState; + QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); + return; } -#endif } errorCode = QNetworkReply::RemoteHostClosedError; @@ -846,7 +859,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket case QAbstractSocket::SocketTimeoutError: // try to reconnect/resend before sending an error. if (state == QHttpNetworkConnectionChannel::WritingState && (reconnectAttempts-- > 0)) { - closeAndResendCurrentRequest(); + resendCurrentRequest(); return; } errorCode = QNetworkReply::TimeoutError; @@ -860,7 +873,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket case QAbstractSocket::ProxyConnectionClosedError: // try to reconnect/resend before sending an error. if (reconnectAttempts-- > 0) { - closeAndResendCurrentRequest(); + resendCurrentRequest(); return; } errorCode = QNetworkReply::ProxyConnectionClosedError; @@ -868,7 +881,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket case QAbstractSocket::ProxyConnectionTimeoutError: // try to reconnect/resend before sending an error. if (reconnectAttempts-- > 0) { - closeAndResendCurrentRequest(); + resendCurrentRequest(); return; } errorCode = QNetworkReply::ProxyTimeoutError; @@ -916,8 +929,18 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket // send the next request QMetaObject::invokeMethod(that, "_q_startNextRequest", Qt::QueuedConnection); - if (that) //signal emission triggered event loop - close(); + if (that) { + //signal emission triggered event loop + if (!socket) + state = QHttpNetworkConnectionChannel::IdleState; + else if (socket->state() == QAbstractSocket::UnconnectedState) + state = QHttpNetworkConnectionChannel::IdleState; + else + state = QHttpNetworkConnectionChannel::ClosingState; + + // pendingEncrypt must only be true in between connected and encrypted states + pendingEncrypt = false; + } } #ifndef QT_NO_NETWORKPROXY @@ -941,7 +964,8 @@ void QHttpNetworkConnectionChannel::_q_proxyAuthenticationRequired(const QNetwor void QHttpNetworkConnectionChannel::_q_uploadDataReadyRead() { - sendRequest(); + if (reply) + sendRequest(); } #ifndef QT_NO_SSL diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h index 231fe11135..a834b7d645 100644 --- a/src/network/access/qhttpnetworkconnectionchannel_p.h +++ b/src/network/access/qhttpnetworkconnectionchannel_p.h @@ -169,6 +169,7 @@ public: void handleUnexpectedEOF(); void closeAndResendCurrentRequest(); + void resendCurrentRequest(); bool isSocketBusy() const; bool isSocketWriting() const; diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp index 55863a3c88..8b71bd8e70 100644 --- a/src/network/access/qhttpnetworkreply.cpp +++ b/src/network/access/qhttpnetworkreply.cpp @@ -191,7 +191,7 @@ QByteArray QHttpNetworkReply::readAny() return QByteArray(); // we'll take the last buffer, so schedule another read from http - if (d->downstreamLimited && d->responseData.bufferCount() == 1) + if (d->downstreamLimited && d->responseData.bufferCount() == 1 && !isFinished()) d->connection->d_func()->readMoreLater(this); return d->responseData.read(); } diff --git a/src/network/access/qhttpprotocolhandler.cpp b/src/network/access/qhttpprotocolhandler.cpp index 3357948519..380aaacf0c 100644 --- a/src/network/access/qhttpprotocolhandler.cpp +++ b/src/network/access/qhttpprotocolhandler.cpp @@ -250,7 +250,6 @@ bool QHttpProtocolHandler::sendRequest() if (!m_reply) { // heh, how should that happen! qWarning() << "QAbstractProtocolHandler::sendRequest() called without QHttpNetworkReply"; - m_channel->state = QHttpNetworkConnectionChannel::IdleState; return false; } diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 26667715be..0e82d4ab66 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -768,6 +768,7 @@ bool QAbstractSocketPrivate::canReadNotification() void QAbstractSocketPrivate::canCloseNotification() { Q_Q(QAbstractSocket); + // Note that this method is only called on Windows. Other platforms close in the canReadNotification() #if defined (QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::canCloseNotification()"); @@ -777,7 +778,11 @@ void QAbstractSocketPrivate::canCloseNotification() if (isBuffered) { // Try to read to the buffer, if the read fail we can close the socket. newBytes = buffer.size(); - if (!readFromSocket()) { + qint64 oldReadBufferMaxSize = readBufferMaxSize; + readBufferMaxSize = 0; // temporarily disable max read buffer, we want to empty the OS buffer + bool hadReadFromSocket = readFromSocket(); + readBufferMaxSize = oldReadBufferMaxSize; + if (!hadReadFromSocket) { q->disconnectFromHost(); return; } diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index c1fab94fce..2b9e9230e0 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -2294,6 +2294,14 @@ void QSslSocketPrivate::_q_errorSlot(QAbstractSocket::SocketError error) qCDebug(lcSsl) << "\tstate =" << q->state(); qCDebug(lcSsl) << "\terrorString =" << q->errorString(); #endif + // this moves encrypted bytes from plain socket into our buffer + if (plainSocket->bytesAvailable()) { + qint64 tmpReadBufferMaxSize = readBufferMaxSize; + readBufferMaxSize = 0; // reset temporarily so the plain sockets completely drained drained + transmit(); + readBufferMaxSize = tmpReadBufferMaxSize; + } + q->setSocketError(plainSocket->error()); q->setErrorString(plainSocket->errorString()); emit q->error(error); diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index ac4336afcc..94655feb9b 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -1419,6 +1419,13 @@ void QSslSocketBackendPrivate::disconnected() { if (plainSocket->bytesAvailable() <= 0) destroySslContext(); + else { + // Move all bytes into the plain buffer + qint64 tmpReadBufferMaxSize = readBufferMaxSize; + readBufferMaxSize = 0; // reset temporarily so the plain socket buffer is completely drained + transmit(); + readBufferMaxSize = tmpReadBufferMaxSize; + } //if there is still buffered data in the plain socket, don't destroy the ssl context yet. //it will be destroyed when the socket is deleted. } -- cgit v1.2.3 From 4a1e5dbade4bab55f39bd368480dcca9a11e4b38 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 9 Jul 2015 09:30:42 +0200 Subject: Better handling of invalid font tables Specifically when reading files with broken cmap tables, we could get some undeterministic results. We handle this more gracefully by verifying that the offsets are sane and bailing out early if not. This replaces the current pattern throughout the font engine for consistency. Change-Id: I507bba49c0be634afca77d1eb3d199a427451bee Reviewed-by: Simon Hausmann Reviewed-by: Thiago Macieira --- src/gui/text/qfontengine.cpp | 212 ++++++++++++++++----- src/gui/text/qfontengine_p.h | 2 +- src/gui/text/qfontengine_qpf2.cpp | 10 +- .../platforms/windows/qwindowsfontengine.cpp | 16 +- src/plugins/platforms/windows/qwindowsfontengine.h | 1 + 5 files changed, 176 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index b360ed5c85..f973abc8e4 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -74,6 +74,16 @@ static inline bool qtransform_equals_no_translate(const QTransform &a, const QTr } } +template +static inline bool qSafeFromBigEndian(const uchar *source, const uchar *end, T *output) +{ + if (source + sizeof(T) > end) + return false; + + *output = qFromBigEndian(source); + return true; +} + // Harfbuzz helper functions #ifdef QT_ENABLE_HARFBUZZ_NG @@ -1044,26 +1054,38 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor) return; const uchar *table = reinterpret_cast(tab.constData()); + const uchar *end = table + tab.size(); + + quint16 version; + if (!qSafeFromBigEndian(table, end, &version)) + return; - unsigned short version = qFromBigEndian(table); if (version != 0) { // qDebug("wrong version"); return; } - unsigned short numTables = qFromBigEndian(table + 2); + quint16 numTables; + if (!qSafeFromBigEndian(table + 2, end, &numTables)) + return; + { int offset = 4; for(int i = 0; i < numTables; ++i) { - if (offset + 6 > tab.size()) { -// qDebug("offset out of bounds"); - goto end; - } const uchar *header = table + offset; - ushort version = qFromBigEndian(header); - ushort length = qFromBigEndian(header+2); - ushort coverage = qFromBigEndian(header+4); + quint16 version; + if (!qSafeFromBigEndian(header, end, &version)) + goto end; + + quint16 length; + if (!qSafeFromBigEndian(header + 2, end, &length)) + goto end; + + quint16 coverage; + if (!qSafeFromBigEndian(header + 4, end, &coverage)) + goto end; + // qDebug("subtable: version=%d, coverage=%x",version, coverage); if(version == 0 && coverage == 0x0001) { if (offset + length > tab.size()) { @@ -1072,7 +1094,10 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor) } const uchar *data = table + offset + 6; - ushort nPairs = qFromBigEndian(data); + quint16 nPairs; + if (!qSafeFromBigEndian(data, end, &nPairs)) + goto end; + if(nPairs * 6 + 8 > length - 6) { // qDebug("corrupt table!"); // corrupt table @@ -1082,8 +1107,21 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor) int off = 8; for(int i = 0; i < nPairs; ++i) { QFontEngine::KernPair p; - p.left_right = (((uint)qFromBigEndian(data+off)) << 16) + qFromBigEndian(data+off+2); - p.adjust = QFixed(((int)(short)qFromBigEndian(data+off+4))) / scalingFactor; + + quint16 tmp; + if (!qSafeFromBigEndian(data + off, end, &tmp)) + goto end; + + p.left_right = uint(tmp) << 16; + if (!qSafeFromBigEndian(data + off + 2, end, &tmp)) + goto end; + + p.left_right |= tmp; + + if (!qSafeFromBigEndian(data + off + 4, end, &tmp)) + goto end; + + p.adjust = QFixed(int(short(tmp))) / scalingFactor; kerning_pairs.append(p); off += 6; } @@ -1103,26 +1141,31 @@ int QFontEngine::glyphCount() const QByteArray maxpTable = getSfntTable(MAKE_TAG('m', 'a', 'x', 'p')); if (maxpTable.size() < 6) return 0; - return qFromBigEndian(reinterpret_cast(maxpTable.constData() + 4)); + + const uchar *source = reinterpret_cast(maxpTable.constData() + 4); + const uchar *end = source + maxpTable.size(); + + quint16 count = 0; + qSafeFromBigEndian(source, end, &count); + return count; } const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize) { const uchar *header = table; - if (tableSize < 4) - return 0; - const uchar *endPtr = table + tableSize; // version check - if (qFromBigEndian(header) != 0) + quint16 version; + if (!qSafeFromBigEndian(header, endPtr, &version) || version != 0) return 0; - unsigned short numTables = qFromBigEndian(header + 2); - const uchar *maps = table + 4; - if (maps + 8 * numTables > endPtr) + quint16 numTables; + if (!qSafeFromBigEndian(header + 2, endPtr, &numTables)) return 0; + const uchar *maps = table + 4; + enum { Invalid, AppleRoman, @@ -1137,8 +1180,14 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy int tableToUse = -1; int score = Invalid; for (int n = 0; n < numTables; ++n) { - const quint16 platformId = qFromBigEndian(maps + 8 * n); - const quint16 platformSpecificId = qFromBigEndian(maps + 8 * n + 2); + quint16 platformId; + if (!qSafeFromBigEndian(maps + 8 * n, endPtr, &platformId)) + return 0; + + quint16 platformSpecificId; + if (!qSafeFromBigEndian(maps + 8 * n + 2, endPtr, &platformSpecificId)) + return 0; + switch (platformId) { case 0: // Unicode if (score < Unicode && @@ -1192,20 +1241,30 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy resolveTable: *isSymbolFont = (symbolTable > -1); - unsigned int unicode_table = qFromBigEndian(maps + 8*tableToUse + 4); + quint32 unicode_table; + if (!qSafeFromBigEndian(maps + 8 * tableToUse + 4, endPtr, &unicode_table)) + return 0; - if (!unicode_table || unicode_table + 8 > tableSize) + if (!unicode_table) return 0; // get the header of the unicode table header = table + unicode_table; - unsigned short format = qFromBigEndian(header); - unsigned int length; - if(format < 8) - length = qFromBigEndian(header + 2); - else - length = qFromBigEndian(header + 4); + quint16 format; + if (!qSafeFromBigEndian(header, endPtr, &format)) + return 0; + + quint32 length; + if (format < 8) { + quint16 tmp; + if (!qSafeFromBigEndian(header + 2, endPtr, &tmp)) + return 0; + length = tmp; + } else { + if (!qSafeFromBigEndian(header + 4, endPtr, &length)) + return 0; + } if (table + unicode_table + length > endPtr) return 0; @@ -1220,7 +1279,7 @@ resolveTable: // Check that none of the latin1 range are in the unicode table bool unicodeTableHasLatin1 = false; for (int uc=0x00; uc<0x100; ++uc) { - if (getTrueTypeGlyphIndex(selectedTable, uc) != 0) { + if (getTrueTypeGlyphIndex(selectedTable, length, uc) != 0) { unicodeTableHasLatin1 = true; break; } @@ -1230,7 +1289,7 @@ resolveTable: bool unicodeTableHasSymbols = false; if (!unicodeTableHasLatin1) { for (int uc=0xf000; uc<0xf100; ++uc) { - if (getTrueTypeGlyphIndex(selectedTable, uc) != 0) { + if (getTrueTypeGlyphIndex(selectedTable, length, uc) != 0) { unicodeTableHasSymbols = true; break; } @@ -1248,12 +1307,17 @@ resolveTable: return table + unicode_table; } -quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode) +quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint unicode) { - unsigned short format = qFromBigEndian(cmap); + const uchar *end = cmap + cmapSize; + quint16 format; + if (!qSafeFromBigEndian(cmap, end, &format)) + return 0; + if (format == 0) { - if (unicode < 256) - return (int) *(cmap+6+unicode); + const uchar *ptr = cmap + 6 + unicode; + if (unicode < 256 && ptr < end) + return quint32(*ptr); } else if (format == 4) { /* some fonts come with invalid cmap tables, where the last segment specified end = start = rangeoffset = 0xffff, delta = 0x0001 @@ -1262,25 +1326,49 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode) */ if(unicode >= 0xffff) return 0; - quint16 segCountX2 = qFromBigEndian(cmap + 6); + + quint16 segCountX2; + if (!qSafeFromBigEndian(cmap + 6, end, &segCountX2)) + return 0; + const unsigned char *ends = cmap + 14; + int i = 0; - for (; i < segCountX2/2 && qFromBigEndian(ends + 2*i) < unicode; i++) {} + for (; i < segCountX2/2; ++i) { + quint16 codePoint; + if (!qSafeFromBigEndian(ends + 2 * i, end, &codePoint)) + return 0; + if (codePoint >= unicode) + break; + } const unsigned char *idx = ends + segCountX2 + 2 + 2*i; - quint16 startIndex = qFromBigEndian(idx); + quint16 startIndex; + if (!qSafeFromBigEndian(idx, end, &startIndex)) + return 0; if (startIndex > unicode) return 0; idx += segCountX2; - qint16 idDelta = (qint16)qFromBigEndian(idx); + + quint16 tmp; + if (!qSafeFromBigEndian(idx, end, &tmp)) + return 0; + qint16 idDelta = qint16(tmp); + idx += segCountX2; - quint16 idRangeoffset_t = (quint16)qFromBigEndian(idx); + + quint16 idRangeoffset_t; + if (!qSafeFromBigEndian(idx, end, &idRangeoffset_t)) + return 0; quint16 glyphIndex; if (idRangeoffset_t) { - quint16 id = qFromBigEndian(idRangeoffset_t + 2*(unicode - startIndex) + idx); + quint16 id; + if (!qSafeFromBigEndian(idRangeoffset_t + 2 * (unicode - startIndex) + idx, end, &id)) + return 0; + if (id) glyphIndex = (idDelta + id) % 0x10000; else @@ -1290,13 +1378,19 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode) } return glyphIndex; } else if (format == 6) { - quint16 tableSize = qFromBigEndian(cmap + 2); + quint16 tableSize; + if (!qSafeFromBigEndian(cmap + 2, end, &tableSize)) + return 0; - quint16 firstCode6 = qFromBigEndian(cmap + 6); + quint16 firstCode6; + if (!qSafeFromBigEndian(cmap + 6, end, &firstCode6)) + return 0; if (unicode < firstCode6) return 0; - quint16 entryCount6 = qFromBigEndian(cmap + 8); + quint16 entryCount6; + if (!qSafeFromBigEndian(cmap + 8, end, &entryCount6)) + return 0; if (entryCount6 * 2 + 10 > tableSize) return 0; @@ -1305,9 +1399,14 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode) return 0; quint16 entryIndex6 = unicode - firstCode6; - return qFromBigEndian(cmap + 10 + (entryIndex6 * 2)); + + quint16 index = 0; + qSafeFromBigEndian(cmap + 10 + (entryIndex6 * 2), end, &index); + return index; } else if (format == 12) { - quint32 nGroups = qFromBigEndian(cmap + 12); + quint32 nGroups; + if (!qSafeFromBigEndian(cmap + 12, end, &nGroups)) + return 0; cmap += 16; // move to start of groups @@ -1315,13 +1414,24 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode) while (left <= right) { int middle = left + ( ( right - left ) >> 1 ); - quint32 startCharCode = qFromBigEndian(cmap + 12*middle); + quint32 startCharCode; + if (!qSafeFromBigEndian(cmap + 12 * middle, end, &startCharCode)) + return 0; + if(unicode < startCharCode) right = middle - 1; else { - quint32 endCharCode = qFromBigEndian(cmap + 12*middle + 4); - if(unicode <= endCharCode) - return qFromBigEndian(cmap + 12*middle + 8) + unicode - startCharCode; + quint32 endCharCode; + if (!qSafeFromBigEndian(cmap + 12 * middle + 4, end, &endCharCode)) + return 0; + + if (unicode <= endCharCode) { + quint32 index; + if (!qSafeFromBigEndian(cmap + 12 * middle + 8, end, &index)) + return 0; + + return index + unicode - startCharCode; + } left = middle + 1; } } diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index 9364b82bed..423b9413ed 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -243,7 +243,7 @@ public: QFontEngineGlyphCache *glyphCache(const void *key, GlyphFormat format, const QTransform &transform) const; static const uchar *getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize); - static quint32 getTrueTypeGlyphIndex(const uchar *cmap, uint unicode); + static quint32 getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint unicode); static QByteArray convertToPostscriptFontFamilyName(const QByteArray &fontFamily); diff --git a/src/gui/text/qfontengine_qpf2.cpp b/src/gui/text/qfontengine_qpf2.cpp index 4785902c99..4bb27c4d51 100644 --- a/src/gui/text/qfontengine_qpf2.cpp +++ b/src/gui/text/qfontengine_qpf2.cpp @@ -322,9 +322,9 @@ bool QFontEngineQPF2::getSfntTableData(uint tag, uchar *buffer, uint *length) co glyph_t QFontEngineQPF2::glyphIndex(uint ucs4) const { - glyph_t glyph = getTrueTypeGlyphIndex(cmap, ucs4); + glyph_t glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4); if (glyph == 0 && symbol && ucs4 < 0x100) - glyph = getTrueTypeGlyphIndex(cmap, ucs4 + 0xf000); + glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4 + 0xf000); if (!findGlyph(glyph)) glyph = 0; @@ -348,16 +348,16 @@ bool QFontEngineQPF2::stringToCMap(const QChar *str, int len, QGlyphLayout *glyp QStringIterator it(str, str + len); while (it.hasNext()) { const uint uc = it.next(); - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc); if(!glyphs->glyphs[glyph_pos] && uc < 0x100) - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000); + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000); ++glyph_pos; } } else { QStringIterator it(str, str + len); while (it.hasNext()) { const uint uc = it.next(); - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc); #if 0 && defined(DEBUG_FONTENGINE) QChar c(uc); if (!findGlyph(glyphs[glyph_pos].glyph) && !seenGlyphs.contains(c)) diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp index e45ff5d744..afb134d014 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.cpp +++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp @@ -181,9 +181,8 @@ void QWindowsFontEngine::getCMap() bool symb = false; if (ttf) { cmapTable = getSfntTable(qbswap(MAKE_TAG('c', 'm', 'a', 'p'))); - int size = 0; cmap = QFontEngine::getCMap(reinterpret_cast(cmapTable.constData()), - cmapTable.size(), &symb, &size); + cmapTable.size(), &symb, &cmapSize); } if (!cmap) { ttf = false; @@ -218,16 +217,16 @@ int QWindowsFontEngine::getGlyphIndexes(const QChar *str, int numChars, QGlyphLa QStringIterator it(str, str + numChars); while (it.hasNext()) { const uint uc = it.next(); - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc); if(!glyphs->glyphs[glyph_pos] && uc < 0x100) - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000); + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000); ++glyph_pos; } } else if (ttf) { QStringIterator it(str, str + numChars); while (it.hasNext()) { const uint uc = it.next(); - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc); ++glyph_pos; } } else { @@ -276,6 +275,7 @@ QWindowsFontEngine::QWindowsFontEngine(const QString &name, hasOutline(0), lw(0), cmap(0), + cmapSize(0), lbearing(SHRT_MIN), rbearing(SHRT_MIN), x_height(-1), @@ -343,11 +343,11 @@ glyph_t QWindowsFontEngine::glyphIndex(uint ucs4) const #if !defined(Q_OS_WINCE) if (symbol) { - glyph = getTrueTypeGlyphIndex(cmap, ucs4); + glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4); if (glyph == 0 && ucs4 < 0x100) - glyph = getTrueTypeGlyphIndex(cmap, ucs4 + 0xf000); + glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4 + 0xf000); } else if (ttf) { - glyph = getTrueTypeGlyphIndex(cmap, ucs4); + glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4); #else if (tm.tmFirstChar > 60000) { glyph = ucs4; diff --git a/src/plugins/platforms/windows/qwindowsfontengine.h b/src/plugins/platforms/windows/qwindowsfontengine.h index 02bc4008d1..c0dda6efca 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.h +++ b/src/plugins/platforms/windows/qwindowsfontengine.h @@ -147,6 +147,7 @@ private: TEXTMETRIC tm; int lw; const unsigned char *cmap; + int cmapSize; QByteArray cmapTable; mutable qreal lbearing; mutable qreal rbearing; -- cgit v1.2.3 From 40cbf1927bdd2fa9f531a047d1ba66f68c35d170 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 10 Jun 2015 07:42:42 -0700 Subject: Don't add qmutex_xxx.cpp to SOURCES, as qmutex.cpp #include's them Normally qmake catches the #include and drops the source from SOURCES. But the parser has bugs, so help it by never adding the files. The false: SOURCES += is left so that the sources can be found by Qt Creator. Task-number: QTBUG-46582 Change-Id: I049a653beeb5454c9539ffff13e667877350346b Reviewed-by: Jake Petroules --- src/corelib/thread/thread.pri | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri index 3c1ddd984a..2cb00a6cf4 100644 --- a/src/corelib/thread/thread.pri +++ b/src/corelib/thread/thread.pri @@ -46,21 +46,21 @@ SOURCES += thread/qatomic.cpp \ unix:SOURCES += thread/qthread_unix.cpp \ thread/qwaitcondition_unix.cpp -win32:SOURCES += thread/qmutex_win.cpp \ - thread/qthread_win.cpp \ +win32:SOURCES += thread/qthread_win.cpp \ thread/qwaitcondition_win.cpp -integrity:SOURCES += thread/qmutex_unix.cpp \ - thread/qthread_unix.cpp \ +integrity:SOURCES += thread/qthread_unix.cpp \ thread/qwaitcondition_unix.cpp -unix: { - mac { - SOURCES += thread/qmutex_mac.cpp - } else:linux-*:!linux-lsb-* { - SOURCES += thread/qmutex_linux.cpp - } else { - SOURCES += thread/qmutex_unix.cpp - } +false { + # files #included by others, but listed here so IDEs parsing this file know + # they are part of QtCore. Usually, qmake can find out that certain files + # are #included by others and thus remove from SOURCES, but it gets lost + # with qmutex.cpp. + SOURCES += \ + thread/qmutex_linux.cpp \ + thread/qmutex_mac.cpp \ + thread/qmutex_unix.cpp \ + thread/qmutex_win.cpp } -- cgit v1.2.3 From f18dc91da5924256de54cfe05ca8f75f03a8a829 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 9 Jul 2015 10:48:21 +0200 Subject: Fix crash when mixing widgets with QtQuick 1 and Qt Quick 2 Apply the fix from commit 313a74cc4a9a5d200b2059d3d8767fe1a274c50d also to the QWidget and the QGraphicsObject destructor. Task-number: QTCREATORBUG-10273 Change-Id: I47983b49cc4d9b75a2e1ee838e13403bc4b95a59 Reviewed-by: Friedemann Kleint --- src/widgets/graphicsview/qgraphicsitem.cpp | 11 +++++++---- src/widgets/kernel/qwidget.cpp | 11 +++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp index c9a9cf9d79..1332134000 100644 --- a/src/widgets/graphicsview/qgraphicsitem.cpp +++ b/src/widgets/graphicsview/qgraphicsitem.cpp @@ -1425,10 +1425,13 @@ QGraphicsItem::~QGraphicsItem() QObjectPrivate *p = QObjectPrivate::get(o); p->wasDeleted = true; if (p->declarativeData) { - if (QAbstractDeclarativeData::destroyed) - QAbstractDeclarativeData::destroyed(p->declarativeData, o); - if (QAbstractDeclarativeData::destroyed_qml1) - QAbstractDeclarativeData::destroyed_qml1(p->declarativeData, o); + if (static_cast(p->declarativeData)->ownedByQml1) { + if (QAbstractDeclarativeData::destroyed_qml1) + QAbstractDeclarativeData::destroyed_qml1(p->declarativeData, o); + } else { + if (QAbstractDeclarativeData::destroyed) + QAbstractDeclarativeData::destroyed(p->declarativeData, o); + } p->declarativeData = 0; } } diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index dbb229484b..ba0fcf75d0 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -1633,10 +1633,13 @@ QWidget::~QWidget() } if (d->declarativeData) { - if (QAbstractDeclarativeData::destroyed) - QAbstractDeclarativeData::destroyed(d->declarativeData, this); - if (QAbstractDeclarativeData::destroyed_qml1) - QAbstractDeclarativeData::destroyed_qml1(d->declarativeData, this); + if (static_cast(d->declarativeData)->ownedByQml1) { + if (QAbstractDeclarativeData::destroyed_qml1) + QAbstractDeclarativeData::destroyed_qml1(d->declarativeData, this); + } else { + if (QAbstractDeclarativeData::destroyed) + QAbstractDeclarativeData::destroyed(d->declarativeData, this); + } d->declarativeData = 0; // don't activate again in ~QObject } -- cgit v1.2.3 From 79ae2b3963f7356d4931de5fee67f2259ec7f6f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Wed, 13 May 2015 20:31:30 +0200 Subject: QMacStyle: Disable progress bar animations Disable progress bar animations on 10.10 Yosemite and higher - the native style does not animate them any more. Keep the indeterminate progress bar animation. Change-Id: If15fa0321e184101ef19b1050eb5e9d8f27480d8 Reviewed-by: Gabriel de Dietrich --- src/widgets/styles/qmacstyle_mac.mm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index d9238dc9d5..d13754b36b 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -4699,7 +4699,8 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter tdi.value = pb->progress; tdi.attributes = vertical ? 0 : kThemeTrackHorizontal; - if (isIndeterminate || tdi.value < tdi.max) { + const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion > QSysInfo::MV_10_9; + if (isIndeterminate || (tdi.value < tdi.max && !usingYosemiteOrLater)) { if (QProgressStyleAnimation *animation = qobject_cast(d->animation(opt->styleObject))) tdi.trackInfo.progress.phase = animation->animationStep(); else if (opt->styleObject) -- cgit v1.2.3 From 51cf05c1bde7e10aa8b11c1de07542c37263ff5d Mon Sep 17 00:00:00 2001 From: Lorn Potter Date: Tue, 23 Jun 2015 07:14:26 +1000 Subject: Add env variable to control bearer backend polling timers. Scanning and updating networks can cause transmission jitters when scanning every 10 seconds. setting QT_BEARER_POLL_TIMEOUT, in milliseconds will set polling timer for those bearer backends that require polling, such as generic and windows. Task-number: QTBUG-46015 Change-Id: I0338cd34ad78488ebef250a0114d17ce190434e8 Reviewed-by: Alex Blasche --- src/network/bearer/qnetworkconfigmanager_p.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/network/bearer/qnetworkconfigmanager_p.cpp b/src/network/bearer/qnetworkconfigmanager_p.cpp index c1e837de7b..8ff6ee828d 100644 --- a/src/network/bearer/qnetworkconfigmanager_p.cpp +++ b/src/network/bearer/qnetworkconfigmanager_p.cpp @@ -465,15 +465,18 @@ QList QNetworkConfigurationManagerPrivate::engines() const void QNetworkConfigurationManagerPrivate::startPolling() { QMutexLocker locker(&mutex); - - if(!pollTimer) { + if (!pollTimer) { pollTimer = new QTimer(this); - pollTimer->setInterval(10000); + bool ok; + int interval = qgetenv("QT_BEARER_POLL_TIMEOUT").toInt(&ok); + if (!ok) + interval = 10000;//default 10 seconds + pollTimer->setInterval(interval); pollTimer->setSingleShot(true); connect(pollTimer, SIGNAL(timeout()), this, SLOT(pollEngines())); } - if(pollTimer->isActive()) + if (pollTimer->isActive()) return; foreach (QBearerEngine *engine, sessionEngines) { @@ -482,6 +485,7 @@ void QNetworkConfigurationManagerPrivate::startPolling() break; } } + performAsyncConfigurationUpdate(); } void QNetworkConfigurationManagerPrivate::pollEngines() -- cgit v1.2.3 From 24dc5973868358d56afb375cc01c5db7d06c9fbd Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Wed, 24 Jun 2015 11:41:16 +0200 Subject: Add reference to QRegularExpression Currently there's no mention of QRegularExpression in QRegExp's documentation. This makes it hard to find QRegularExpression for user used to QRegExp. This patch adds that missing reference. Task-number: QTBUG-46816 Change-Id: If3a981d5759fbed3eecd07e046882e6da378cc4e Reviewed-by: Oswald Buddenhagen Reviewed-by: Sze Howe Koh --- src/corelib/tools/qregexp.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp index cd8c393d51..f896828e2e 100644 --- a/src/corelib/tools/qregexp.cpp +++ b/src/corelib/tools/qregexp.cpp @@ -115,6 +115,10 @@ int qFindString(const QChar *haystack, int haystackLen, int from, A good text on regexps is \e {Mastering Regular Expressions} (Third Edition) by Jeffrey E. F. Friedl, ISBN 0-596-52812-4. + \note In Qt 5, the new QRegularExpression class provides a Perl + compatible implementation of regular expressions and is recommended + in place of QRegExp. + \tableofcontents \section1 Introduction -- cgit v1.2.3 From 925822eca54d98ea4da73ea75387393e76dbcdda Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Sun, 2 Aug 2015 01:50:33 +0200 Subject: QProcessEnvironment documentation typo fix Task-number: QTBUG-45985 Change-Id: I42de961ca6d57847c135abd8395494d0e416ab05 Reviewed-by: Sze Howe Koh --- src/corelib/io/qprocess.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 914774b433..af80f4f281 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -127,7 +127,7 @@ QT_BEGIN_NAMESPACE Unix environment allows both variable names and contents to contain arbitrary binary data (except for the NUL character). QProcessEnvironment will preserve such variables, but does not support manipulating variables whose names or - values are not encodable by the current locale settings (see + values cannot be encoded by the current locale settings (see QTextCodec::codecForLocale). On Windows, the variable names are case-insensitive, but case-preserving. @@ -528,7 +528,7 @@ void QProcessPrivate::Channel::clear() QProcess can merge the two output channels, so that standard output and standard error data from the running process both use the standard output channel. Call setProcessChannelMode() with - MergedChannels before starting the process to activative + MergedChannels before starting the process to activate this feature. You also have the option of forwarding the output of the running process to the calling, main process, by passing ForwardedChannels as the argument. It is also possible to forward @@ -1266,7 +1266,7 @@ QProcess::InputChannelMode QProcess::inputChannelMode() const /*! \since 5.2 - Sets the channel mode of the QProcess standard intput + Sets the channel mode of the QProcess standard input channel to the \a mode specified. This mode will be used the next time start() is called. @@ -2311,7 +2311,7 @@ void QProcess::setArguments(const QStringList &arguments) The process may not exit as a result of calling this function (it is given the chance to prompt the user for any unsaved files, etc). - On Windows, terminate() posts a WM_CLOSE message to all toplevel windows + On Windows, terminate() posts a WM_CLOSE message to all top-level windows of the process and then to the main thread of the process itself. On Unix and OS X the \c SIGTERM signal is sent. @@ -2507,7 +2507,7 @@ QT_END_INCLUDE_NAMESPACE This function does not cache the system environment. Therefore, it's possible to obtain an updated version of the environment if low-level C - library functions like \tt setenv ot \tt putenv have been called. + library functions like \tt setenv or \tt putenv have been called. However, note that repeated calls to this function will recreate the list of environment variables, which is a non-trivial operation. @@ -2537,7 +2537,7 @@ QStringList QProcess::systemEnvironment() It is returned as a QProcessEnvironment. This function does not cache the system environment. Therefore, it's possible to obtain an updated version of the environment if low-level C library - functions like \tt setenv ot \tt putenv have been called. + functions like \tt setenv or \tt putenv have been called. However, note that repeated calls to this function will recreate the QProcessEnvironment object, which is a non-trivial operation. -- cgit v1.2.3 From 6e0a6be105565bd8e5438d0b601e583c5ea74b11 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Thu, 6 Aug 2015 10:46:14 +0200 Subject: Doc: Fix wrong reference QApplication::setStandardPalette MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-46078 Change-Id: Ifb1c650467a0fc30a0d11ad58708a64e5f9fabd5 Reviewed-by: Leena Miettinen Reviewed-by: Topi Reiniö --- src/widgets/styles/qstyle.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp index 5e51866d8f..13833d2edd 100644 --- a/src/widgets/styles/qstyle.cpp +++ b/src/widgets/styles/qstyle.cpp @@ -2263,8 +2263,9 @@ int QStyle::sliderValueFromPosition(int min, int max, int pos, int span, bool up standard palette is not used. In particular, the Windows XP, Vista, and Mac styles do not use the standard palette, but make use of native theme engines. With these styles, you should not set - the palette with QApplication::setStandardPalette(). + the palette with QApplication::setPalette(). + \sa QApplication::setPalette() */ QPalette QStyle::standardPalette() const { -- cgit v1.2.3 From 64b53ddf560b790fe4f98bcfc2329293cdc7483e Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Mon, 3 Aug 2015 00:37:30 +0200 Subject: Doc: add clarification about signals not being buffered when blocked MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-15238 Change-Id: Id762007415245f104ffe5cdfd100889f9a73ae95 Reviewed-by: Leena Miettinen Reviewed-by: Topi Reiniö --- src/corelib/kernel/qobject.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 6bc4d7e7ed..bcc4e7f8e6 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1385,6 +1385,8 @@ bool QObject::eventFilter(QObject * /* watched */, QEvent * /* event */) Note that the destroyed() signal will be emitted even if the signals for this object have been blocked. + Signals emitted while being blocked are not buffered. + \sa signalsBlocked() */ -- cgit v1.2.3 From 141f03a814245e33a1e30d89429dc92783c227bd Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Mon, 3 Aug 2015 01:13:07 +0200 Subject: Doc: mark private QChar constructors as internal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-39862 Change-Id: Ie0d533e3897200589248c803069c41661b15997e Reviewed-by: Sze Howe Koh Reviewed-by: Topi Reiniö --- src/corelib/tools/qchar.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp index 5c094772b8..1bf0aa0dec 100644 --- a/src/corelib/tools/qchar.cpp +++ b/src/corelib/tools/qchar.cpp @@ -595,12 +595,14 @@ QT_BEGIN_NAMESPACE /*! \fn QChar::QChar(char ch) + \internal Constructs a QChar corresponding to ASCII/Latin-1 character \a ch. */ /*! \fn QChar::QChar(uchar ch) + \internal Constructs a QChar corresponding to ASCII/Latin-1 character \a ch. */ -- cgit v1.2.3 From 63cd55b1722f43910436e46e7e16d2cf50c9218e Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Thu, 6 Aug 2015 09:46:45 +0200 Subject: QTreeView: add size hint handling information to uniformRowHeights Task-number: QTBUG-10802 Change-Id: I6aa60d8fd7678f02003a229e191a5ab4f93c4b9d Reviewed-by: Leena Miettinen --- src/widgets/itemviews/qtreeview.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp index 9b3e270fdd..57092a7cdc 100644 --- a/src/widgets/itemviews/qtreeview.cpp +++ b/src/widgets/itemviews/qtreeview.cpp @@ -433,6 +433,9 @@ void QTreeView::setRootIsDecorated(bool show) The height is obtained from the first item in the view. It is updated when the data changes on that item. + \note If the editor size hint is bigger than the cell size hint, then the + size hint of the editor will be used. + By default, this property is \c false. */ bool QTreeView::uniformRowHeights() const -- cgit v1.2.3 From 4d572362e882432a9cc8decbea2bcb16d4c7fbcb Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 23 Jul 2015 23:06:07 +0200 Subject: Fix link to QQ article Change-Id: I04d373778b243fdeb281c98e292359996639c95e Reviewed-by: Richard J. Moore --- src/widgets/kernel/qlayoutitem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/kernel/qlayoutitem.cpp b/src/widgets/kernel/qlayoutitem.cpp index 3d444136e3..03988aab99 100644 --- a/src/widgets/kernel/qlayoutitem.cpp +++ b/src/widgets/kernel/qlayoutitem.cpp @@ -92,7 +92,7 @@ inline static QSize toLayoutItemSize(QWidgetPrivate *priv, const QSize &size) be expressed using hasHeightForWidth(), heightForWidth(), and minimumHeightForWidth(). For more explanation see the \e{Qt Quarterly} article - \l{http://doc.qt.digia.com/qq/qq04-height-for-width.html}{Trading + \l{http://doc.qt.io/archives/qq/qq04-height-for-width.html}{Trading Height for Width}. \sa QLayout -- cgit v1.2.3 From e92c2e119beb06e3ef47ae6fd871b34ec0ef0939 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 7 Aug 2015 15:37:07 +0200 Subject: Improve readability of QTextLine's handling of (negative) right bearing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Helper functions in LineBreakHelper have been renamed from adjustFoo to calculateFoo, to signal that they do work, and are not adjusting something relative to something else. - The use of QFixed(1) and >= 0 has been replaced with an explicit constant for the case of the bearing not being calculated yet. - A helper function negativeRightBearing() has been added that returns the absolute value of any negative right bearing, making the width computations simpler. - Comments have been added and rewritten to make the logic clearer. Change-Id: I1d3a0214cfa8b4fed4551f3444b43a37d55bd69b Reviewed-by: Eskil Abrahamsen Blomfeldt Reviewed-by: Tor Arne Vestbø --- src/gui/text/qtextlayout.cpp | 81 ++++++++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 7da3e84041..013cd8ae0f 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1605,8 +1605,8 @@ namespace { bool checkFullOtherwiseExtend(QScriptLine &line); QFixed calculateNewWidth(const QScriptLine &line) const { - return line.textWidth + tmpData.textWidth + spaceData.textWidth + softHyphenWidth - - qMin(rightBearing, QFixed()); + return line.textWidth + tmpData.textWidth + spaceData.textWidth + + softHyphenWidth + negativeRightBearing(); } inline glyph_t currentGlyph() const @@ -1626,33 +1626,51 @@ namespace { } } - inline void adjustRightBearing(glyph_t glyph) + inline void calculateRightBearing(glyph_t glyph) { qreal rb; fontEngine->getGlyphBearings(glyph, 0, &rb); - rightBearing = qMin(QFixed(), QFixed::fromReal(rb)); + + // We only care about negative right bearings, so we limit the range + // of the bearing here so that we can assume it's negative in the rest + // of the code, as well ase use QFixed(1) as a sentinel to represent + // the state where we have yet to compute the right bearing. + rightBearing = qMin(QFixed::fromReal(rb), QFixed(0)); } - inline void adjustRightBearing() + inline void calculateRightBearing() { if (currentPosition <= 0) return; - adjustRightBearing(currentGlyph()); + calculateRightBearing(currentGlyph()); } - inline void adjustPreviousRightBearing() + inline void calculateRightBearingForPreviousGlyph() { if (previousGlyph > 0) - adjustRightBearing(previousGlyph); + calculateRightBearing(previousGlyph); } + static const QFixed RightBearingNotCalculated; + inline void resetRightBearing() { - rightBearing = QFixed(1); // Any positive number is defined as invalid since only - // negative right bearings are interesting to us. + rightBearing = RightBearingNotCalculated; + } + + // We express the negative right bearing as an absolute number + // so that it can be applied to the width using addition. + inline QFixed negativeRightBearing() const + { + if (rightBearing == RightBearingNotCalculated) + return QFixed(0); + + return qAbs(rightBearing); } }; +const QFixed LineBreakHelper::RightBearingNotCalculated = QFixed(1); + inline bool LineBreakHelper::checkFullOtherwiseExtend(QScriptLine &line) { LB_DEBUG("possible break width %f, spacew=%f", tmpData.textWidth.toReal(), spaceData.textWidth.toReal()); @@ -1805,7 +1823,7 @@ void QTextLine::layout_helper(int maxGlyphs) current, lbh.logClusters, lbh.glyphs); } else { lbh.tmpData.length++; - lbh.adjustPreviousRightBearing(); + lbh.calculateRightBearingForPreviousGlyph(); } line += lbh.tmpData; goto found; @@ -1887,22 +1905,29 @@ void QTextLine::layout_helper(int maxGlyphs) lbh.tmpData.textWidth += lbh.glyphs.advances[lbh.logClusters[lbh.currentPosition - 1]]; } - // The actual width of the text needs to take the right bearing into account. The - // right bearing is left-ward, which means that if the rightmost pixel is to the right - // of the advance of the glyph, the bearing will be negative. We flip the sign - // for the code to be more readable. Logic borrowed from qfontmetrics.cpp. - // We ignore the right bearing if the minimum negative bearing is too little to - // expand the text beyond the edge. if (sb_or_ws|breakany) { - QFixed rightBearing = lbh.rightBearing; // store previous right bearing + // To compute the final width of the text we need to take negative right bearing + // into account (negative right bearing means the glyph has pixel data past the + // advance length). Note that the negative right bearing is an absolute number, + // so that we can apply it to the width using straight forward addition. + + // Store previous right bearing (for the already accepted glyph) in case we + // end up breaking due to the current glyph being too wide. + QFixed previousRightBearing = lbh.rightBearing; + + // We ignore the right bearing if the minimum negative bearing is too little to + // expand the text beyond the edge. if (lbh.calculateNewWidth(line) - lbh.minimumRightBearing > line.width) - lbh.adjustRightBearing(); + lbh.calculateRightBearing(); + if (lbh.checkFullOtherwiseExtend(line)) { - // we are too wide, fix right bearing - if (rightBearing <= 0) - lbh.rightBearing = rightBearing; // take from cache + // We are too wide to accept the next glyph with its bearing, so we restore the + // right bearing to that of the previous glyph (the one that was already accepted), + // so that the bearing can be be applied to the final width of the text below. + if (previousRightBearing != LineBreakHelper::RightBearingNotCalculated) + lbh.rightBearing = previousRightBearing; else - lbh.adjustPreviousRightBearing(); + lbh.calculateRightBearingForPreviousGlyph(); if (!breakany) { line.textWidth += lbh.softHyphenWidth; @@ -1919,10 +1944,14 @@ void QTextLine::layout_helper(int maxGlyphs) LB_DEBUG("reached end of line"); lbh.checkFullOtherwiseExtend(line); found: - if (lbh.rightBearing > 0 && !lbh.whiteSpaceOrObject) // If right bearing has not yet been adjusted - lbh.adjustRightBearing(); line.textAdvance = line.textWidth; - line.textWidth -= qMin(QFixed(), lbh.rightBearing); + + // If right bearing has not been calculated yet, do that now + if (lbh.rightBearing == LineBreakHelper::RightBearingNotCalculated && !lbh.whiteSpaceOrObject) + lbh.calculateRightBearing(); + + // Then apply any negative right bearing + line.textWidth += lbh.negativeRightBearing(); if (line.length == 0) { LB_DEBUG("no break available in line, adding temp: length %d, width %f, space: length %d, width %f", -- cgit v1.2.3 From 01c15a94387f8791e2bd600519de98bd0e03f266 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 14 Jul 2015 15:32:40 +0200 Subject: Always return grayscale indexed8 from QImage::alphaChannel() We shouldn't short-cut alpha8 formats in alphaChannel, the method is used under the assumption that the returned alpha map has encoded the alphas as an indexed grayscale image. The method is also documented as not returning alpha8. Task-number: QTBUG-47138 Change-Id: I1cf16957d12e65d44f2b586d9f127fcb33c549b6 Reviewed-by: Friedemann Kleint Reviewed-by: Gunnar Sletta --- src/gui/image/qimage.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 08eb759ec2..176cdfe09f 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -4134,9 +4134,6 @@ QImage QImage::alphaChannel() const if (!d) return QImage(); - if (d->format == QImage::Format_Alpha8) - return *this; - int w = d->width; int h = d->height; @@ -4166,6 +4163,10 @@ QImage QImage::alphaChannel() const src_data += d->bytes_per_line; dest_data += image.d->bytes_per_line; } + } else if (d->format == Format_Alpha8) { + const uchar *src_data = d->data; + uchar *dest_data = image.d->data; + memcpy(dest_data, src_data, d->bytes_per_line * h); } else { QImage alpha32 = *this; bool canSkipConversion = (d->format == Format_ARGB32 || d->format == Format_ARGB32_Premultiplied); -- cgit v1.2.3 From bec8c726bf76cda94f73efc76fef6bcea5bc133a Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Sat, 25 Jul 2015 14:43:14 +0200 Subject: Fix out-of-buffer read on image upscale Avoid reading from the next pixel when the sample is fully based on the current pixel. This is particular important for the last pixel in an image when the next pixel might be outside the image buffer. Change-Id: I3607f9c6c332d11ff944ca35d216d417368f9fd5 Task-number: QTBUG-47228 Reviewed-by: Konstantin Ritt Reviewed-by: Gunnar Sletta --- src/gui/painting/qimagescale.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/painting/qimagescale.cpp b/src/gui/painting/qimagescale.cpp index 867c64c5e0..2f85e90c49 100644 --- a/src/gui/painting/qimagescale.cpp +++ b/src/gui/painting/qimagescale.cpp @@ -312,7 +312,10 @@ static void qt_qimageScaleAARGBA_up_xy(QImageScaleInfo *isi, unsigned int *dest, for (int x = dxx; x < end; x++) { const unsigned int *pix = sptr + xpoints[x]; const int xap = xapoints[x]; - *dptr = INTERPOLATE_PIXEL_256(pix[0], 256 - xap, pix[1], xap); + if (xap > 0) + *dptr = INTERPOLATE_PIXEL_256(pix[0], 256 - xap, pix[1], xap); + else + *dptr = pix[0]; dptr++; } } -- cgit v1.2.3 From d2f0f46c459bca229d30132f233e724d55490a78 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Tue, 4 Aug 2015 17:49:39 +0200 Subject: When the focus changes make sure that the IME finishes correctly When clicking onto another widget while in the middle of composing should cause it to be seen as an acceptance of the composed text so far instead of just cancelling it outright. This was validated against the Japanese, Korean and Chinese IMEs on Windows 7. Task-number: QTBUG-42344 Change-Id: I03be0cd099840f51a9550929f33e2afbbf31e85a Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/qwindowsinputcontext.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index 0cce171340..c943438570 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -206,7 +206,7 @@ void QWindowsInputContext::setFocusObject(QObject *object) // remains active when this happens resulting in a lock-up. Consecutive // key events still have VK_PROCESSKEY set and are thus ignored. if (m_compositionContext.isComposing) - imeNotifyCancelComposition(m_compositionContext.hwnd); + reset(); const QWindow *window = QGuiApplication::focusWindow(); if (object && window && window->handle()) { -- cgit v1.2.3 From 22e752bada2b1f83f94b95c3473b6c3fe13cd7c5 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Mon, 3 Aug 2015 15:47:40 +0200 Subject: QLineEdit: update IM status after selection change MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As it stood, we only told the platform about a selection change if the cursor also changed position. But if you have a selection, and press key left, the selection will be cleared without moving the cursor. And for those cases, we didn't report the selection change back to the platform. The result was that the IM status in the platform plugin got out of sync with the widget. This patch will add the missing connection that updates the platform whenever the selection changes. Change-Id: Iab0848f27207b63ed4fb47f0d4f24a6d02e87db1 Reviewed-by: Tor Arne Vestbø --- src/widgets/widgets/qlineedit_p.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp index ad3a92d35a..3f768bfbd3 100644 --- a/src/widgets/widgets/qlineedit_p.cpp +++ b/src/widgets/widgets/qlineedit_p.cpp @@ -188,6 +188,9 @@ void QLineEditPrivate::init(const QString& txt) QObject::connect(control, SIGNAL(selectionChanged()), q, SLOT(update())); + QObject::connect(control, SIGNAL(selectionChanged()), + q, SLOT(updateMicroFocus())); + QObject::connect(control, SIGNAL(displayTextChanged(QString)), q, SLOT(update())); -- cgit v1.2.3 From 7f0f6380b132be76e6d5293b7b357918b7cb3d56 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Tue, 4 Aug 2015 13:37:00 +0200 Subject: QComboBox: make editable comboboxes usable with input methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QComboBox uses a QLineEdit for text editing. But while editing, the combobox is the widget having focus, not the line edit. Instead the combobox forwards all the IM events to the line edit internally. This causes a problem since the line edit will not be able to update the platforms IM state in QWidget::updateMicroFocus() since it doesn't have focus. The result will be that the platforms IM state will get out of sync with the QLineEdit. This patch will add the missing connections that lets QComboBox update the platforms IM state when the inner QLineEdit signals that its needed. Change-Id: Ic3e0fdbf155d4dbeab31e2cd859f6e425ae87375 Reviewed-by: Tor Arne Vestbø --- src/widgets/widgets/qcombobox.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index 17762eb39d..4840b75c1b 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -1771,6 +1771,8 @@ void QComboBox::setLineEdit(QLineEdit *edit) connect(d->lineEdit, SIGNAL(editingFinished()), this, SLOT(_q_editingFinished())); connect(d->lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(editTextChanged(QString))); connect(d->lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(currentTextChanged(QString))); + connect(d->lineEdit, SIGNAL(cursorPositionChanged(int,int)), this, SLOT(updateMicroFocus())); + connect(d->lineEdit, SIGNAL(selectionChanged()), this, SLOT(updateMicroFocus())); d->lineEdit->setFrame(false); d->lineEdit->setContextMenuPolicy(Qt::NoContextMenu); d->updateFocusPolicy(); -- cgit v1.2.3 From 0cf00efcedb8f8ef438f8d204b7adf938849bf9c Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Thu, 2 Jul 2015 11:11:14 +0200 Subject: iOS: support cut/copy/paste shortcuts when using Bluetooth keyboard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Iaa602771227f64c3a477a27656362a361f78e8dd Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiostextresponder.mm | 50 +++++++++++++++++++++----- 1 file changed, 42 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index 09839790fa..e933c43a9e 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -322,6 +322,46 @@ // ------------------------------------------------------------------------- +- (void)sendKeyPressRelease:(Qt::Key)key modifiers:(Qt::KeyboardModifiers)modifiers +{ + QKeyEvent press(QEvent::KeyPress, key, modifiers); + QKeyEvent release(QEvent::KeyRelease, key, modifiers); + [self sendEventToFocusObject:press]; + [self sendEventToFocusObject:release]; +} + +- (void)cut:(id)sender +{ + Q_UNUSED(sender); + [self sendKeyPressRelease:Qt::Key_X modifiers:Qt::ControlModifier]; +} + +- (void)copy:(id)sender +{ + Q_UNUSED(sender); + [self sendKeyPressRelease:Qt::Key_C modifiers:Qt::ControlModifier]; +} + +- (void)paste:(id)sender +{ + Q_UNUSED(sender); + [self sendKeyPressRelease:Qt::Key_V modifiers:Qt::ControlModifier]; +} + +- (void)selectAll:(id)sender +{ + Q_UNUSED(sender); + [self sendKeyPressRelease:Qt::Key_A modifiers:Qt::ControlModifier]; +} + +- (void)delete:(id)sender +{ + Q_UNUSED(sender); + [self sendKeyPressRelease:Qt::Key_Delete modifiers:Qt::ControlModifier]; +} + +// ------------------------------------------------------------------------- + - (void)notifyInputDelegate:(Qt::InputMethodQueries)updatedProperties { // As documented, we should not report textWillChange/textDidChange unless the text @@ -656,10 +696,7 @@ return; if ([text isEqualToString:@"\n"]) { - QKeyEvent press(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier); - QKeyEvent release(QEvent::KeyRelease, Qt::Key_Return, Qt::NoModifier); - [self sendEventToFocusObject:press]; - [self sendEventToFocusObject:release]; + [self sendKeyPressRelease:Qt::Key_Return modifiers:Qt::NoModifier]; if (self.returnKeyType == UIReturnKeyDone) [self resignFirstResponder]; @@ -677,10 +714,7 @@ // Since we're posting im events directly to the focus object, we should do the // same for key events. Otherwise they might end up in a different place or out // of sync with im events. - QKeyEvent press(QEvent::KeyPress, (int)Qt::Key_Backspace, Qt::NoModifier); - QKeyEvent release(QEvent::KeyRelease, (int)Qt::Key_Backspace, Qt::NoModifier); - [self sendEventToFocusObject:press]; - [self sendEventToFocusObject:release]; + [self sendKeyPressRelease:Qt::Key_Backspace modifiers:Qt::NoModifier]; } @end -- cgit v1.2.3 From afaeecd4e8adc5de3a94bbdbf7e6d805d66c4241 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Fri, 3 Jul 2015 13:46:21 +0200 Subject: iOS: ensure that we restore text selection with correct cursor and anchor pos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Qt keeps track of the selection direction since a selection anchor can be placed both to the left or to the right of the cursor. On iOS, the selection should instead always be specified from left to right (using a position together with a positive length). So when restoring the selection after performing the calculation of the text rect, we need to ensure that we follow this format. Change-Id: Id8bea6c35e2781e1431ee963f601b6e9ef05dbf5 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiostextresponder.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index e933c43a9e..be9c3b9e27 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -578,7 +578,7 @@ if (cursorPos != int(r.location + r.length) || cursorPos != anchorPos) { attrs = QList(); - attrs << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, cursorPos, (cursorPos - anchorPos), 0); + attrs << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, qMin(cursorPos, anchorPos), qAbs(cursorPos - anchorPos), 0); e = QInputMethodEvent(m_markedText, attrs); [self sendEventToFocusObject:e]; } -- cgit v1.2.3 From 6129be8a4ba976c42e51012ebaa9005eb402db80 Mon Sep 17 00:00:00 2001 From: Milian Wolff Date: Mon, 27 Jul 2015 11:49:55 +0200 Subject: Prefer QT_PLUGIN_PATH over compiled-in paths. Currently, when one compiles a Qt plugin that is also installed system wide to a local path added to QT_PLUGIN_PATH, you have no way to ever load it as the global plugin will always be preferred. This is due to the order in which the QCoreApplications::libraryPaths are constructed, which always appended the QT_PLUGIN_PATH contents to the end. Now, the QT_PLUGIN_PATH contents are put first, such that the plugins in there are preferred and loaded. [ChangeLog][QtCore][QPluginLoader] Fixed the search order of Qt plugins so that paths specified by the QT_PLUGIN_PATH environment variable are searched before built-in paths. Change-Id: Iad8ca2cd34e7a622c191a416c01c1c5cc1812fc9 Reviewed-by: Oswald Buddenhagen Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qcoreapplication.cpp | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index e08f709cd2..e9fdb8c8ef 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -2541,17 +2541,6 @@ QStringList QCoreApplication::libraryPaths() if (!coreappdata()->app_libpaths) { QStringList *app_libpaths = coreappdata()->app_libpaths = new QStringList; - QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath); - if (QFile::exists(installPathPlugins)) { - // Make sure we convert from backslashes to slashes. - installPathPlugins = QDir(installPathPlugins).canonicalPath(); - if (!app_libpaths->contains(installPathPlugins)) - app_libpaths->append(installPathPlugins); - } - - // If QCoreApplication is not yet instantiated, - // make sure we add the application path when we construct the QCoreApplication - if (self) self->d_func()->appendApplicationPathToLibraryPaths(); const QByteArray libPathEnv = qgetenv("QT_PLUGIN_PATH"); if (!libPathEnv.isEmpty()) { @@ -2564,6 +2553,18 @@ QStringList QCoreApplication::libraryPaths() } } } + + QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath); + if (QFile::exists(installPathPlugins)) { + // Make sure we convert from backslashes to slashes. + installPathPlugins = QDir(installPathPlugins).canonicalPath(); + if (!app_libpaths->contains(installPathPlugins)) + app_libpaths->append(installPathPlugins); + } + + // If QCoreApplication is not yet instantiated, + // make sure we add the application path when we construct the QCoreApplication + if (self) self->d_func()->appendApplicationPathToLibraryPaths(); } return *(coreappdata()->app_libpaths); } -- cgit v1.2.3 From 2366ca059e6c4b8ae93a125eb8df8f660275d527 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 11 Aug 2015 00:48:14 -0700 Subject: Fix warning about unused local variables qopenglengineshadermanager.cpp(430): warning #177: variable "none" was declared but never referenced qopenglengineshadermanager.cpp(431): warning #177: variable "br" was declared but never referenced Change-Id: I7de033f80b0e4431b7f1ffff13f958e4a4cca16e Reviewed-by: David Faure Reviewed-by: Laszlo Agocs --- src/gui/opengl/qopenglengineshadermanager.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/gui/opengl/qopenglengineshadermanager.cpp b/src/gui/opengl/qopenglengineshadermanager.cpp index 7e53c01cba..40f4ce94c2 100644 --- a/src/gui/opengl/qopenglengineshadermanager.cpp +++ b/src/gui/opengl/qopenglengineshadermanager.cpp @@ -427,11 +427,10 @@ QOpenGLEngineShaderProg *QOpenGLEngineSharedShaders::findProgramInCache(const QO if (!inCache) shaderCache.store(newProg->program, QOpenGLContext::currentContext()); } else { - QLatin1String none("none"); - QLatin1String br("\n"); QString error; error = QLatin1String("Shader program failed to link,"); #if defined(QT_DEBUG) + QLatin1String br("\n"); error += QLatin1String("\n Shaders Used:\n"); for (int i = 0; i < newProg->program->shaders().count(); ++i) { QOpenGLShader *shader = newProg->program->shaders().at(i); -- cgit v1.2.3 From 34130b9caf001682f1decb6ba69b80657b814ed0 Mon Sep 17 00:00:00 2001 From: David Faure Date: Mon, 27 Jul 2015 00:22:11 +0200 Subject: QMimeDatabase: use QElapsedTimer instead of QDateTime::currentDateTime() This reduces the number of syscalls greatly, by avoiding the timezone conversion every time. Change-Id: I39a54def4b45f25c6e037ced6943b05ddc749c9d Reviewed-by: Milian Wolff --- src/corelib/mimetypes/qmimeprovider.cpp | 5 ++--- src/corelib/mimetypes/qmimeprovider_p.h | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp index 7342a5cd77..1ab1a44392 100644 --- a/src/corelib/mimetypes/qmimeprovider.cpp +++ b/src/corelib/mimetypes/qmimeprovider.cpp @@ -79,10 +79,9 @@ Q_CORE_EXPORT int qmime_secondsBetweenChecks = 5; // exported for the unit test bool QMimeProviderBase::shouldCheck() { - const QDateTime now = QDateTime::currentDateTime(); - if (m_lastCheck.isValid() && m_lastCheck.secsTo(now) < qmime_secondsBetweenChecks) + if (m_lastCheck.isValid() && m_lastCheck.elapsed() < qmime_secondsBetweenChecks * 1000) return false; - m_lastCheck = now; + m_lastCheck.start(); return true; } diff --git a/src/corelib/mimetypes/qmimeprovider_p.h b/src/corelib/mimetypes/qmimeprovider_p.h index 5a89ac23c3..eaf95942f7 100644 --- a/src/corelib/mimetypes/qmimeprovider_p.h +++ b/src/corelib/mimetypes/qmimeprovider_p.h @@ -51,6 +51,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -77,7 +78,7 @@ public: QMimeDatabasePrivate *m_db; protected: bool shouldCheck(); - QDateTime m_lastCheck; + QElapsedTimer m_lastCheck; }; /* -- cgit v1.2.3 From af3152adee2de79c03c0926400e920122b669c4d Mon Sep 17 00:00:00 2001 From: Milian Wolff Date: Mon, 13 Jul 2015 15:42:35 +0200 Subject: QMimeProvider: Do not crash when globPatterns is empty. Change-Id: I351a533a1f03ac2e7bdec876b657a80fac60b2ed Reviewed-by: Milian Wolff --- src/corelib/mimetypes/qmimeprovider.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp index 1ab1a44392..dab5bb81c9 100644 --- a/src/corelib/mimetypes/qmimeprovider.cpp +++ b/src/corelib/mimetypes/qmimeprovider.cpp @@ -624,7 +624,7 @@ void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data) // Let's assume that shared-mime-info is at least version 0.70 // Otherwise we would need 1) a version check, and 2) code for parsing patterns from the globs file. #if 1 - if (!mainPattern.isEmpty() && data.globPatterns.first() != mainPattern) { + if (!mainPattern.isEmpty() && (data.globPatterns.isEmpty() || data.globPatterns.first() != mainPattern)) { // ensure it's first in the list of patterns data.globPatterns.removeAll(mainPattern); data.globPatterns.prepend(mainPattern); -- cgit v1.2.3 From e3d7cf7c96964f9d55116f235dc3e0cbf5fef971 Mon Sep 17 00:00:00 2001 From: Michael Klein Date: Sat, 8 Aug 2015 21:07:58 +0100 Subject: Cocoa: fix integer multiplication overflow in qt_gettime() Task-number: QTBUG-24031 Change-Id: Iae00b10b6a7423508669ef173a80a03b3dd388c6 Reviewed-by: Thiago Macieira --- src/corelib/tools/qelapsedtimer_mac.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/corelib/tools/qelapsedtimer_mac.cpp b/src/corelib/tools/qelapsedtimer_mac.cpp index a355bf03e8..e946ac096f 100644 --- a/src/corelib/tools/qelapsedtimer_mac.cpp +++ b/src/corelib/tools/qelapsedtimer_mac.cpp @@ -59,8 +59,13 @@ static qint64 absoluteToNSecs(qint64 cpuTime) { if (info.denom == 0) mach_timebase_info(&info); +#ifdef __LP64__ + __uint128_t nsecs = static_cast<__uint128_t>(cpuTime) * info.numer / info.denom; + return static_cast(nsecs); +#else qint64 nsecs = cpuTime * info.numer / info.denom; return nsecs; +#endif } static qint64 absoluteToMSecs(qint64 cpuTime) -- cgit v1.2.3 From 314c83c0c2f91532654f869b7dc6af1b7e8538da Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 31 Jul 2015 22:55:55 +0200 Subject: Do not use Q_GLOBAL_STATIC in the implementation of QMutex Since Q_GLOBAL_STATIC might use QMutex and cause a stack overflow. Task-number: QTBUG-47554 Change-Id: I4853c5e9b9168d4a417200e2a45a1bf9cb103a30 Reviewed-by: David Faure Reviewed-by: Pierre Rossi Reviewed-by: Thiago Macieira --- src/corelib/thread/qmutex.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp index 002a9cc7bc..3269ee3ae8 100644 --- a/src/corelib/thread/qmutex.cpp +++ b/src/corelib/thread/qmutex.cpp @@ -563,7 +563,28 @@ const int FreeListConstants::Sizes[FreeListConstants::BlockCount] = { }; typedef QFreeList FreeList; -Q_GLOBAL_STATIC(FreeList, freelist); +// We cannot use Q_GLOBAL_STATIC because it uses QMutex +#if defined(Q_COMPILER_THREADSAFE_STATICS) +FreeList *freelist() +{ + static FreeList list; + return &list; +} +#else +FreeList *freelist() +{ + static QAtomicPointer list; + FreeList *local = list.loadAcquire(); + if (!local) { + local = new FreeList; + if (!list.testAndSetRelease(0, local)) { + delete local; + local = list.loadAcquire(); + } + } + return local; +} +#endif } QMutexPrivate *QMutexPrivate::allocate() -- cgit v1.2.3 From 109cdeda3008fe57aabf2385f95cf8e55b8c7da2 Mon Sep 17 00:00:00 2001 From: David Faure Date: Fri, 31 Jul 2015 14:15:56 +0200 Subject: qprintdialog_unix.cpp: fix out-of-bounds when cwd is empty. This happens when the cwd got deleted meanwhile; this warning is printed out: QFileSystemEngine::currentPath: getcwd() failed and currentPath() is empty. Not a problem in itself, but qprintdialog should not assume it's not empty, then. Change-Id: I5c89992b36ca58b6325ced399cff33aca9efb7ec Reviewed-by: Thiago Macieira --- src/printsupport/dialogs/qprintdialog_unix.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/printsupport/dialogs/qprintdialog_unix.cpp b/src/printsupport/dialogs/qprintdialog_unix.cpp index f3be45262b..502ff7d98a 100644 --- a/src/printsupport/dialogs/qprintdialog_unix.cpp +++ b/src/printsupport/dialogs/qprintdialog_unix.cpp @@ -803,7 +803,7 @@ void QUnixPrintWidgetPrivate::applyPrinterProperties() QString cur = QDir::currentPath(); if (home.at(home.length()-1) != QLatin1Char('/')) home += QLatin1Char('/'); - if (cur.at(cur.length()-1) != QLatin1Char('/')) + if (!cur.isEmpty() && cur.at(cur.length()-1) != QLatin1Char('/')) cur += QLatin1Char('/'); if (cur.left(home.length()) != home) cur = home; -- cgit v1.2.3 From 68c915f3df4316dc12d98cabc8d645532c26af3b Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Sun, 2 Aug 2015 13:52:11 +0300 Subject: ANGLE: call flex/bison by their standard names qt5.git now contains the winflexbison tools as flex/bison. Task-number: QTBUG-46852 Change-Id: I8b86cd4211ae8fb120f955be1f423f94b10b318e Reviewed-by: Thiago Macieira Reviewed-by: Maurice Kalinowski --- src/angle/src/compiler/preprocessor/preprocessor.pro | 6 +++--- src/angle/src/compiler/translator.pro | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/angle/src/compiler/preprocessor/preprocessor.pro b/src/angle/src/compiler/preprocessor/preprocessor.pro index 8c5b1555dc..759a3399b4 100644 --- a/src/angle/src/compiler/preprocessor/preprocessor.pro +++ b/src/angle/src/compiler/preprocessor/preprocessor.pro @@ -40,15 +40,15 @@ SOURCES += \ $$ANGLE_DIR/src/compiler/preprocessor/Preprocessor.cpp \ $$ANGLE_DIR/src/compiler/preprocessor/Token.cpp -# NOTE: 'win_flex' and 'bison' can be found in qt5/gnuwin32/bin -flex.commands = $$addGnuPath(win_flex) --noline --nounistd --outfile=${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_NAME} +# NOTE: 'flex' and 'bison' can be found in qt5/gnuwin32/bin +flex.commands = $$addGnuPath(flex) --noline --nounistd --outfile=${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_NAME} flex.output = ${QMAKE_FILE_BASE}.cpp flex.input = FLEX_SOURCES flex.dependency_type = TYPE_C flex.variable_out = GENERATED_SOURCES QMAKE_EXTRA_COMPILERS += flex -bison.commands = $$addGnuPath(win_bison) --no-lines --skeleton=yacc.c --output=${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_NAME} +bison.commands = $$addGnuPath(bison) --no-lines --skeleton=yacc.c --output=${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_NAME} bison.output = ${QMAKE_FILE_BASE}.cpp bison.input = BISON_SOURCES bison.dependency_type = TYPE_C diff --git a/src/angle/src/compiler/translator.pro b/src/angle/src/compiler/translator.pro index e9d16ca5af..9572a51ad4 100644 --- a/src/angle/src/compiler/translator.pro +++ b/src/angle/src/compiler/translator.pro @@ -162,15 +162,15 @@ SOURCES += \ $$ANGLE_DIR/src/third_party/compiler/ArrayBoundsClamper.cpp -# NOTE: 'win_flex' and 'bison' can be found in qt5/gnuwin32/bin -flex.commands = $$addGnuPath(win_flex) --noline --nounistd --outfile=${QMAKE_FILE_BASE}_lex.cpp ${QMAKE_FILE_NAME} +# NOTE: 'flex' and 'bison' can be found in qt5/gnuwin32/bin +flex.commands = $$addGnuPath(flex) --noline --nounistd --outfile=${QMAKE_FILE_BASE}_lex.cpp ${QMAKE_FILE_NAME} flex.output = ${QMAKE_FILE_BASE}_lex.cpp flex.input = FLEX_SOURCES flex.dependency_type = TYPE_C flex.variable_out = GENERATED_SOURCES QMAKE_EXTRA_COMPILERS += flex -bison.commands = $$addGnuPath(win_bison) --no-lines --skeleton=yacc.c --defines=${QMAKE_FILE_BASE}_tab.h \ +bison.commands = $$addGnuPath(bison) --no-lines --skeleton=yacc.c --defines=${QMAKE_FILE_BASE}_tab.h \ --output=${QMAKE_FILE_BASE}_tab.cpp ${QMAKE_FILE_NAME} bison.output = ${QMAKE_FILE_BASE}_tab.h bison.input = BISON_SOURCES -- cgit v1.2.3 From 01d0b1d6e3fe76d1cd09eeb6474c69e712f37b16 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 8 Apr 2015 14:14:16 -0700 Subject: Merge the multiple implementations of getting the local hostname This commit moves the functionality from QtNetwork's QHostInfo to QtCore. Note that due to Windows ws2_32.dll's quirky behavior of requiring WSAStartup before calling gethostname, this change required moving the initialization to QtCore too. On Linux systems, gethostname() gets the name from uname(), so we bypass the middle man and save one memcpy. Change-Id: I27eaacb532114dd188c4ffff13d32655a6301346 Reviewed-by: Erik Verbruggen Reviewed-by: Oliver Wolff Reviewed-by: Oswald Buddenhagen Reviewed-by: Thiago Macieira --- src/corelib/global/qglobal.cpp | 124 +++++++++++++++++++++++++ src/corelib/global/qsysinfo.h | 2 + src/network/kernel/qhostinfo.cpp | 16 +++- src/network/kernel/qhostinfo_unix.cpp | 9 -- src/network/kernel/qhostinfo_win.cpp | 13 +-- src/network/kernel/qhostinfo_winrt.cpp | 39 -------- src/network/socket/qnativesocketengine.cpp | 7 +- src/network/socket/qnativesocketengine_p.h | 14 --- src/network/socket/qnativesocketengine_win.cpp | 19 ---- 9 files changed, 144 insertions(+), 99 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 37a765b40a..77ac53f7e9 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -65,6 +65,20 @@ # endif #endif +#ifdef Q_OS_WINRT +#include +#include +#include +#include +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::Networking; +using namespace ABI::Windows::Networking::Connectivity; +using namespace ABI::Windows::Networking::Sockets; +#endif + #if defined(Q_OS_VXWORKS) && defined(_WRS_KERNEL) # include #endif @@ -90,6 +104,10 @@ #include #endif +#ifdef Q_OS_BSD4 +#include +#endif + #include "archdetect.cpp" QT_BEGIN_NAMESPACE @@ -1887,6 +1905,36 @@ QT_END_INCLUDE_NAMESPACE #ifndef Q_OS_WINRT +# ifndef QT_BOOTSTRAPPED +class QWindowsSockInit +{ +public: + QWindowsSockInit(); + ~QWindowsSockInit(); + int version; +}; + +QWindowsSockInit::QWindowsSockInit() +: version(0) +{ + //### should we try for 2.2 on all platforms ?? + WSAData wsadata; + + // IPv6 requires Winsock v2.0 or better. + if (WSAStartup(MAKEWORD(2,0), &wsadata) != 0) { + qWarning("QTcpSocketAPI: WinSock v2.0 initialization failed."); + } else { + version = 0x20; + } +} + +QWindowsSockInit::~QWindowsSockInit() +{ + WSACleanup(); +} +Q_GLOBAL_STATIC(QWindowsSockInit, winsockInit) +# endif // QT_BOOTSTRAPPED + # ifndef Q_OS_WINCE // Determine Windows versions >= 8 by querying the version of kernel32.dll. @@ -2775,6 +2823,82 @@ QString QSysInfo::prettyProductName() return unknownText(); } +#ifndef QT_BOOTSTRAPPED +/*! + \since 5.6 + + Returns this machine's host name, if one is configured. Note that hostnames + are not guaranteed to be globally unique, especially if they were + configured automatically. + + This function does not guarantee the returned host name is a Fully + Qualified Domain Name (FQDN). For that, use QHostInfo to resolve the + returned name to an FQDN. + + This function returns the same as QHostInfo::localHostName(). + + \sa QHostInfo::localDomainName + */ +QString QSysInfo::machineHostName() +{ +#if defined(Q_OS_LINUX) + // gethostname(3) on Linux just calls uname(2), so do it ourselves + // and avoid a memcpy + struct utsname u; + if (uname(&u) == 0) + return QString::fromLocal8Bit(u.nodename); +#elif defined(Q_OS_WINRT) + ComPtr statics; + GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Connectivity_NetworkInformation).Get(), &statics); + + ComPtr> hostNames; + statics->GetHostNames(&hostNames); + if (!hostNames) + return QString(); + + unsigned int size; + hostNames->get_Size(&size); + if (size == 0) + return QString(); + + for (unsigned int i = 0; i < size; ++i) { + ComPtr hostName; + hostNames->GetAt(i, &hostName); + HostNameType type; + hostName->get_Type(&type); + if (type != HostNameType_DomainName) + continue; + + HString name; + hostName->get_CanonicalName(name.GetAddressOf()); + UINT32 length; + PCWSTR rawString = name.GetRawBuffer(&length); + return QString::fromWCharArray(rawString, length); + } + ComPtr firstHost; + hostNames->GetAt(0, &firstHost); + + HString name; + firstHost->get_CanonicalName(name.GetAddressOf()); + UINT32 length; + PCWSTR rawString = name.GetRawBuffer(&length); + return QString::fromWCharArray(rawString, length); +#else +# ifdef Q_OS_WIN + // Important: QtNetwork depends on machineHostName() initializing ws2_32.dll + winsockInit(); +# endif + + char hostName[512]; + if (gethostname(hostName, sizeof(hostName)) == -1) + return QString(); + hostName[sizeof(hostName) - 1] = '\0'; + return QString::fromLocal8Bit(hostName); +#endif + return QString(); +} +#endif // QT_BOOTSTRAPPED + /*! \macro void Q_ASSERT(bool test) \relates diff --git a/src/corelib/global/qsysinfo.h b/src/corelib/global/qsysinfo.h index d40e6659c7..27a285fd36 100644 --- a/src/corelib/global/qsysinfo.h +++ b/src/corelib/global/qsysinfo.h @@ -186,6 +186,8 @@ public: static QString productType(); static QString productVersion(); static QString prettyProductName(); + + static QString machineHostName(); }; QT_END_NAMESPACE diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index a2ac9065fd..c6c09542e7 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -415,10 +415,22 @@ void QHostInfo::setErrorString(const QString &str) /*! \fn QString QHostInfo::localHostName() - Returns the host name of this machine. + Returns this machine's host name, if one is configured. Note that hostnames + are not guaranteed to be globally unique, especially if they were + configured automatically. - \sa hostName() + This function does not guarantee the returned host name is a Fully + Qualified Domain Name (FQDN). For that, use fromName() to resolve the + returned name to an FQDN. + + This function returns the same as QSysInfo::machineHostName(). + + \sa hostName(), localDomainName() */ +QString QHostInfo::localHostName() +{ + return QSysInfo::machineHostName(); +} /*! \fn QString QHostInfo::localDomainName() diff --git a/src/network/kernel/qhostinfo_unix.cpp b/src/network/kernel/qhostinfo_unix.cpp index 90a6f763f7..266a67771c 100644 --- a/src/network/kernel/qhostinfo_unix.cpp +++ b/src/network/kernel/qhostinfo_unix.cpp @@ -315,15 +315,6 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) return results; } -QString QHostInfo::localHostName() -{ - char hostName[512]; - if (gethostname(hostName, sizeof(hostName)) == -1) - return QString(); - hostName[sizeof(hostName) - 1] = '\0'; - return QString::fromLocal8Bit(hostName); -} - QString QHostInfo::localDomainName() { #if !defined(Q_OS_VXWORKS) && !defined(Q_OS_ANDROID) diff --git a/src/network/kernel/qhostinfo_win.cpp b/src/network/kernel/qhostinfo_win.cpp index e044728198..fc65ce9fa2 100644 --- a/src/network/kernel/qhostinfo_win.cpp +++ b/src/network/kernel/qhostinfo_win.cpp @@ -111,7 +111,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) QMutexLocker locker(&qPrivCEMutex); #endif - QWindowsSockInit winSock; + QSysInfo::machineHostName(); // this initializes ws2_32.dll // Load res_init on demand. static QBasicAtomicInt triedResolve = Q_BASIC_ATOMIC_INITIALIZER(false); @@ -256,17 +256,6 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) return results; } -QString QHostInfo::localHostName() -{ - QWindowsSockInit winSock; - - char hostName[512]; - if (gethostname(hostName, sizeof(hostName)) == -1) - return QString(); - hostName[sizeof(hostName) - 1] = '\0'; - return QString::fromLocal8Bit(hostName); -} - // QString QHostInfo::localDomainName() defined in qnetworkinterface_win.cpp QT_END_NAMESPACE diff --git a/src/network/kernel/qhostinfo_winrt.cpp b/src/network/kernel/qhostinfo_winrt.cpp index 1a97fe0e40..3d2344726b 100644 --- a/src/network/kernel/qhostinfo_winrt.cpp +++ b/src/network/kernel/qhostinfo_winrt.cpp @@ -130,45 +130,6 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) return results; } -QString QHostInfo::localHostName() -{ - ComPtr statics; - GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Connectivity_NetworkInformation).Get(), &statics); - - ComPtr> hostNames; - statics->GetHostNames(&hostNames); - if (!hostNames) - return QString(); - - unsigned int size; - hostNames->get_Size(&size); - if (size == 0) - return QString(); - - for (unsigned int i = 0; i < size; ++i) { - ComPtr hostName; - hostNames->GetAt(i, &hostName); - HostNameType type; - hostName->get_Type(&type); - if (type != HostNameType_DomainName) - continue; - - HString name; - hostName->get_CanonicalName(name.GetAddressOf()); - UINT32 length; - PCWSTR rawString = name.GetRawBuffer(&length); - return QString::fromWCharArray(rawString, length); - } - ComPtr firstHost; - hostNames->GetAt(0, &firstHost); - - HString name; - firstHost->get_CanonicalName(name.GetAddressOf()); - UINT32 length; - PCWSTR rawString = name.GetRawBuffer(&length); - return QString::fromWCharArray(rawString, length); -} - // QString QHostInfo::localDomainName() defined in qnetworkinterface_win.cpp QT_END_NAMESPACE diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp index 33bf3af0b5..22151b8e56 100644 --- a/src/network/socket/qnativesocketengine.cpp +++ b/src/network/socket/qnativesocketengine.cpp @@ -152,10 +152,6 @@ QT_BEGIN_NAMESPACE /*! \internal Constructs the private class and initializes all data members. - - On Windows, WSAStartup is called "recursively" for every - concurrent QNativeSocketEngine. This is safe, because WSAStartup and - WSACleanup are reference counted. */ QNativeSocketEnginePrivate::QNativeSocketEnginePrivate() : socketDescriptor(-1), @@ -163,6 +159,9 @@ QNativeSocketEnginePrivate::QNativeSocketEnginePrivate() : writeNotifier(0), exceptNotifier(0) { +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) + QSysInfo::machineHostName(); // this initializes ws2_32.dll +#endif } /*! \internal diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h index 24909bf310..653309302c 100644 --- a/src/network/socket/qnativesocketengine_p.h +++ b/src/network/socket/qnativesocketengine_p.h @@ -173,16 +173,6 @@ private: Q_DISABLE_COPY(QNativeSocketEngine) }; -#ifdef Q_OS_WIN -class QWindowsSockInit -{ -public: - QWindowsSockInit(); - ~QWindowsSockInit(); - int version; -}; -#endif - class QSocketNotifier; class QNativeSocketEnginePrivate : public QAbstractSocketEnginePrivate @@ -196,10 +186,6 @@ public: QSocketNotifier *readNotifier, *writeNotifier, *exceptNotifier; -#ifdef Q_OS_WIN - QWindowsSockInit winSock; -#endif - enum ErrorString { NonBlockingInitFailedErrorString, BroadcastingInitFailedErrorString, diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 7856db0487..8c3f68f04f 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -320,25 +320,6 @@ static inline int qt_socket_getMaxMsgSize(qintptr socketDescriptor) return value; } -QWindowsSockInit::QWindowsSockInit() -: version(0) -{ - //### should we try for 2.2 on all platforms ?? - WSAData wsadata; - - // IPv6 requires Winsock v2.0 or better. - if (WSAStartup(MAKEWORD(2,0), &wsadata) != 0) { - qWarning("QTcpSocketAPI: WinSock v2.0 initialization failed."); - } else { - version = 0x20; - } -} - -QWindowsSockInit::~QWindowsSockInit() -{ - WSACleanup(); -} - // MS Transport Provider IOCTL to control // reporting PORT_UNREACHABLE messages // on UDP sockets via recv/WSARecv/etc. -- cgit v1.2.3 From 6d8c7a61f52f4169eb3587d3da896efed0083dea Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 11 Aug 2015 00:09:46 -0700 Subject: Fix -Wcast-qual warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qwidget.cpp:12864:70: error: cast from type ‘const QWidget*’ to type ‘void*’ casts away qualifiers [-Werror=cast-qual] Change-Id: I7de033f80b0e4431b7f1ffff13f956cb26108af7 Reviewed-by: Martin Smith --- src/gui/kernel/qscreen.cpp | 2 +- src/gui/kernel/qwindow.cpp | 2 +- src/tools/qdoc/node.cpp | 2 +- src/widgets/kernel/qwidget.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp index 407b4ee9b6..b6b50372ae 100644 --- a/src/gui/kernel/qscreen.cpp +++ b/src/gui/kernel/qscreen.cpp @@ -698,7 +698,7 @@ Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QScreen *screen) { const QDebugStateSaver saver(debug); debug.nospace(); - debug << "QScreen(" << (void *)screen; + debug << "QScreen(" << (const void *)screen; if (screen) { debug << ", name=" << screen->name(); if (debug.verbosity() > 2) { diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index e93e964c6b..89bd119564 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -2508,7 +2508,7 @@ QDebug operator<<(QDebug debug, const QWindow *window) QDebugStateSaver saver(debug); debug.nospace(); if (window) { - debug << window->metaObject()->className() << '(' << (void *)window; + debug << window->metaObject()->className() << '(' << (const void *)window; if (!window->objectName().isEmpty()) debug << ", name=" << window->objectName(); if (debug.verbosity() > 2) { diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp index 8646e699a9..ebb54735d4 100644 --- a/src/tools/qdoc/node.cpp +++ b/src/tools/qdoc/node.cpp @@ -2030,7 +2030,7 @@ QString FunctionNode::signature(bool values) const PropertyNode::FunctionRole PropertyNode::role(const FunctionNode* fn) const { for (int i=0; i<4; i++) { - if (functions_[i].contains((Node*)fn)) + if (functions_[i].contains(const_cast(fn))) return (FunctionRole) i; } return Notifier; diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 1ebf782edf..91641db60d 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -12861,7 +12861,7 @@ QDebug operator<<(QDebug debug, const QWidget *widget) const QDebugStateSaver saver(debug); debug.nospace(); if (widget) { - debug << widget->metaObject()->className() << '(' << (void *)widget; + debug << widget->metaObject()->className() << '(' << (const void *)widget; if (!widget->objectName().isEmpty()) debug << ", name=" << widget->objectName(); if (debug.verbosity() > 2) { -- cgit v1.2.3 From 1183fb3ea9a5a8777454c662194ee9c3a02686c6 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 11 Aug 2015 16:45:29 -0700 Subject: Doc: Remove the section about IPv6 site-local addresses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Site-local addresses were deprecated in RFC 3879 (September 2004) and RFC 4193 (October 2005) replaced them with Unique Local Address. ULAs are part of the global range but supposedly unique to an organization. Change-Id: I7de033f80b0e4431b7f1ffff13f98d2124c5cffc Reviewed-by: Martin Smith Reviewed-by: Topi Reiniö --- src/network/kernel/qhostaddress.cpp | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src') diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp index 58c0de1f3b..1fcfd1e1db 100644 --- a/src/network/kernel/qhostaddress.cpp +++ b/src/network/kernel/qhostaddress.cpp @@ -775,11 +775,6 @@ QString QHostAddress::toString() const on your host. Link-local addresses ("fe80...") are generated from the MAC address of the local network adaptor, and are not guaranteed to be unique. - \li Site-local: Addresses that are local to the site / private network - (e.g., the company intranet). Site-local addresses ("fec0...") are - usually distributed by the site router, and are not guaranteed to be - unique outside of the local site. - \li Global: For globally routable addresses, such as public servers on the Internet. -- cgit v1.2.3 From 40a4105faef14268410b3ab4ae432f386c74d0e2 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Wed, 12 Aug 2015 17:00:49 +0200 Subject: Fix QChar char constructors documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reverts the wrongly added \internal and adds a warning for users that the constructors will not be available if QT_NO_CAST_FROM_ASCII is defined Task-number: QTBUG-39862 Change-Id: I038eea3f4eef0b914b470309a2f515741eec35a9 Reviewed-by: Topi Reiniö Reviewed-by: Sze Howe Koh --- src/corelib/tools/qchar.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp index 1bf0aa0dec..014d91162a 100644 --- a/src/corelib/tools/qchar.cpp +++ b/src/corelib/tools/qchar.cpp @@ -595,16 +595,24 @@ QT_BEGIN_NAMESPACE /*! \fn QChar::QChar(char ch) - \internal Constructs a QChar corresponding to ASCII/Latin-1 character \a ch. + + \note This constructor is not available when \c QT_NO_CAST_FROM_ASCII + is defined. + + \sa QT_NO_CAST_FROM_ASCII */ /*! \fn QChar::QChar(uchar ch) - \internal Constructs a QChar corresponding to ASCII/Latin-1 character \a ch. + + \note This constructor is not available when \c QT_NO_CAST_FROM_ASCII + is defined. + + \sa QT_NO_CAST_FROM_ASCII */ /*! -- cgit v1.2.3 From c21113f9eefee0fb38252d8bb31c3fe078fcc4af Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 13 Aug 2015 21:01:14 -0700 Subject: QHostAddress: don't inline the parse() function It's called everywhere due to QT_ENSURE_PARSED and it's big. There's no need to duplicate it everywhere. Change-Id: I7de033f80b0e4431b7f1ffff13fa383f29114712 Reviewed-by: Richard J. Moore --- src/network/kernel/qhostaddress.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp index 1fcfd1e1db..3d51ab4025 100644 --- a/src/network/kernel/qhostaddress.cpp +++ b/src/network/kernel/qhostaddress.cpp @@ -193,7 +193,7 @@ static bool parseIp6(const QString &address, QIPAddressUtils::IPv6Address &addr, return QIPAddressUtils::parseIp6(addr, tmp.constBegin(), tmp.constEnd()) == 0; } -bool QHostAddressPrivate::parse() +Q_NEVER_INLINE bool QHostAddressPrivate::parse() { isParsed = true; protocol = QAbstractSocket::UnknownNetworkLayerProtocol; -- cgit v1.2.3 From 45e59556ed8bececf1300b8774ec6d37b68b735c Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 11 Aug 2015 15:22:53 -0700 Subject: Fix warning of unused variable Only happens on systems without getifaddrs, which we aren't usually testing. Change-Id: I7de033f80b0e4431b7f1ffff13f9889f5cfdea5b Reviewed-by: Richard J. Moore --- src/network/kernel/qnetworkinterface_unix.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/network/kernel/qnetworkinterface_unix.cpp b/src/network/kernel/qnetworkinterface_unix.cpp index 9c5ba4e799..04e1ce7edd 100644 --- a/src/network/kernel/qnetworkinterface_unix.cpp +++ b/src/network/kernel/qnetworkinterface_unix.cpp @@ -127,14 +127,13 @@ static QNetworkInterface::InterfaceFlags convertFlags(uint rawFlags) #ifdef QT_NO_GETIFADDRS // getifaddrs not available -static const int STORAGEBUFFER_GROWTH = 256; - static QSet interfaceNames(int socket) { QSet result; #ifdef QT_NO_IPV6IFNAME QByteArray storageBuffer; struct ifconf interfaceList; + static const int STORAGEBUFFER_GROWTH = 256; forever { // grow the storage buffer -- cgit v1.2.3 From 060b7ffe5bb5641fac103358f628fe38daf460d1 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 18 Mar 2015 08:42:51 +0900 Subject: QtTest: Add QHostAddress support for QCOMPARE failures Change-Id: Iee8cbc07c4434ce9b560ffff13cc6dad04a5a554 Reviewed-by: Richard J. Moore --- src/testlib/qtest.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'src') diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h index 1d8b195907..8da16af91e 100644 --- a/src/testlib/qtest.h +++ b/src/testlib/qtest.h @@ -51,6 +51,9 @@ #include #include +#ifdef QT_NETWORK_LIB +# include +#endif QT_BEGIN_NAMESPACE @@ -162,6 +165,23 @@ template<> inline char *toString(const QVariant &v) return qstrdup(vstring.constData()); } +#ifdef QT_NETWORK_LIB +template<> inline char *toString(const QHostAddress &addr) +{ + switch (addr.protocol()) { + case QAbstractSocket::UnknownNetworkLayerProtocol: + return qstrdup(""); + case QAbstractSocket::AnyIPProtocol: + return qstrdup("QHostAddress::Any"); + case QAbstractSocket::IPv4Protocol: + case QAbstractSocket::IPv6Protocol: + break; + } + + return qstrdup(addr.toString().toLatin1().constData()); +} +#endif + template<> inline bool qCompare(QString const &t1, QLatin1String const &t2, const char *actual, const char *expected, const char *file, int line) -- cgit v1.2.3 From 3bfba054cb310d06543b08b5efb88de9b34a992e Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 16 Mar 2015 18:59:49 -0700 Subject: Add QHostAddress::isMulticast This complements QHostAddress::isLoopback. The only missing check now is for the "Any" address types, though operator== is quite fast nowadays. Change-Id: Iee8cbc07c4434ce9b560ffff13cc2691e15014b6 Reviewed-by: Richard J. Moore --- src/network/kernel/qhostaddress.cpp | 16 ++++++++++++++++ src/network/kernel/qhostaddress.h | 1 + 2 files changed, 17 insertions(+) (limited to 'src') diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp index 3d51ab4025..579567023e 100644 --- a/src/network/kernel/qhostaddress.cpp +++ b/src/network/kernel/qhostaddress.cpp @@ -1090,6 +1090,22 @@ bool QHostAddress::isLoopback() const return false; } +/*! + \since 5.6 + + Returns \c true if the address is an IPv4 or IPv6 multicast address, \c + false otherwise. +*/ +bool QHostAddress::isMulticast() const +{ + QT_ENSURE_PARSED(this); + if ((d->a & 0xF0000000) == 0xE0000000) + return true; // 224.0.0.0-239.255.255.255 (including v4-mapped IPv6 addresses) + if (d->protocol == QAbstractSocket::IPv6Protocol) + return d->a6.c[0] == 0xff; + return false; +} + #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const QHostAddress &address) { diff --git a/src/network/kernel/qhostaddress.h b/src/network/kernel/qhostaddress.h index 8478240d28..cea54a2984 100644 --- a/src/network/kernel/qhostaddress.h +++ b/src/network/kernel/qhostaddress.h @@ -124,6 +124,7 @@ public: bool isInSubnet(const QPair &subnet) const; bool isLoopback() const; + bool isMulticast() const; static QPair parseSubnet(const QString &subnet); -- cgit v1.2.3 From 1ff66a79626d40a8379a639a0fae3696fc7a06c0 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 18 Feb 2015 12:36:47 -0800 Subject: QProcess: Ensure that the stdin buffer is cleared on start() The buffer may have been left dirty if we were unable to write all the data to the child process in the previous run. So ensure we clear it before starting a new one. We already did that for stdout and stderr, for some reason. Task-number: QTBUG-44517 Change-Id: I1a800c709d3543699131ffff13c419da3bbffacf Reviewed-by: Kai Koehne Reviewed-by: Joerg Bornemann Reviewed-by: Thiago Macieira Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qprocess.cpp | 3 ++- src/corelib/io/qwindowspipewriter.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 176386d6df..c29b97b535 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. -** Copyright (C) 2014 Intel Corporation +** Copyright (C) 2015 Intel Corporation ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -2135,6 +2135,7 @@ void QProcessPrivate::start(QIODevice::OpenMode mode) qDebug() << "QProcess::start(" << program << ',' << arguments << ',' << mode << ')'; #endif + stdinChannel.buffer.clear(); stdoutChannel.buffer.clear(); stderrChannel.buffer.clear(); diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp index add2ac94da..57053f129a 100644 --- a/src/corelib/io/qwindowspipewriter.cpp +++ b/src/corelib/io/qwindowspipewriter.cpp @@ -85,7 +85,7 @@ qint64 QWindowsPipeWriter::write(const char *ptr, qint64 maxlen) return -1; QMutexLocker locker(&lock); - data.append(QByteArray(ptr, maxlen)); + data.append(ptr, maxlen); waitCondition.wakeOne(); return maxlen; } -- cgit v1.2.3 From 4ccf5c6f4a411d367749565323f7c7fd469b025e Mon Sep 17 00:00:00 2001 From: David Faure Date: Thu, 13 Aug 2015 23:51:34 +0200 Subject: QMimeDatabase: adapt to changes in shared-mime-info 1.3 The generated xml file is now lowercase. This was changed in shared-mime-info 3805d0bcf2. It led to runtime warnings "No file found for ...", which helped notice the bug. Change-Id: I31f0fc7f0fe8a098c3f79c0bcbeeb1909d2cc05a Reviewed-by: Thiago Macieira --- src/corelib/mimetypes/qmimeprovider.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp index dab5bb81c9..887db51e5c 100644 --- a/src/corelib/mimetypes/qmimeprovider.cpp +++ b/src/corelib/mimetypes/qmimeprovider.cpp @@ -560,10 +560,13 @@ void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data) // load comment and globPatterns const QString file = data.name + QLatin1String(".xml"); - const QStringList mimeFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QString::fromLatin1("mime/") + file); + // shared-mime-info since 1.3 lowercases the xml files + QStringList mimeFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QString::fromLatin1("mime/") + file.toLower()); if (mimeFiles.isEmpty()) { - // TODO: ask Thiago about this - qWarning() << "No file found for" << file << ", even though the file appeared in a directory listing."; + mimeFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QString::fromLatin1("mime/") + file); // pre-1.3 + } + if (mimeFiles.isEmpty()) { + qWarning() << "No file found for" << file << ", even though update-mime-info said it would exist."; qWarning() << "Either it was just removed, or the directory doesn't have executable permission..."; qWarning() << QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime"), QStandardPaths::LocateDirectory); return; -- cgit v1.2.3 From 1bf9cb44e24ba2d795e3c242276d07acb0e46322 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 11 Aug 2015 15:21:30 -0700 Subject: QNetworkInterface: prefer SIOCGIFINDEX over if_nametoindex On Linux (on a bad system without getifaddrs), the ioctl for SIOCGIFINDEX should be faster than if_nametoindex. The ioctl on the already open socket will require one syscall, while if_nametoindex will require at least one more (to open the socket), probably more. Change-Id: I7de033f80b0e4431b7f1ffff13f9888bf2044105 Reviewed-by: Richard J. Moore --- src/network/kernel/qnetworkinterface_unix.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/network/kernel/qnetworkinterface_unix.cpp b/src/network/kernel/qnetworkinterface_unix.cpp index 04e1ce7edd..38cddd8f7a 100644 --- a/src/network/kernel/qnetworkinterface_unix.cpp +++ b/src/network/kernel/qnetworkinterface_unix.cpp @@ -185,9 +185,14 @@ static QNetworkInterfacePrivate *findInterface(int socket, QList= 0) + ifindex = req.ifr_ifindex; +# else ifindex = if_nametoindex(req.ifr_name); +# endif // find the interface data QList::Iterator if_it = interfaces.begin(); -- cgit v1.2.3 From 8fa44b382f80d57a39306ba13c23c4e6b8c0847d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 11 Aug 2015 15:23:55 -0700 Subject: QNetworkInterface: Merge the two sections of code that do SIOCGIFxxx The separation was accidental due to refactoring. It does not need to exist. Change-Id: I7de033f80b0e4431b7f1ffff13f988adc47d57d5 Reviewed-by: Richard J. Moore --- src/network/kernel/qnetworkinterface_unix.cpp | 42 +++++++++++++-------------- 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/network/kernel/qnetworkinterface_unix.cpp b/src/network/kernel/qnetworkinterface_unix.cpp index 38cddd8f7a..cc53087024 100644 --- a/src/network/kernel/qnetworkinterface_unix.cpp +++ b/src/network/kernel/qnetworkinterface_unix.cpp @@ -218,6 +218,27 @@ static QNetworkInterfacePrivate *findInterface(int socket, QListindex = ifindex; interfaces << iface; + } + + return iface; +} + +static QList interfaceListing() +{ + QList interfaces; + + int socket; + if ((socket = qt_safe_socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) == -1) + return interfaces; // error + + QSet names = interfaceNames(socket); + QSet::ConstIterator it = names.constBegin(); + for ( ; it != names.constEnd(); ++it) { + ifreq req; + memset(&req, 0, sizeof(ifreq)); + memcpy(req.ifr_name, *it, qMin(it->length() + 1, sizeof(req.ifr_name) - 1)); + + QNetworkInterfacePrivate *iface = findInterface(socket, interfaces, req); #ifdef SIOCGIFNAME // Get the canonical name @@ -246,27 +267,6 @@ static QNetworkInterfacePrivate *findInterface(int socket, QListhardwareAddress = iface->makeHwAddress(6, addr); } #endif - } - - return iface; -} - -static QList interfaceListing() -{ - QList interfaces; - - int socket; - if ((socket = qt_safe_socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) == -1) - return interfaces; // error - - QSet names = interfaceNames(socket); - QSet::ConstIterator it = names.constBegin(); - for ( ; it != names.constEnd(); ++it) { - ifreq req; - memset(&req, 0, sizeof(ifreq)); - memcpy(req.ifr_name, *it, qMin(it->length() + 1, sizeof(req.ifr_name) - 1)); - - QNetworkInterfacePrivate *iface = findInterface(socket, interfaces, req); // Get the interface broadcast address QNetworkAddressEntry entry; -- cgit v1.2.3 From c72311440b160f37d5175c131508d37249889a36 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 11 Aug 2015 16:42:34 -0700 Subject: QNetworkInterface: make the name lookup search numbers in string forms That's how QHostAddress::scopeId() stores them, so we ought to look them up the same way. Change-Id: I7de033f80b0e4431b7f1ffff13f98cf87d45ebc6 Reviewed-by: Richard J. Moore --- src/network/kernel/qhostaddress.cpp | 12 +++++++++--- src/network/kernel/qnetworkinterface.cpp | 14 ++++++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp index 579567023e..5087576b44 100644 --- a/src/network/kernel/qhostaddress.cpp +++ b/src/network/kernel/qhostaddress.cpp @@ -785,7 +785,7 @@ QString QHostAddress::toString() const usually the same as the interface name (e.g., "eth0", "en1") or number (e.g., "1", "2"). - \sa setScopeId() + \sa setScopeId(), QNetworkInterface, QNetworkInterface::interfaceFromName */ QString QHostAddress::scopeId() const { @@ -796,8 +796,14 @@ QString QHostAddress::scopeId() const /*! \since 4.1 - Sets the IPv6 scope ID of the address to \a id. If the address - protocol is not IPv6, this function does nothing. + Sets the IPv6 scope ID of the address to \a id. If the address protocol is + not IPv6, this function does nothing. The scope ID may be set as an + interface name (such as "eth0" or "en1") or as an integer representing the + interface index. If \a id is an interface name, QtNetwork will convert to + an interface index using QNetworkInterface::interfaceIndexFromName() before + calling the operating system networking functions. + + \sa scopeId(), QNetworkInterface, QNetworkInterface::interfaceFromName */ void QHostAddress::setScopeId(const QString &id) { diff --git a/src/network/kernel/qnetworkinterface.cpp b/src/network/kernel/qnetworkinterface.cpp index 2fbbf56e0f..4a527052d1 100644 --- a/src/network/kernel/qnetworkinterface.cpp +++ b/src/network/kernel/qnetworkinterface.cpp @@ -86,9 +86,16 @@ QSharedDataPointer QNetworkInterfaceManager::interface { QList > interfaceList = allInterfaces(); QList >::ConstIterator it = interfaceList.constBegin(); - for ( ; it != interfaceList.constEnd(); ++it) - if ((*it)->name == name) + + bool ok; + uint index = name.toUInt(&ok); + + for ( ; it != interfaceList.constEnd(); ++it) { + if (ok && (*it)->index == int(index)) return *it; + else if ((*it)->name == name) + return *it; + } return empty; } @@ -516,6 +523,9 @@ QList QNetworkInterface::addressEntries() const name. If no such interface exists, this function returns an invalid QNetworkInterface object. + The string \a name may be either an actual interface name (such as "eth0" + or "en1") or an interface index in string form ("1", "2", etc.). + \sa name(), isValid() */ QNetworkInterface QNetworkInterface::interfaceFromName(const QString &name) -- cgit v1.2.3 From 4fbc63f03bf14c3c5e8e2ffde243fe81535d3007 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 11 Aug 2015 19:39:43 -0700 Subject: Fix thread-safety of qnetworkinterface_win.cpp:resolveLibs Change-Id: Ia4b5103c9c590c24de9a43c5c7097b0c7b83e679 Reviewed-by: Richard J. Moore --- src/network/kernel/qnetworkinterface_win.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/network/kernel/qnetworkinterface_win.cpp b/src/network/kernel/qnetworkinterface_win.cpp index ddeb6c111f..eeb2e1665a 100644 --- a/src/network/kernel/qnetworkinterface_win.cpp +++ b/src/network/kernel/qnetworkinterface_win.cpp @@ -58,11 +58,11 @@ static void resolveLibs() static bool done = false; if (!done) { - done = true; - HINSTANCE iphlpapiHnd = QSystemLibrary::load(L"iphlpapi"); - if (iphlpapiHnd == NULL) + if (iphlpapiHnd == NULL) { + done = true; return; + } #if defined(Q_OS_WINCE) ptrGetAdaptersInfo = (PtrGetAdaptersInfo)GetProcAddress(iphlpapiHnd, L"GetAdaptersInfo"); @@ -73,6 +73,7 @@ static void resolveLibs() ptrGetAdaptersAddresses = (PtrGetAdaptersAddresses)GetProcAddress(iphlpapiHnd, "GetAdaptersAddresses"); ptrGetNetworkParams = (PtrGetNetworkParams)GetProcAddress(iphlpapiHnd, "GetNetworkParams"); #endif + done = true; } } -- cgit v1.2.3 From 3ae90ed371f5d10c0eaefce148e0c88157c43fa4 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 11 Aug 2015 18:04:50 -0700 Subject: QNetworkInterface: remove fallback code for Windows pre-XP and CE pre-4 All versions we support have support for the WinXP-style functions we need, so we don't need the Win2k fallback. Change-Id: I7de033f80b0e4431b7f1ffff13f99175a507a2ed Reviewed-by: Richard J. Moore --- src/network/kernel/qnetworkinterface_win.cpp | 56 ---------------------------- 1 file changed, 56 deletions(-) (limited to 'src') diff --git a/src/network/kernel/qnetworkinterface_win.cpp b/src/network/kernel/qnetworkinterface_win.cpp index eeb2e1665a..a07840a848 100644 --- a/src/network/kernel/qnetworkinterface_win.cpp +++ b/src/network/kernel/qnetworkinterface_win.cpp @@ -222,67 +222,11 @@ static QList interfaceListingWinXP() return interfaces; } -static QList interfaceListingWin2k() -{ - QList interfaces; - IP_ADAPTER_INFO staticBuf[2]; // 2 is arbitrary - PIP_ADAPTER_INFO pAdapter = staticBuf; - ULONG bufSize = sizeof staticBuf; - - DWORD retval = ptrGetAdaptersInfo(pAdapter, &bufSize); - if (retval == ERROR_BUFFER_OVERFLOW) { - // need more memory - pAdapter = (IP_ADAPTER_INFO *)malloc(bufSize); - if (!pAdapter) - return interfaces; - // try again - if (ptrGetAdaptersInfo(pAdapter, &bufSize) != ERROR_SUCCESS) { - free(pAdapter); - return interfaces; - } - } else if (retval != ERROR_SUCCESS) { - // error - return interfaces; - } - - // iterate over the list and add the entries to our listing - for (PIP_ADAPTER_INFO ptr = pAdapter; ptr; ptr = ptr->Next) { - QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate; - interfaces << iface; - - iface->index = ptr->Index; - iface->flags = QNetworkInterface::IsUp | QNetworkInterface::IsRunning; - if (ptr->Type == MIB_IF_TYPE_PPP) - iface->flags |= QNetworkInterface::IsPointToPoint; - else - iface->flags |= QNetworkInterface::CanBroadcast; - iface->name = QString::fromLocal8Bit(ptr->AdapterName); - iface->hardwareAddress = QNetworkInterfacePrivate::makeHwAddress(ptr->AddressLength, - ptr->Address); - - for (PIP_ADDR_STRING addr = &ptr->IpAddressList; addr; addr = addr->Next) { - QNetworkAddressEntry entry; - entry.setIp(QHostAddress(QLatin1String(addr->IpAddress.String))); - entry.setNetmask(QHostAddress(QLatin1String(addr->IpMask.String))); - // broadcast address is set on postProcess() - - iface->addressEntries << entry; - } - } - - if (pAdapter != staticBuf) - free(pAdapter); - - return interfaces; -} - static QList interfaceListing() { resolveLibs(); if (ptrGetAdaptersAddresses != NULL) return interfaceListingWinXP(); - else if (ptrGetAdaptersInfo != NULL) - return interfaceListingWin2k(); // failed return QList(); -- cgit v1.2.3 From dbcf5730ac2d4f61f872e50126d3ce73e3f6031e Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 13 Aug 2015 20:45:29 -0700 Subject: QHostAddress hashing: use qHashBits Instead of constructing a temporary QByteArray, which could conceivably fail, to hash those bits. Change-Id: I7de033f80b0e4431b7f1ffff13fa376302d9720f Reviewed-by: Richard J. Moore --- src/network/kernel/qhostaddress.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp index 5087576b44..6ee76a4250 100644 --- a/src/network/kernel/qhostaddress.cpp +++ b/src/network/kernel/qhostaddress.cpp @@ -1129,7 +1129,7 @@ uint qHash(const QHostAddress &key, uint seed) { // both lines might throw QT_ENSURE_PARSED(&key); - return qHash(QByteArray::fromRawData(reinterpret_cast(key.d->a6.c), 16), seed); + return qHashBits(key.d->a6.c, 16, seed); } #ifndef QT_NO_DATASTREAM -- cgit v1.2.3 From 507625d984f9467b056e603560d62a2e4a56074d Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Tue, 28 Jul 2015 13:43:54 +0200 Subject: fix assertion in QProcess/Win Do not call bytesAvailableInChannel if the source pipe end is invalid. This is the case when redirecting channels on Windows. The assertions in bytesAvailableInChannel were triggered whenever an output process or output file was set and waitForBytesWritten was called. Task-number: QTBUG-45548 Change-Id: I225dfea2c5e27e122f75008a3a06d425554e00fe Reviewed-by: Alex Trotsenko Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qprocess_win.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index cef961ecbd..eb88ded2c9 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -704,13 +704,15 @@ bool QProcessPrivate::waitForBytesWritten(int msecs) return true; // If we wouldn't write anything, check if we can read stdout. - if (bytesAvailableInChannel(&stdoutChannel) != 0) { + if (stdoutChannel.pipe[0] != INVALID_Q_PIPE + && bytesAvailableInChannel(&stdoutChannel) != 0) { tryReadFromChannel(&stdoutChannel); timer.resetIncrements(); } // Check if we can read stderr. - if (bytesAvailableInChannel(&stderrChannel) != 0) { + if (stderrChannel.pipe[0] != INVALID_Q_PIPE + && bytesAvailableInChannel(&stderrChannel) != 0) { tryReadFromChannel(&stderrChannel); timer.resetIncrements(); } -- cgit v1.2.3 From 0636ec4ff5d25845b4020358d0570afb92ce580c Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Wed, 10 Jun 2015 13:33:09 +0300 Subject: Open menu on the third click on QMenuBar on X11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't replay mouse events after closing popups on X11. This leads to the bug when the menu doesn't show after clicking three times on the menu bar. It can be fixed by reverting 78d7192338e2cbba0c9b53c429d35b9437b7e1cd, but then we need an alternative fix for QTBUG-32807 on Windows. So don't replay mouse events for the menu bar on all platforms. Change-Id: I3db8e24a6de6f35b0a17dffac6a131f1cad42e6d Reviewed-by: Shawn Rutledge Reviewed-by: Friedemann Kleint Reviewed-by: Jørgen Lind --- src/widgets/widgets/qmenubar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp index 1ad99bed9c..883fd3a945 100644 --- a/src/widgets/widgets/qmenubar.cpp +++ b/src/widgets/widgets/qmenubar.cpp @@ -1042,8 +1042,8 @@ void QMenuBar::mousePressEvent(QMouseEvent *e) if(d->currentAction == action && d->popupState) { if(QMenu *menu = d->activeMenu) { d->activeMenu = 0; + menu->setAttribute(Qt::WA_NoMouseReplay); menu->hide(); - d->closePopupMode = 1; } } else { d->setCurrentAction(action, true); -- cgit v1.2.3 From 08150122aaf0e1da706346497cf9767534a455b0 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 11 Aug 2015 15:09:47 +0200 Subject: Do not add GLSL line statements for old drivers Older VMware virtual machines do not like the #line statements. These were introduced in 5.5.0, meaning that when upgrading from 5.4 in such a VM, shader compilation via QOpenGLShaderProgram stops working. This should be avoided. Task-number: QTBUG-47598 Change-Id: I8cccd76119350e7ce40da96d24a7a6e9eb399052 Reviewed-by: Sean Harmer --- src/gui/opengl/qopenglshaderprogram.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/gui/opengl/qopenglshaderprogram.cpp b/src/gui/opengl/qopenglshaderprogram.cpp index 5de79c9e1e..04b796ddb0 100644 --- a/src/gui/opengl/qopenglshaderprogram.cpp +++ b/src/gui/opengl/qopenglshaderprogram.cpp @@ -525,7 +525,8 @@ bool QOpenGLShader::compileSourceCode(const char *source) // The precision qualifiers are useful on OpenGL/ES systems, // but usually not present on desktop systems. - const QSurfaceFormat currentSurfaceFormat = QOpenGLContext::currentContext()->format(); + QOpenGLContext *ctx = QOpenGLContext::currentContext(); + const QSurfaceFormat currentSurfaceFormat = ctx->format(); QOpenGLContextPrivate *ctx_d = QOpenGLContextPrivate::get(QOpenGLContext::currentContext()); if (currentSurfaceFormat.renderableType() == QSurfaceFormat::OpenGL || ctx_d->workaround_missingPrecisionQualifiers @@ -545,10 +546,16 @@ bool QOpenGLShader::compileSourceCode(const char *source) } #endif - // Append #line directive in order to compensate for text insertion - QByteArray lineDirective = QStringLiteral("#line %1\n").arg(versionDirectivePosition.line).toUtf8(); - sourceChunks.append(lineDirective.constData()); - sourceChunkLengths.append(GLint(lineDirective.length())); + QByteArray lineDirective; + // #line is rejected by some drivers: + // "2.1 Mesa 8.1-devel (git-48a3d4e)" or "MESA 2.1 Mesa 8.1-devel" + const char *version = reinterpret_cast(ctx->functions()->glGetString(GL_VERSION)); + if (!version || !strstr(version, "2.1 Mesa 8")) { + // Append #line directive in order to compensate for text insertion + lineDirective = QStringLiteral("#line %1\n").arg(versionDirectivePosition.line).toUtf8(); + sourceChunks.append(lineDirective.constData()); + sourceChunkLengths.append(GLint(lineDirective.length())); + } // Append rest of shader code sourceChunks.append(source + versionDirectivePosition.position); -- cgit v1.2.3 From be18d6fb01749184d40cdcd079e685d220ff8b80 Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Thu, 18 Sep 2014 16:16:26 +0400 Subject: Fix shortcuts with keypad keys The way of searching a shortcut match for a key without the keypad modifier introduced in 547a1bea492954d828aa0798be93384669812489 is not correct. QKeyEvent::setModifiers() doesn't change native scan code so we get the incorrect QKeyEvent object which is eventually passed to the implementation of QPlatformIntegration::possibleKeys(). And then QPlatformIntegration::possibleKeys() returns the same result as for the original QKeyEvent object. So to fix it we have to remove Qt::KeypadModifier from keys after calling the implementation of QPlatformIntegration::possibleKeys(), as it was before 547a1bea492954d828aa0798be93384669812489. Task-number: QTBUG-33093 Task-number: QTBUG-44577 Change-Id: I5b33c9b6cf2c06b133166a31eba9aff9181c9483 Reviewed-by: Gunnar Sletta --- src/gui/kernel/qshortcutmap.cpp | 12 +++++------- src/gui/kernel/qshortcutmap_p.h | 4 ++-- 2 files changed, 7 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qshortcutmap.cpp b/src/gui/kernel/qshortcutmap.cpp index 0ff5c36119..3e267f2e0b 100644 --- a/src/gui/kernel/qshortcutmap.cpp +++ b/src/gui/kernel/qshortcutmap.cpp @@ -386,9 +386,7 @@ QKeySequence::SequenceMatch QShortcutMap::nextState(QKeyEvent *e) result = find(e); if (result == QKeySequence::NoMatch && (e->modifiers() & Qt::KeypadModifier)) { // Try to find a match without keypad modifier - QKeyEvent event = *e; - event.setModifiers(e->modifiers() & ~Qt::KeypadModifier); - result = find(&event); + result = find(e, Qt::KeypadModifier); } if (result == QKeySequence::NoMatch && e->modifiers() & Qt::ShiftModifier) { // If Shift + Key_Backtab, also try Shift + Qt::Key_Tab @@ -441,13 +439,13 @@ bool QShortcutMap::hasShortcutForKeySequence(const QKeySequence &seq) const which can be access through matches(). \sa matches */ -QKeySequence::SequenceMatch QShortcutMap::find(QKeyEvent *e) +QKeySequence::SequenceMatch QShortcutMap::find(QKeyEvent *e, int ignoredModifiers) { Q_D(QShortcutMap); if (!d->sequences.count()) return QKeySequence::NoMatch; - createNewSequences(e, d->newEntries); + createNewSequences(e, d->newEntries, ignoredModifiers); #if defined(DEBUG_QSHORTCUTMAP) qDebug() << "Possible shortcut key sequences:" << d->newEntries; #endif @@ -549,7 +547,7 @@ void QShortcutMap::clearSequence(QVector &ksl) Alters \a seq to the new sequence state, based on the current sequence state, and the new key event \a e. */ -void QShortcutMap::createNewSequences(QKeyEvent *e, QVector &ksl) +void QShortcutMap::createNewSequences(QKeyEvent *e, QVector &ksl, int ignoredModifiers) { Q_D(QShortcutMap); QList possibleKeys = QKeyMapper::possibleKeys(e); @@ -579,7 +577,7 @@ void QShortcutMap::createNewSequences(QKeyEvent *e, QVector &ksl) curKsl.setKey(0, 2); curKsl.setKey(0, 3); } - curKsl.setKey(possibleKeys.at(pkNum), index); + curKsl.setKey(possibleKeys.at(pkNum) & ~ignoredModifiers, index); } } } diff --git a/src/gui/kernel/qshortcutmap_p.h b/src/gui/kernel/qshortcutmap_p.h index 242c021ca4..2376d27c78 100644 --- a/src/gui/kernel/qshortcutmap_p.h +++ b/src/gui/kernel/qshortcutmap_p.h @@ -88,10 +88,10 @@ private: QKeySequence::SequenceMatch state(); void dispatchEvent(QKeyEvent *e); - QKeySequence::SequenceMatch find(QKeyEvent *e); + QKeySequence::SequenceMatch find(QKeyEvent *e, int ignoredModifiers = 0); QKeySequence::SequenceMatch matches(const QKeySequence &seq1, const QKeySequence &seq2) const; QVector matches() const; - void createNewSequences(QKeyEvent *e, QVector &ksl); + void createNewSequences(QKeyEvent *e, QVector &ksl, int ignoredModifiers); void clearSequence(QVector &ksl); int translateModifiers(Qt::KeyboardModifiers modifiers); -- cgit v1.2.3 From 1fe890317a383e3729e496afff79a9ba58cc880a Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 17 Aug 2015 18:01:03 +0200 Subject: libinput: Rename logging category to prevent clashes Anything linking to platformsupport may use the same name so use something less generic. Change-Id: I657dd5dfcad9cf22585fcb17eda62deaf26ea6c4 Reviewed-by: Andy Nichols --- src/platformsupport/input/libinput/qlibinputhandler.cpp | 6 +++--- src/platformsupport/input/libinput/qlibinputkeyboard.cpp | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/platformsupport/input/libinput/qlibinputhandler.cpp b/src/platformsupport/input/libinput/qlibinputhandler.cpp index 1a64ad5a30..5aa66a4eaf 100644 --- a/src/platformsupport/input/libinput/qlibinputhandler.cpp +++ b/src/platformsupport/input/libinput/qlibinputhandler.cpp @@ -46,7 +46,7 @@ QT_BEGIN_NAMESPACE -Q_LOGGING_CATEGORY(qLcInput, "qt.qpa.input") +Q_LOGGING_CATEGORY(qLcLibInput, "qt.qpa.input") static int liOpen(const char *path, int flags, void *user_data) { @@ -75,7 +75,7 @@ static void liLogHandler(libinput *libinput, libinput_log_priority priority, con if (n > 0) { if (buf[n - 1] == '\n') buf[n - 1] = '\0'; - qCDebug(qLcInput, "libinput: %s", buf); + qCDebug(qLcLibInput, "libinput: %s", buf); } } @@ -93,7 +93,7 @@ QLibInputHandler::QLibInputHandler(const QString &key, const QString &spec) qFatal("Failed to get libinput context"); libinput_log_set_handler(m_li, liLogHandler); - if (qLcInput().isDebugEnabled()) + if (qLcLibInput().isDebugEnabled()) libinput_log_set_priority(m_li, LIBINPUT_LOG_PRIORITY_DEBUG); if (libinput_udev_assign_seat(m_li, "seat0")) diff --git a/src/platformsupport/input/libinput/qlibinputkeyboard.cpp b/src/platformsupport/input/libinput/qlibinputkeyboard.cpp index 5f1bc550b4..3bb9107e16 100644 --- a/src/platformsupport/input/libinput/qlibinputkeyboard.cpp +++ b/src/platformsupport/input/libinput/qlibinputkeyboard.cpp @@ -33,6 +33,7 @@ #include "qlibinputkeyboard_p.h" #include +#include #include #include #ifndef QT_NO_XKBCOMMON_EVDEV @@ -42,6 +43,8 @@ QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(qLcLibInput) + const int REPEAT_DELAY = 500; const int REPEAT_RATE = 100; @@ -128,6 +131,7 @@ QLibInputKeyboard::QLibInputKeyboard() #endif { #ifndef QT_NO_XKBCOMMON_EVDEV + qCDebug(qLcLibInput) << "Using xkbcommon for key mapping"; m_ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!m_ctx) { qWarning("Failed to create xkb context"); @@ -150,6 +154,8 @@ QLibInputKeyboard::QLibInputKeyboard() m_repeatTimer.setSingleShot(true); connect(&m_repeatTimer, &QTimer::timeout, this, &QLibInputKeyboard::handleRepeat); +#else + qCWarning(qLcLibInput) << "X-less xkbcommon not available, not performing key mapping"; #endif } -- cgit v1.2.3 From 95aad72e841b7d9bdef97a934c7fdfd65dc7122c Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 17 Aug 2015 18:04:34 +0200 Subject: eglfs: Use libinput by default when available Can be overridden by setting QT_QPA_EGLFS_NO_LIBINPUT. On systems where libinput is present it is usually a better choice to rely on it instead of evdev*. Change-Id: I78857ff91c837f58fdc7d1e119260bd6819fbf4e Reviewed-by: Andy Nichols --- src/plugins/platforms/eglfs/qeglfsintegration.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src') diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp index aec5a5e179..5f2cc9abbc 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -62,6 +63,10 @@ #include +#ifndef QT_NO_LIBINPUT +#include +#endif + #if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK)) #include #include @@ -389,6 +394,13 @@ void QEglFSIntegration::loadKeymapStatic(const QString &filename) void QEglFSIntegration::createInputHandlers() { +#ifndef QT_NO_LIBINPUT + if (!qEnvironmentVariableIntValue("QT_QPA_EGLFS_NO_LIBINPUT")) { + new QLibInputHandler(QLatin1String("libinput"), QString()); + return; + } +#endif + #if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK)) m_kbdMgr = new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString() /* spec */, this); new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString() /* spec */, this); -- cgit v1.2.3 From df80753134b714defe956ba87bc5077e32b1d63b Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 17 Aug 2015 18:27:35 +0200 Subject: linuxfb: Use libinput by default when available Can be overridden by setting QT_QPA_FB_NO_LIBINPUT. On systems where libinput is present it is usually a better choice to rely on it instead of evdev*. Change-Id: I8532c923bacd605434cfca1c7e314cb95d41b372 Reviewed-by: Andy Nichols --- src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src') diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp index ccf86dafb2..8c8c8a15ea 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp +++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp @@ -46,6 +46,10 @@ #include #include +#ifndef QT_NO_LIBINPUT +#include +#endif + #if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK)) #include #include @@ -130,6 +134,13 @@ QPlatformServices *QLinuxFbIntegration::services() const void QLinuxFbIntegration::createInputHandlers() { +#ifndef QT_NO_LIBINPUT + if (!qEnvironmentVariableIntValue("QT_QPA_FB_NO_LIBINPUT")) { + new QLibInputHandler(QLatin1String("libinput"), QString()); + return; + } +#endif + #if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK)) new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString(), this); new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString(), this); -- cgit v1.2.3 From fae725d45183f44fce93826df66e2f1ab2b6fa74 Mon Sep 17 00:00:00 2001 From: Joni Poikelin Date: Thu, 2 Jul 2015 13:28:29 +0300 Subject: Fix potential SIGFPEs in QRasterizer::rasterizeLine() Task-number: QTBUG-46985 Change-Id: If9897a6d4014dbcbc1f6cac1c6dd5dc648694b96 Reviewed-by: Gunnar Sletta --- src/gui/painting/qrasterizer.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/gui/painting/qrasterizer.cpp b/src/gui/painting/qrasterizer.cpp index 75bf31cde1..34d72bf493 100644 --- a/src/gui/painting/qrasterizer.cpp +++ b/src/gui/painting/qrasterizer.cpp @@ -863,8 +863,8 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width, const Q16Dot16 iLeft = int(left); const Q16Dot16 iRight = int(right); const Q16Dot16 leftWidth = IntToQ16Dot16(iLeft + 1) - - FloatToQ16Dot16(left); - const Q16Dot16 rightWidth = FloatToQ16Dot16(right) + - qSafeFloatToQ16Dot16(left); + const Q16Dot16 rightWidth = qSafeFloatToQ16Dot16(right) - IntToQ16Dot16(iRight); Q16Dot16 coverage[3]; @@ -898,8 +898,8 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width, const Q16Dot16 iTopFP = IntToQ16Dot16(int(pa.y())); const Q16Dot16 iBottomFP = IntToQ16Dot16(int(pb.y())); - const Q16Dot16 yPa = FloatToQ16Dot16(pa.y()); - const Q16Dot16 yPb = FloatToQ16Dot16(pb.y()); + const Q16Dot16 yPa = qSafeFloatToQ16Dot16(pa.y()); + const Q16Dot16 yPb = qSafeFloatToQ16Dot16(pb.y()); for (Q16Dot16 yFP = iTopFP; yFP <= iBottomFP; yFP += Q16Dot16Factor) { const Q16Dot16 rowHeight = qMin(yFP + Q16Dot16Factor, yPb) - qMax(yFP, yPa); @@ -983,16 +983,16 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width, const Q16Dot16 iRightFP = IntToQ16Dot16(int(right.y())); const Q16Dot16 iBottomFP = IntToQ16Dot16(int(bottomBound)); - Q16Dot16 leftIntersectAf = FloatToQ16Dot16(top.x() + (int(topBound) - top.y()) * topLeftSlope); - Q16Dot16 rightIntersectAf = FloatToQ16Dot16(top.x() + (int(topBound) - top.y()) * topRightSlope); + Q16Dot16 leftIntersectAf = qSafeFloatToQ16Dot16(top.x() + (int(topBound) - top.y()) * topLeftSlope); + Q16Dot16 rightIntersectAf = qSafeFloatToQ16Dot16(top.x() + (int(topBound) - top.y()) * topRightSlope); Q16Dot16 leftIntersectBf = 0; Q16Dot16 rightIntersectBf = 0; if (iLeftFP < iTopFP) - leftIntersectBf = FloatToQ16Dot16(left.x() + (int(topBound) - left.y()) * bottomLeftSlope); + leftIntersectBf = qSafeFloatToQ16Dot16(left.x() + (int(topBound) - left.y()) * bottomLeftSlope); if (iRightFP < iTopFP) - rightIntersectBf = FloatToQ16Dot16(right.x() + (int(topBound) - right.y()) * bottomRightSlope); + rightIntersectBf = qSafeFloatToQ16Dot16(right.x() + (int(topBound) - right.y()) * bottomRightSlope); Q16Dot16 rowTop, rowBottomLeft, rowBottomRight, rowTopLeft, rowTopRight, rowBottom; Q16Dot16 topLeftIntersectAf, topLeftIntersectBf, topRightIntersectAf, topRightIntersectBf; @@ -1000,10 +1000,10 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width, int leftMin, leftMax, rightMin, rightMax; - const Q16Dot16 yTopFP = FloatToQ16Dot16(top.y()); - const Q16Dot16 yLeftFP = FloatToQ16Dot16(left.y()); - const Q16Dot16 yRightFP = FloatToQ16Dot16(right.y()); - const Q16Dot16 yBottomFP = FloatToQ16Dot16(bottom.y()); + const Q16Dot16 yTopFP = qSafeFloatToQ16Dot16(top.y()); + const Q16Dot16 yLeftFP = qSafeFloatToQ16Dot16(left.y()); + const Q16Dot16 yRightFP = qSafeFloatToQ16Dot16(right.y()); + const Q16Dot16 yBottomFP = qSafeFloatToQ16Dot16(bottom.y()); rowTop = qMax(iTopFP, yTopFP); topLeftIntersectAf = leftIntersectAf + @@ -1021,7 +1021,7 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width, if (yFP == iLeftFP) { const int y = Q16Dot16ToInt(yFP); - leftIntersectBf = FloatToQ16Dot16(left.x() + (y - left.y()) * bottomLeftSlope); + leftIntersectBf = qSafeFloatToQ16Dot16(left.x() + (y - left.y()) * bottomLeftSlope); topLeftIntersectBf = leftIntersectBf + Q16Dot16Multiply(bottomLeftSlopeFP, rowTopLeft - yFP); bottomLeftIntersectAf = leftIntersectAf + Q16Dot16Multiply(topLeftSlopeFP, rowBottomLeft - yFP); } else { @@ -1031,7 +1031,7 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width, if (yFP == iRightFP) { const int y = Q16Dot16ToInt(yFP); - rightIntersectBf = FloatToQ16Dot16(right.x() + (y - right.y()) * bottomRightSlope); + rightIntersectBf = qSafeFloatToQ16Dot16(right.x() + (y - right.y()) * bottomRightSlope); topRightIntersectBf = rightIntersectBf + Q16Dot16Multiply(bottomRightSlopeFP, rowTopRight - yFP); bottomRightIntersectAf = rightIntersectAf + Q16Dot16Multiply(topRightSlopeFP, rowBottomRight - yFP); } else { -- cgit v1.2.3 From ba84e346b8a3eba6686fa18e1ef546def98073fa Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 17 Aug 2015 12:52:53 +0200 Subject: egl: Do not do any further ops when context creation fails Change-Id: I54bf4a720e8d414d310ecdb88f08a9705023aef9 Reviewed-by: Andy Nichols --- src/platformsupport/eglconvenience/qeglplatformcontext.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp index 6d9f9e4ae0..5bee29afef 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp @@ -240,7 +240,8 @@ void QEGLPlatformContext::adopt(const QVariant &nativeHandle, QPlatformOpenGLCon void QEGLPlatformContext::initialize() { - updateFormatFromGL(); + if (m_eglContext != EGL_NO_CONTEXT) + updateFormatFromGL(); } EGLSurface QEGLPlatformContext::createTemporaryOffscreenSurface() -- cgit v1.2.3 From 4dccb2ca674e9eafca65da0775254932102c7f4b Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 22 May 2015 09:39:52 +0200 Subject: Handle action events in QLineEditIconButton. Ensure QAction::setVisible() is handled and reposition if visibility changes. Task-number: QTBUG-39660 Change-Id: I14f0659aedc8dc89ddef3159d3a500b40b1563ff Reviewed-by: David Faure --- src/widgets/widgets/qlineedit_p.cpp | 24 ++++++++++++++++++++++-- src/widgets/widgets/qlineedit_p.h | 16 ++++++++++++++-- 2 files changed, 36 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp index 3f768bfbd3..6645a375a7 100644 --- a/src/widgets/widgets/qlineedit_p.cpp +++ b/src/widgets/widgets/qlineedit_p.cpp @@ -324,6 +324,24 @@ void QLineEditIconButton::paintEvent(QPaintEvent *) painter.drawPixmap(pixmapRect, iconPixmap); } +void QLineEditIconButton::actionEvent(QActionEvent *e) +{ + switch (e->type()) { + case QEvent::ActionChanged: { + const QAction *action = e->action(); + if (isVisible() != action->isVisible()) { + setVisible(action->isVisible()); + if (QLineEdit *le = qobject_cast(parentWidget())) + static_cast(qt_widget_private(le))->positionSideWidgets(); + } + } + break; + default: + break; + } + QToolButton::actionEvent(e); +} + void QLineEditIconButton::setOpacity(qreal value) { if (!qFuzzyCompare(m_opacity, value)) { @@ -415,12 +433,14 @@ void QLineEditPrivate::positionSideWidgets() QRect widgetGeometry(QPoint(QLineEditIconButton::IconMargin, (contentRect.height() - iconSize.height()) / 2), iconSize); foreach (const SideWidgetEntry &e, leftSideWidgetList()) { e.widget->setGeometry(widgetGeometry); - widgetGeometry.moveLeft(widgetGeometry.left() + delta); + if (e.widget->isVisible()) + widgetGeometry.moveLeft(widgetGeometry.left() + delta); } widgetGeometry.moveLeft(contentRect.width() - iconSize.width() - QLineEditIconButton::IconMargin); foreach (const SideWidgetEntry &e, rightSideWidgetList()) { e.widget->setGeometry(widgetGeometry); - widgetGeometry.moveLeft(widgetGeometry.left() - delta); + if (e.widget->isVisible()) + widgetGeometry.moveLeft(widgetGeometry.left() - delta); } } } diff --git a/src/widgets/widgets/qlineedit_p.h b/src/widgets/widgets/qlineedit_p.h index 4654262ea7..5a22285149 100644 --- a/src/widgets/widgets/qlineedit_p.h +++ b/src/widgets/widgets/qlineedit_p.h @@ -61,6 +61,8 @@ #include "private/qwidgetlinecontrol_p.h" +#include + QT_BEGIN_NAMESPACE // QLineEditIconButton: This is a simple helper class that represents clickable icons that fade in with text @@ -81,6 +83,7 @@ public: #endif protected: + void actionEvent(QActionEvent *e) Q_DECL_OVERRIDE; void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; private slots: @@ -226,14 +229,23 @@ private: mutable QSize m_iconSize; }; +static bool isSideWidgetVisible(const QLineEditPrivate::SideWidgetEntry &e) +{ + return e.widget->isVisible(); +} + inline int QLineEditPrivate::effectiveLeftTextMargin() const { - return leftTextMargin + leftSideWidgetList().size() * (QLineEditIconButton::IconMargin + iconSize().width()); + return leftTextMargin + (QLineEditIconButton::IconMargin + iconSize().width()) + * int(std::count_if(leftSideWidgetList().constBegin(), leftSideWidgetList().constEnd(), + isSideWidgetVisible)); } inline int QLineEditPrivate::effectiveRightTextMargin() const { - return rightTextMargin + rightSideWidgetList().size() * (QLineEditIconButton::IconMargin + iconSize().width()); + return rightTextMargin + (QLineEditIconButton::IconMargin + iconSize().width()) + * int(std::count_if(rightSideWidgetList().constBegin(), rightSideWidgetList().constEnd(), + isSideWidgetVisible)); } #endif // QT_NO_LINEEDIT -- cgit v1.2.3 From ee15bef3ea24a78e5fd4708c0a1cebee2e4fac5d Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Mon, 17 Aug 2015 11:28:16 +0200 Subject: QRegularExpression: fix matching over QStringRefs Playing with the offset argument of pcre_exec is not equivalent to adjusting the pointer to the subject string. In particular, PCRE can go behind the offset to check for lookbehinds or "transition" metacharacters (\b, \B, etc.). This made the code that deals with QStringRefs not matching in behavior with the corresponding code dealing with QStrings. For instance, QString subject("Miss"); QRegularExpression re("(?<=M)iss"); re.match(subject.mid(1)); // doesn't match re.match(subject.midRef(1)); // matches!!! Instead, actually adjust the pointer to the subject string so that the behavior is identical. A broken test that relied on the equivalence is also removed. Change-Id: If96333241ef59621d7f5a6a170ebd0a186844874 Reviewed-by: Volker Krause Reviewed-by: Thiago Macieira --- src/corelib/tools/qregularexpression.cpp | 45 +++++++++++++++----------------- 1 file changed, 21 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp index 2e3c2ca79f..070e68154f 100644 --- a/src/corelib/tools/qregularexpression.cpp +++ b/src/corelib/tools/qregularexpression.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2012 Giuseppe D'Angelo . -** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo +** Copyright (C) 2015 Giuseppe D'Angelo . +** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** @@ -1325,48 +1325,45 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString int * const captureOffsets = priv->capturedOffsets.data(); const int captureOffsetsCount = priv->capturedOffsets.size(); - int realOffset = offset + subjectStart; - const int realSubjectLength = subjectLength + subjectStart; - - const unsigned short * const subjectUtf16 = subject.utf16(); + const unsigned short * const subjectUtf16 = subject.utf16() + subjectStart; int result; if (!previousMatchWasEmpty) { result = pcre16SafeExec(compiledPattern, currentStudyData, - subjectUtf16, realSubjectLength, - realOffset, pcreOptions, + subjectUtf16, subjectLength, + offset, pcreOptions, captureOffsets, captureOffsetsCount); } else { result = pcre16SafeExec(compiledPattern, currentStudyData, - subjectUtf16, realSubjectLength, - realOffset, pcreOptions | PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED, + subjectUtf16, subjectLength, + offset, pcreOptions | PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED, captureOffsets, captureOffsetsCount); if (result == PCRE_ERROR_NOMATCH) { - ++realOffset; + ++offset; if (usingCrLfNewlines - && realOffset < realSubjectLength - && subjectUtf16[realOffset - 1] == QLatin1Char('\r') - && subjectUtf16[realOffset] == QLatin1Char('\n')) { - ++realOffset; - } else if (realOffset < realSubjectLength - && QChar::isLowSurrogate(subjectUtf16[realOffset])) { - ++realOffset; + && offset < subjectLength + && subjectUtf16[offset - 1] == QLatin1Char('\r') + && subjectUtf16[offset] == QLatin1Char('\n')) { + ++offset; + } else if (offset < subjectLength + && QChar::isLowSurrogate(subjectUtf16[offset])) { + ++offset; } result = pcre16SafeExec(compiledPattern, currentStudyData, - subjectUtf16, realSubjectLength, - realOffset, pcreOptions, + subjectUtf16, subjectLength, + offset, pcreOptions, captureOffsets, captureOffsetsCount); } } #ifdef QREGULAREXPRESSION_DEBUG qDebug() << "Matching" << pattern << "against" << subject - << "starting at" << subjectStart << "len" << subjectLength << "real len" << realSubjectLength - << "offset" << offset << "real offset" << realOffset + << "starting at" << subjectStart << "len" << subjectLength + << "offset" << offset << matchType << matchOptions << previousMatchWasEmpty << "result" << result; #endif @@ -2041,7 +2038,7 @@ QString QRegularExpressionMatch::captured(int nth) const if (start == -1) // didn't capture return QString(); - return d->subject.mid(start, capturedLength(nth)); + return d->subject.mid(start + d->subjectStart, capturedLength(nth)); } /*! @@ -2062,7 +2059,7 @@ QStringRef QRegularExpressionMatch::capturedRef(int nth) const if (start == -1) // didn't capture return QStringRef(); - return d->subject.midRef(start, capturedLength(nth)); + return d->subject.midRef(start + d->subjectStart, capturedLength(nth)); } /*! -- cgit v1.2.3 From 6a57a260fc1ce8250fef4ed6e0242ac933c7ee56 Mon Sep 17 00:00:00 2001 From: Julien Brianceau Date: Tue, 18 Aug 2015 10:48:26 +0200 Subject: Doc: remove type() reference from QApplication and QGuiApplication QApplication::type() is gone since Qt 5.0. Task-number: QTBUG-28093 Change-Id: I8700c69a42271e8b99f3e86a5014c8abf7711f53 Reviewed-by: Friedemann Kleint --- src/gui/kernel/qguiapplication.cpp | 3 +-- src/widgets/kernel/qapplication.cpp | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 654567e7df..7dc8444163 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -449,8 +449,7 @@ static QWindowGeometrySpecification windowGeometrySpecification; \row \li Miscellaneous \li startingUp(), - closingDown(), - type(). + closingDown(). \endtable \sa QCoreApplication, QAbstractEventDispatcher, QEventLoop diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index b9fd6312e7..647484ece1 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -339,8 +339,7 @@ void QApplicationPrivate::createEventDispatcher() \li Miscellaneous \li closeAllWindows(), startingUp(), - closingDown(), - type(). + closingDown(). \endtable \sa QCoreApplication, QAbstractEventDispatcher, QEventLoop, QSettings -- cgit v1.2.3 From e50629cc0db628efdea6c654a87fe0e7acbad596 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 31 Jul 2015 15:52:11 +0200 Subject: qthread_win.cpp: Fix compiler warnings by MSVC2015 (64bit). thread\qthread_win.cpp(121): warning C4312: 'reinterpret_cast': conversion from 'DWORD' to 'Qt::HANDLE' of greater size thread\qthread_win.cpp(343): warning C4312: 'reinterpret_cast': conversion from 'DWORD' to 'Qt::HANDLE' of greater size thread\qthread_win.cpp(416): warning C4312: 'reinterpret_cast': conversion from 'DWORD' to 'Qt::HANDLE' of greater size Change-Id: I5e60e4bb91a32491562748755d34a2c5a1e264b4 Reviewed-by: Joerg Bornemann --- src/corelib/thread/qthread_win.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index c16a2e958c..57eeb10b7d 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -118,7 +118,7 @@ QThreadData *QThreadData::current(bool createIfNecessary) } threadData->deref(); threadData->isAdopted = true; - threadData->threadId = reinterpret_cast(GetCurrentThreadId()); + threadData->threadId = reinterpret_cast(quintptr(GetCurrentThreadId())); if (!QCoreApplicationPrivate::theMainThread) { QCoreApplicationPrivate::theMainThread = threadData->thread; @@ -340,7 +340,7 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi qt_create_tls(); TlsSetValue(qt_current_thread_data_tls_index, data); - data->threadId = reinterpret_cast(GetCurrentThreadId()); + data->threadId = reinterpret_cast(quintptr(GetCurrentThreadId())); QThread::setTerminationEnabled(false); @@ -413,7 +413,7 @@ void QThreadPrivate::finish(void *arg, bool lockAnyway) Qt::HANDLE QThread::currentThreadId() Q_DECL_NOTHROW { - return reinterpret_cast(GetCurrentThreadId()); + return reinterpret_cast(quintptr(GetCurrentThreadId())); } int QThread::idealThreadCount() Q_DECL_NOTHROW -- cgit v1.2.3 From b479d5befbf6f6ed1bffef0dbccecf504263e1d6 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sun, 16 Aug 2015 00:03:30 +0200 Subject: Disable the testlib watchdog if a debugger is present Currently this is only implemented on Linux and Windows. But it's an improvement nevertheless when debugging Qt unit tests :) Change-Id: Iea307dad0e12c24f305c16f0a1805e7c246ee372 Reviewed-by: Friedemann Kleint Reviewed-by: Oliver Wolff Reviewed-by: Lars Knoll --- src/testlib/qtestcase.cpp | 46 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index ae83432eb8..1a74bab538 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -76,6 +76,7 @@ #if defined(Q_OS_LINUX) #include #include +#include #endif #ifdef Q_OS_WIN @@ -2213,9 +2214,11 @@ static bool qInvokeTestMethod(const char *slotName, const char *data, WatchDog * QTestDataSetter s(curDataIndex >= dataCount ? static_cast(0) : table.testData(curDataIndex)); - watchDog->beginTest(); + if (watchDog) + watchDog->beginTest(); qInvokeTestMethodDataEntry(slot); - watchDog->testFinished(); + if (watchDog) + watchDog->testFinished(); if (data) break; @@ -2487,6 +2490,37 @@ char *toPrettyUnicode(const ushort *p, int length) return buffer.take(); } +static bool debuggerPresent() +{ +#if defined(Q_OS_LINUX) + int fd = open("/proc/self/status", O_RDONLY); + if (fd == -1) + return false; + char buffer[2048]; + ssize_t size = read(fd, buffer, sizeof(buffer)); + if (size == -1) { + close(fd); + return false; + } + buffer[size] = 0; + const char tracerPidToken[] = "TracerPid:"; + char *tracerPid = strstr(buffer, tracerPidToken); + if (!tracerPid) { + close(fd); + return false; + } + tracerPid += sizeof(tracerPidToken); + long int pid = strtol(tracerPid, &tracerPid, 10); + close(fd); + return pid != 0; +#elif defined(Q_OS_WIN) + return IsDebuggerPresent(); +#else + // TODO + return false; +#endif +} + static void qInvokeTestMethods(QObject *testObject) { const QMetaObject *metaObject = testObject->metaObject(); @@ -2496,7 +2530,9 @@ static void qInvokeTestMethods(QObject *testObject) QTestTable::globalTestTable(); invokeMethod(testObject, "initTestCase_data()"); - WatchDog watchDog; + QScopedPointer watchDog; + if (!debuggerPresent()) + watchDog.reset(new WatchDog); if (!QTestResult::skipCurrentTest() && !QTest::currentTestFailed()) { invokeMethod(testObject, "initTestCase()"); @@ -2512,7 +2548,7 @@ static void qInvokeTestMethods(QObject *testObject) if (QTest::testFuncs) { for (int i = 0; i != QTest::testFuncCount; i++) { if (!qInvokeTestMethod(metaObject->method(QTest::testFuncs[i].function()).methodSignature().constData(), - QTest::testFuncs[i].data(), &watchDog)) { + QTest::testFuncs[i].data(), watchDog.data())) { break; } } @@ -2525,7 +2561,7 @@ static void qInvokeTestMethods(QObject *testObject) for (int i = 0; i != methodCount; i++) { if (!isValidSlot(testMethods[i])) continue; - if (!qInvokeTestMethod(testMethods[i].methodSignature().constData(), 0, &watchDog)) + if (!qInvokeTestMethod(testMethods[i].methodSignature().constData(), 0, watchDog.data())) break; } delete[] testMethods; -- cgit v1.2.3 From dd92002416270c56c795cce81fb9f0e55c1b2ddd Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 10 Aug 2015 13:08:15 -0700 Subject: QHostAddress: Improve code generation Mostly related to IPv6, because Q_IPV6ADDR is an array of char, so the compilers were generating byte access to each value. Instead, force access as 32- and 64-bit in most places that make sense (64-bit access decays to 32-bit on 32-bit machines). In one isLoopback(), this is now a 128-bit access for best improvement. Some smaller improvements relating to SpecialAddress by combining the three IPv4 special addresses. Change-Id: I7de033f80b0e4431b7f1ffff13f932b1cd7b5d21 Reviewed-by: Richard J. Moore --- src/network/kernel/qhostaddress.cpp | 99 +++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp index 6ee76a4250..935af04e31 100644 --- a/src/network/kernel/qhostaddress.cpp +++ b/src/network/kernel/qhostaddress.cpp @@ -46,6 +46,9 @@ #ifndef QT_NO_DATASTREAM #include #endif +#ifdef __SSE2__ +# include +#endif #ifdef QT_LINUXBASE # include @@ -106,7 +109,11 @@ public: QString scopeId; quint32 a; // IPv4 address - Q_IPV6ADDR a6; // IPv6 address + union { + Q_IPV6ADDR a6; // IPv6 address + struct { quint64 c[2]; } a6_64; + struct { quint32 c[4]; } a6_32; + }; QAbstractSocket::NetworkLayerProtocol protocol; bool isParsed; @@ -123,24 +130,17 @@ QHostAddressPrivate::QHostAddressPrivate() void QHostAddressPrivate::setAddress(quint32 a_) { a = a_; + protocol = QAbstractSocket::IPv4Protocol; + isParsed = true; + //create mapped address, except for a_ == 0 (any) - memset(&a6, 0, sizeof(a6)); + a6_64.c[0] = 0; if (a) { - a6[11] = 0xFF; - a6[10] = 0xFF; + a6_32.c[2] = qToBigEndian(0xffff); + a6_32.c[3] = qToBigEndian(a); } else { - a6[11] = 0; - a6[10] = 0; + a6_64.c[1] = 0; } - - int i; - for (i=15; a_ != 0; i--) { - a6[i] = a_ & 0xFF; - a_ >>=8; - } - Q_ASSERT(i >= 11); - protocol = QAbstractSocket::IPv4Protocol; - isParsed = true; } /// parses v4-mapped addresses or the AnyIPv6 address and stores in \a a; @@ -163,21 +163,16 @@ static bool convertToIpv4(quint32& a, const Q_IPV6ADDR &a6) void QHostAddressPrivate::setAddress(const quint8 *a_) { - for (int i = 0; i < 16; i++) - a6[i] = a_[i]; - a = 0; - convertToIpv4(a, a6); protocol = QAbstractSocket::IPv6Protocol; isParsed = true; + memcpy(a6.c, a_, sizeof(a6)); + a = 0; + convertToIpv4(a, a6); } void QHostAddressPrivate::setAddress(const Q_IPV6ADDR &a_) { - a6 = a_; - a = 0; - convertToIpv4(a, a6); - protocol = QAbstractSocket::IPv6Protocol; - isParsed = true; + setAddress(a_.c); } static bool parseIp6(const QString &address, QIPAddressUtils::IPv6Address &addr, QString *scopeId) @@ -486,31 +481,35 @@ QHostAddress::QHostAddress(SpecialAddress address) { Q_IPV6ADDR ip6; memset(&ip6, 0, sizeof ip6); + quint32 ip4 = INADDR_ANY; switch (address) { case Null: - break; + return; + case Broadcast: - d->setAddress(quint32(-1)); + ip4 = INADDR_BROADCAST; break; case LocalHost: - d->setAddress(0x7f000001); - break; - case LocalHostIPv6: - ip6[15] = 1; - d->setAddress(ip6); + ip4 = INADDR_LOOPBACK; break; case AnyIPv4: - setAddress(0u); break; + + case LocalHostIPv6: + ip6[15] = 1; + // fall through case AnyIPv6: d->setAddress(ip6); - break; + return; + case Any: - d->clear(); d->protocol = QAbstractSocket::AnyIPProtocol; - break; + return; } + + // common IPv4 part + d->setAddress(ip4); } /*! @@ -837,34 +836,36 @@ bool QHostAddress::operator==(const QHostAddress &other) const bool QHostAddress::operator ==(SpecialAddress other) const { QT_ENSURE_PARSED(this); + quint32 ip4 = INADDR_ANY; switch (other) { case Null: return d->protocol == QAbstractSocket::UnknownNetworkLayerProtocol; case Broadcast: - return d->protocol == QAbstractSocket::IPv4Protocol && d->a == INADDR_BROADCAST; + ip4 = INADDR_BROADCAST; + break; case LocalHost: - return d->protocol == QAbstractSocket::IPv4Protocol && d->a == INADDR_LOOPBACK; + ip4 = INADDR_LOOPBACK; + break; case Any: return d->protocol == QAbstractSocket::AnyIPProtocol; case AnyIPv4: - return d->protocol == QAbstractSocket::IPv4Protocol && d->a == INADDR_ANY; + break; case LocalHostIPv6: case AnyIPv6: if (d->protocol == QAbstractSocket::IPv6Protocol) { - Q_IPV6ADDR ip6 = { { 0 } }; - ip6[15] = quint8(other == LocalHostIPv6); // 1 for localhost, 0 for any - return memcmp(&d->a6, &ip6, sizeof ip6) == 0; + quint64 second = quint8(other == LocalHostIPv6); // 1 for localhost, 0 for any + return d->a6_64.c[0] == 0 && d->a6_64.c[1] == qToBigEndian(second); } return false; } - Q_UNREACHABLE(); - return false; + // common IPv4 part + return d->protocol == QAbstractSocket::IPv4Protocol && d->a == ip4; } /*! @@ -1086,11 +1087,15 @@ bool QHostAddress::isLoopback() const if ((d->a & 0xFF000000) == 0x7F000000) return true; // v4 range (including IPv6 wrapped IPv4 addresses) if (d->protocol == QAbstractSocket::IPv6Protocol) { - if (d->a6.c[15] != 1) +#ifdef __SSE2__ + const __m128i loopback = _mm_setr_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); + __m128i ipv6 = _mm_loadu_si128((const __m128i *)d->a6.c); + __m128i cmp = _mm_cmpeq_epi8(ipv6, loopback); + return _mm_movemask_epi8(cmp) == 0xffff; +#else + if (d->a6_64.c[0] != 0 || qFromBigEndian(d->a6_64.c[1]) != 1) return false; - for (int i = 0; i < 15; i++) - if (d->a6[i] != 0) - return false; +#endif return true; } return false; -- cgit v1.2.3 From 53762b102bc656c1f9b294b164f9b494a6d78da7 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 19 Aug 2015 08:59:59 +0200 Subject: Exclude ANGLE from translations. Fix lupdate warning: qtbase/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp:20: Ignoring definition of undeclared qualified class Change-Id: Ica6b560ce7f80319f4fc9d550f91d6baf61a8241 Reviewed-by: Andrew Knight --- src/angle/src/common/common.pri | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/angle/src/common/common.pri b/src/angle/src/common/common.pri index 735c841ad8..57f92f1089 100644 --- a/src/angle/src/common/common.pri +++ b/src/angle/src/common/common.pri @@ -7,6 +7,8 @@ INCLUDEPATH += \ LIBS_PRIVATE = $$QMAKE_LIBS_CORE $$QMAKE_LIBS_GUI +TR_EXCLUDE += $$ANGLE_DIR/src/* + lib_replace.match = $$[QT_INSTALL_LIBS/get] lib_replace.replace = \$\$\$\$[QT_INSTALL_LIBS] lib_replace.CONFIG = path -- cgit v1.2.3 From d558100aa71f714342526c072005ad3bcef88d0f Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Wed, 12 Aug 2015 11:00:19 +0200 Subject: qdoc: Improve resolving related non-members and their overload numbers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There were several problems related to resolving related non-member (RNM) functions for classes. This commit does the following changes: - Overload numbers for RNMs are now calculated at the time the \relates command is processed, instead of a separate step. - If a \relates refers to an entity outside the module boundary, write the argument passed to it as-is into the index file. - Delay the destruction of QDocIndexFiles singleton, to resolve the RNMs read from the index files prior to generating docs. - Remove the redundant call to normalizeOverloads() for single- exec mode as unnecessary. These changes ensure that all RNMs are listed in the documentation for the node that they belong to. A remaining issue is that if a function relates to a class outside the module boundary, that function documentation will be empty because the doc content is not stored into the index file (for obvious reasons). Single-exec mode does not have this problem. Change-Id: I33f038120728932cd9fd70da28d9090023068bd6 Task-number: QTBUG-47589 Reviewed-by: Topi Reiniö --- src/tools/qdoc/cppcodeparser.cpp | 10 ++++- src/tools/qdoc/node.cpp | 94 +++++++++++++++++++++++++++++---------- src/tools/qdoc/node.h | 3 ++ src/tools/qdoc/qdocdatabase.cpp | 6 ++- src/tools/qdoc/qdocindexfiles.cpp | 31 ++++++++++--- src/tools/qdoc/qdocindexfiles.h | 1 + 6 files changed, 112 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/tools/qdoc/cppcodeparser.cpp b/src/tools/qdoc/cppcodeparser.cpp index 0f70777256..46a62d629f 100644 --- a/src/tools/qdoc/cppcodeparser.cpp +++ b/src/tools/qdoc/cppcodeparser.cpp @@ -924,8 +924,14 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc, else if (command == COMMAND_RELATES) { QStringList path = arg.split("::"); Node* n = qdb_->findRelatesNode(path); - if (!n) - doc.location().warning(tr("Cannot find '%1' in '\\%2'").arg(arg).arg(COMMAND_RELATES)); + if (!n) { + // Store just a string to write to the index file + if (Generator::preparing()) + node->setRelates(arg); + else + doc.location().warning(tr("Cannot find '%1' in '\\%2'").arg(arg).arg(COMMAND_RELATES)); + + } else node->setRelates(static_cast(n)); } diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp index c803acbf60..c879d1d9b4 100644 --- a/src/tools/qdoc/node.cpp +++ b/src/tools/qdoc/node.cpp @@ -106,7 +106,24 @@ Node::~Node() { if (parent_) parent_->removeChild(this); + if (relatesTo_) + removeRelates(); +} + +/*! + Removes this node from the aggregate's list of related + nodes, or if this node has created a dummy "relates" + aggregate, deletes it. +*/ +void Node::removeRelates() +{ + if (!relatesTo_) + return; + + if (relatesTo_->isDocumentNode() && !relatesTo_->parent()) + delete relatesTo_; + else relatesTo_->removeRelated(this); } @@ -463,11 +480,19 @@ bool Node::fromFlagValue(FlagValue fv, bool defaultValue) */ void Node::setRelates(Aggregate *pseudoParent) { - if (relatesTo_) { - relatesTo_->removeRelated(this); - } + removeRelates(); relatesTo_ = pseudoParent; - pseudoParent->related_.append(this); + pseudoParent->addRelated(this); +} + +/*! + Sets the (unresolved) entity \a name that this node relates to. + */ +void Node::setRelates(const QString& name) +{ + removeRelates(); + // Create a dummy aggregate for writing the name into the index + relatesTo_ = new DocumentNode(0, name, Node::NoSubtype, Node::NoPageType); } /*! @@ -934,8 +959,9 @@ void Aggregate::makeUndocumentedChildrenInternal() } /*! - This is where we should set the overload numbers, including - the related non-members. + This is where we set the overload numbers for function nodes. + \note Overload numbers for related non-members are handled + separately. */ void Aggregate::normalizeOverloads() { @@ -1006,23 +1032,6 @@ void Aggregate::normalizeOverloads() } ++p; } - /* - Add the related non-members here. - */ - if (!related_.isEmpty()) { - foreach (Node* n, related_) { - if (n->isFunction()) { - FunctionNode* fn = static_cast(n); - QMap::Iterator p = primaryFunctionMap_.find(fn->name()); - if (p != primaryFunctionMap_.end()) { - secondaryFunctionMap_[fn->name()].append(fn); - fn->setOverloadNumber(secondaryFunctionMap_[fn->name()].size()); - } - else - fn->setOverloadNumber(0); - } - } - } /* Recursive part. */ @@ -1322,10 +1331,49 @@ QString Node::physicalModuleName() const } /*! + Removes a node from the list of nodes related to this one. + If it is a function node, also remove from the primary/ + secondary function maps. */ void Aggregate::removeRelated(Node *pseudoChild) { related_.removeAll(pseudoChild); + + if (pseudoChild->isFunction()) { + QMap::Iterator p = primaryFunctionMap_.find(pseudoChild->name()); + while (p != primaryFunctionMap_.end()) { + if (p.value() == pseudoChild) { + primaryFunctionMap_.erase(p); + break; + } + ++p; + } + NodeList& overloads = secondaryFunctionMap_[pseudoChild->name()]; + overloads.removeAll(pseudoChild); + } +} + +/*! + Adds \a pseudoChild to the list of nodes related to this one. Resolve a correct + overload number for a related non-member function. + */ +void Aggregate::addRelated(Node *pseudoChild) +{ + related_.append(pseudoChild); + + if (pseudoChild->isFunction()) { + FunctionNode* fn = static_cast(pseudoChild); + if (primaryFunctionMap_.contains(pseudoChild->name())) { + secondaryFunctionMap_[pseudoChild->name()].append(pseudoChild); + fn->setOverloadNumber(secondaryFunctionMap_[pseudoChild->name()].size()); + fn->setOverloadFlag(true); + } + else { + primaryFunctionMap_.insert(pseudoChild->name(), pseudoChild); + fn->setOverloadNumber(0); + fn->setOverloadFlag(false); + } + } } /*! diff --git a/src/tools/qdoc/node.h b/src/tools/qdoc/node.h index 596a71b6d5..6262cee0ab 100644 --- a/src/tools/qdoc/node.h +++ b/src/tools/qdoc/node.h @@ -178,6 +178,7 @@ public: void setThreadSafeness(ThreadSafeness t) { safeness_ = (unsigned char) t; } void setSince(const QString &since); void setRelates(Aggregate* pseudoParent); + void setRelates(const QString &name); void setPhysicalModuleName(const QString &name) { physicalModuleName_ = name; } void setUrl(const QString& url) { url_ = url; } void setTemplateStuff(const QString &t) { templateStuff_ = t; } @@ -336,6 +337,7 @@ public: protected: Node(NodeType type, Aggregate* parent, const QString& name); + void removeRelates(); private: @@ -421,6 +423,7 @@ private: static bool isSameSignature(const FunctionNode* f1, const FunctionNode* f2); void removeRelated(Node* pseudoChild); + void addRelated(Node* pseudoChild); QString outputFileName_; QStringList pageKeywds; diff --git a/src/tools/qdoc/qdocdatabase.cpp b/src/tools/qdoc/qdocdatabase.cpp index 7f2e64b00c..97f1929fb4 100644 --- a/src/tools/qdoc/qdocdatabase.cpp +++ b/src/tools/qdoc/qdocdatabase.cpp @@ -1295,6 +1295,10 @@ void QDocDatabase::resolveIssues() { resolveQmlInheritance(primaryTreeRoot()); primaryTree()->resolveTargets(primaryTreeRoot()); primaryTree()->resolveCppToQmlLinks(); + if (!Generator::singleExec()) { + QDocIndexFiles::qdocIndexFiles()->resolveRelates(); + QDocIndexFiles::destroyQDocIndexFiles(); + } } void QDocDatabase::resolveStuff() @@ -1305,7 +1309,6 @@ void QDocDatabase::resolveStuff() primaryTree()->resolveCppToQmlLinks(); primaryTree()->resolveUsingClauses(); resolveNamespaces(); - primaryTreeRoot()->normalizeOverloads(); } /*! @@ -1495,7 +1498,6 @@ void QDocDatabase::readIndexes(const QStringList& t) qDebug() << "This index file is already in memory:" << f; } QDocIndexFiles::qdocIndexFiles()->readIndexes(indexFiles); - QDocIndexFiles::destroyQDocIndexFiles(); } /*! diff --git a/src/tools/qdoc/qdocindexfiles.cpp b/src/tools/qdoc/qdocindexfiles.cpp index 8db901bbc7..fc262d9834 100644 --- a/src/tools/qdoc/qdocindexfiles.cpp +++ b/src/tools/qdoc/qdocindexfiles.cpp @@ -100,6 +100,7 @@ void QDocIndexFiles::destroyQDocIndexFiles() */ void QDocIndexFiles::readIndexes(const QStringList& indexFiles) { + relatedList_.clear(); foreach (const QString& indexFile, indexFiles) { QString msg = "Loading index file: " + indexFile; Location::logToStdErr(msg); @@ -146,9 +147,7 @@ void QDocIndexFiles::readIndexFile(const QString& path) indexUrl = installDir.relativeFilePath(path).section('/', 0, -2); } project_ = attrs.value(QLatin1String("project")).toString(); - basesList_.clear(); - relatedList_.clear(); NamespaceNode* root = qdb_->newIndexTree(project_); @@ -730,17 +729,37 @@ void QDocIndexFiles::resolveIndex() pair.first->addUnresolvedBaseClass(Node::Public, basePath, QString()); } } + // No longer needed. + basesList_.clear(); +} + +/* + Goes though the list of nodes that are related to other aggregates + that were read from all index files, and tries to find the aggregate + nodes from the database. Calls the node's setRelates() for each + aggregate that is found in the local module (primary tree). + + This function is meant to be called before starting the doc generation, + after all the index files are read. + */ +void QDocIndexFiles::resolveRelates() +{ + if (relatedList_.isEmpty()) + return; + + // Restrict searching only to the local (primary) tree + QVector searchOrder = qdb_->searchOrder(); + qdb_->setLocalSearch(); QPair relatedPair; foreach (relatedPair, relatedList_) { QStringList path = relatedPair.second.split("::"); Node* n = qdb_->findRelatesNode(path); if (n) - relatedPair.first->setRelates(static_cast(n)); + relatedPair.first->setRelates(static_cast(n)); } - - // No longer needed. - basesList_.clear(); + // Restore original search order + qdb_->setSearchOrder(searchOrder); relatedList_.clear(); } diff --git a/src/tools/qdoc/qdocindexfiles.h b/src/tools/qdoc/qdocindexfiles.h index 1b9b6afc40..67a7e7226e 100644 --- a/src/tools/qdoc/qdocindexfiles.h +++ b/src/tools/qdoc/qdocindexfiles.h @@ -65,6 +65,7 @@ class QDocIndexFiles void readIndexFile(const QString& path); void readIndexSection(QXmlStreamReader &reader, Node* current, const QString& indexUrl); void resolveIndex(); + void resolveRelates(); bool generateIndexSection(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false); void generateIndexSections(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false); -- cgit v1.2.3 From 2473f4fac31fae8b40be0975fbf41b115333bda8 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Wed, 19 Aug 2015 13:18:39 +0200 Subject: qdoc: Check and warn if \relates is used incorrectly There are instances in the documentation where a member function tries to set itself also a related non-member of its parent. This should be treated as invalid behavior, as it likely causes also problems during deletion of the node tree. QDoc now checks for and warns about these instances. Change-Id: I951e0de6be4d48618c60b8a0382e2c70700cc402 Task-number: QTBUG-47751 Reviewed-by: Martin Smith --- src/tools/qdoc/cppcodeparser.cpp | 5 ++++- src/tools/qdoc/node.cpp | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/tools/qdoc/cppcodeparser.cpp b/src/tools/qdoc/cppcodeparser.cpp index 46a62d629f..5d2a2c90d0 100644 --- a/src/tools/qdoc/cppcodeparser.cpp +++ b/src/tools/qdoc/cppcodeparser.cpp @@ -932,8 +932,11 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc, doc.location().warning(tr("Cannot find '%1' in '\\%2'").arg(arg).arg(COMMAND_RELATES)); } - else + else if (node->parent() != n) node->setRelates(static_cast(n)); + else + doc.location().warning(tr("Invalid use of '\\%1' (already a member of '%2')") + .arg(COMMAND_RELATES, arg)); } else if (command == COMMAND_CONTENTSPAGE) { setLink(node, Node::ContentsLink, arg); diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp index c879d1d9b4..1fe0af352d 100644 --- a/src/tools/qdoc/node.cpp +++ b/src/tools/qdoc/node.cpp @@ -480,6 +480,9 @@ bool Node::fromFlagValue(FlagValue fv, bool defaultValue) */ void Node::setRelates(Aggregate *pseudoParent) { + if (pseudoParent == parent()) + return; + removeRelates(); relatesTo_ = pseudoParent; pseudoParent->addRelated(this); -- cgit v1.2.3 From e525d1f44d2678f0360a0ee6c9ce2c9cb44f52a2 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Wed, 19 Aug 2015 13:24:59 +0200 Subject: Doc: Remove invalid uses of \relates command A function cannot be both a member and a non-member of the same class. Change-Id: I07d1e04c09fea2ba1171b3692e716660044cd37a Reviewed-by: Martin Smith --- src/corelib/io/qabstractfileengine.cpp | 1 - src/corelib/tools/qrect.cpp | 4 ---- src/corelib/tools/qstring.cpp | 4 ++-- src/corelib/tools/qtimezone.cpp | 1 - src/gui/accessible/qaccessible.cpp | 1 - 5 files changed, 2 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp index 07270eb790..2ab789e0af 100644 --- a/src/corelib/io/qabstractfileengine.cpp +++ b/src/corelib/io/qabstractfileengine.cpp @@ -891,7 +891,6 @@ bool QAbstractFileEngine::unmap(uchar *address) /*! \typedef QAbstractFileEngine::Iterator \since 4.3 - \relates QAbstractFileEngine Synonym for QAbstractFileEngineIterator. */ diff --git a/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp index b2174745e4..847f650a70 100644 --- a/src/corelib/tools/qrect.cpp +++ b/src/corelib/tools/qrect.cpp @@ -2403,7 +2403,6 @@ QRect QRectF::toAlignedRect() const Q_DECL_NOTHROW /*! \fn QRectF QRectF::marginsAdded(const QMarginsF &margins) const - \relates QRectF \since 5.3 Returns a rectangle grown by the \a margins. @@ -2413,7 +2412,6 @@ QRect QRectF::toAlignedRect() const Q_DECL_NOTHROW /*! \fn QRectF QRectF::marginsRemoved(const QMarginsF &margins) const - \relates QRectF \since 5.3 Removes the \a margins from the rectangle, shrinking it. @@ -2423,7 +2421,6 @@ QRect QRectF::toAlignedRect() const Q_DECL_NOTHROW /*! \fn QRectF QRectF::operator+=(const QMarginsF &margins) - \relates QRectF \since 5.3 Adds the \a margins to the rectangle, growing it. @@ -2433,7 +2430,6 @@ QRect QRectF::toAlignedRect() const Q_DECL_NOTHROW /*! \fn QRectF QRectF::operator-=(const QMarginsF &margins) - \relates QRectF \since 5.3 Returns a rectangle shrunk by the \a margins. diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 8bb8953dde..c43a7be7fd 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -2738,7 +2738,7 @@ bool operator<(const QString &s1, const QString &s2) } /*! \overload operator<() - \relates QString + Returns \c true if this string is lexically less than the parameter string called \a other; otherwise returns \c false. */ @@ -2843,7 +2843,7 @@ bool QString::operator<(QLatin1String other) const /*! \overload operator>() - \relates QString + Returns \c true if this string is lexically greater than the parameter string \a other; otherwise returns \c false. */ diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/tools/qtimezone.cpp index 45ae23cdf5..900c8ff14e 100644 --- a/src/corelib/tools/qtimezone.cpp +++ b/src/corelib/tools/qtimezone.cpp @@ -310,7 +310,6 @@ Q_GLOBAL_STATIC(QTimeZoneSingleton, global_tz); /*! \typedef QTimeZone::OffsetDataList - \relates QTimeZone Synonym for QVector. */ diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp index 50a4a09102..e9995045b1 100644 --- a/src/gui/accessible/qaccessible.cpp +++ b/src/gui/accessible/qaccessible.cpp @@ -451,7 +451,6 @@ QAccessibleInterface::~QAccessibleInterface() /*! \typedef QAccessible::Id - \relates QAccessible Synonym for unsigned, used by the QAccessibleInterface cache. */ -- cgit v1.2.3 From cc6a06632b26c4f60cb29f540af6eafc31ae3f02 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 19 Aug 2015 15:22:53 +0200 Subject: xcb: send QTabletEvent before QMouseEvent It was a regression: drawing applications which can handle both mouse and tablet events should not need to wait to see whether a mouse event will be followed by a corresponding tablet event. The tablet event is preferred because it has all the tablet parameters (pressure etc.) Also, show the timestamp of each mouse event in the log message, which helps to verify the correspondence. Task-number: QTBUG-47702 Change-Id: I9e832c19de935ec1243138eb4c1484284f61cbfc Reviewed-by: Laszlo Agocs --- src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 19 ++++++++++--------- src/plugins/platforms/xcb/qxcbwindow.cpp | 6 +++--- 2 files changed, 13 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 335236578b..d7688be0ff 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -971,15 +971,6 @@ bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData, Q xXIGenericDeviceEvent *xiEvent = static_cast(event); xXIDeviceEvent *xiDeviceEvent = reinterpret_cast(xiEvent); -#ifdef XCB_USE_XINPUT22 - // Synthesize mouse events since otherwise there are no mouse events from - // the pen on the XI 2.2+ path. - if (xi2MouseEvents() && eventListener) - eventListener->handleXIMouseEvent(reinterpret_cast(event)); -#else - Q_UNUSED(eventListener); -#endif - switch (xiEvent->evtype) { case XI_ButtonPress: { Qt::MouseButton b = xiToQtMouseButton(xiDeviceEvent->detail); @@ -1064,6 +1055,16 @@ bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData, Q handled = false; break; } + +#ifdef XCB_USE_XINPUT22 + // Synthesize mouse events since otherwise there are no mouse events from + // the pen on the XI 2.2+ path. + if (xi2MouseEvents() && eventListener) + eventListener->handleXIMouseEvent(reinterpret_cast(event)); +#else + Q_UNUSED(eventListener); +#endif + return handled; } diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index af4a88b7bc..4fdebe1ebb 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -2249,17 +2249,17 @@ void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event) switch (ev->evtype) { case XI_ButtonPress: - qCDebug(lcQpaXInput, "XI2 mouse press, button %d", button); + qCDebug(lcQpaXInput, "XI2 mouse press, button %d, time %d", button, ev->time); conn->setButton(button, true); handleButtonPressEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time); break; case XI_ButtonRelease: - qCDebug(lcQpaXInput, "XI2 mouse release, button %d", button); + qCDebug(lcQpaXInput, "XI2 mouse release, button %d, time %d", button, ev->time); conn->setButton(button, false); handleButtonReleaseEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time); break; case XI_Motion: - qCDebug(lcQpaXInput, "XI2 mouse motion %d,%d", event_x, event_y); + qCDebug(lcQpaXInput, "XI2 mouse motion %d,%d, time %d", event_x, event_y, ev->time); handleMotionNotifyEvent(event_x, event_y, root_x, root_y, modifiers, ev->time); break; default: -- cgit v1.2.3 From 5bf5fe964bc495f4390462d3287575bb99aab18e Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 11 Aug 2015 12:39:29 -0700 Subject: Fix Clang warning about copy elision Found by Clang 3.7: qcommandlineoption.cpp:287:12: error: moving a local object in a return statement prevents copy elision [-Werror,-Wpessimizing-move] Change-Id: I7de033f80b0e4431b7f1ffff13f97fb480001d36 Reviewed-by: David Faure --- src/corelib/tools/qcommandlineoption.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/tools/qcommandlineoption.cpp b/src/corelib/tools/qcommandlineoption.cpp index eb50cee5bb..5eda114087 100644 --- a/src/corelib/tools/qcommandlineoption.cpp +++ b/src/corelib/tools/qcommandlineoption.cpp @@ -284,7 +284,7 @@ QStringList QCommandLineOptionPrivate::removeInvalidNames(QStringList nameList) else nameList.erase(std::remove_if(nameList.begin(), nameList.end(), IsInvalidName()), nameList.end()); - return qMove(nameList); + return nameList; } /*! -- cgit v1.2.3 From cc5e84c8788a6d6f05dfdf76fc249177ee74dce1 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 11 Aug 2015 09:59:10 -0700 Subject: Avoid overflow in QTime::addSecs with too big a number of seconds QDateTime::addSecs needs to do something similar, but not identical because it needs the number of days too. And then there are daylight savings transitions... Task-number: QTBUG-47717 Change-Id: I7de033f80b0e4431b7f1ffff13f976f4f5e5a059 Reviewed-by: Allan Sandfeld Jensen --- src/corelib/tools/qdatetime.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index e445055e1d..eb4eff32b4 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -1681,6 +1681,7 @@ bool QTime::setHMS(int h, int m, int s, int ms) QTime QTime::addSecs(int s) const { + s %= SECS_PER_DAY; return addMSecs(s * 1000); } -- cgit v1.2.3 From b349289fa0003da58adb5cee51e5c2e093a6dd6f Mon Sep 17 00:00:00 2001 From: Samuel Nevala Date: Mon, 17 Aug 2015 14:57:46 +0300 Subject: winrt: Hide status bar on windows phone. Task-Id: QTBUG-47789 Change-Id: I9ca5f336ba9ee7524d4a4bbff3bbf4fbbb56fd54 Reviewed-by: Andrew Knight --- src/plugins/platforms/winrt/qwinrtscreen.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'src') diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 89ad33657b..2a7cbaa159 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -414,6 +414,9 @@ public: ComPtr canvas; ComPtr view; ComPtr displayInformation; +#ifdef Q_OS_WINPHONE + ComPtr statusBar; +#endif // Q_OS_WINPHONE QScopedPointer cursor; @@ -535,6 +538,15 @@ QWinRTScreen::QWinRTScreen(Xaml::IWindow *xamlWindow) Q_ASSERT_SUCCEEDED(hr); d->cursor.reset(new QWinRTCursor); + +#ifdef Q_OS_WINPHONE + ComPtr statusBarStatics; + hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_StatusBar).Get(), + IID_PPV_ARGS(&statusBarStatics)); + Q_ASSERT_SUCCEEDED(hr); + hr = statusBarStatics->GetForCurrentView(&d->statusBar); + Q_ASSERT_SUCCEEDED(hr); +#endif // Q_OS_WINPHONE } QWinRTScreen::~QWinRTScreen() @@ -660,6 +672,19 @@ void QWinRTScreen::addWindow(QWindow *window) Q_D(QWinRTScreen); if (window == topWindow()) return; + +#ifdef Q_OS_WINPHONE + if (d->statusBar && (window->flags() & Qt::WindowType_Mask) == Qt::Window) { + QEventDispatcherWinRT::runOnXamlThread([this, d]() { + HRESULT hr; + ComPtr op; + hr = d->statusBar->HideAsync(&op); + Q_ASSERT_SUCCEEDED(hr); + return S_OK; + }); + } +#endif // Q_OS_WINPHONE + d->visibleWindows.prepend(window); QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason); handleExpose(); -- cgit v1.2.3 From 025d6a778ceb377e688f1b394aa5252d74d77199 Mon Sep 17 00:00:00 2001 From: Jorgen Lind Date: Mon, 15 Jun 2015 17:57:20 +0200 Subject: Fix unnecessary enter leave events Task-number: QTBUG-45565 Change-Id: I92c1dc0a14440259349eeae40372221dbc3c548f Reviewed-by: Andy Shaw --- src/widgets/kernel/qwidgetwindow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index d4e73bcac4..24ef7de1cf 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -445,11 +445,11 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) receiver = popupChild; if (receiver != popup) widgetPos = receiver->mapFromGlobal(event->globalPos()); - QWidget *alien = m_widget->childAt(m_widget->mapFromGlobal(event->globalPos())); + QWidget *alien = receiver->childAt(receiver->mapFromGlobal(event->globalPos())); QMouseEvent e(event->type(), widgetPos, event->windowPos(), event->screenPos(), event->button(), event->buttons(), event->modifiers()); QGuiApplicationPrivate::setMouseEventSource(&e, QGuiApplicationPrivate::mouseEventSource(event)); e.setTimestamp(event->timestamp()); - QApplicationPrivate::sendMouseEvent(receiver, &e, alien, m_widget, &qt_button_down, qt_last_mouse_receiver); + QApplicationPrivate::sendMouseEvent(receiver, &e, alien, receiver->window(), &qt_button_down, qt_last_mouse_receiver); qt_last_mouse_receiver = receiver; } else { // close disabled popups when a mouse button is pressed or released -- cgit v1.2.3 From d99c9bcf2c4e14d3db02ad375aa624a0695e838d Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Tue, 7 Apr 2015 15:06:20 +0200 Subject: Fix regression in reading certain compressed bmp images For BITFIELDS compressed images, the image data may be preceded by bitmask fields. The file positioning code that should make sure those were read correctly was erroneously included in the block of code that was moved in 6f1b82fccdaf202856dcc6510c16b0531680fe23. Task-number: QTBUG-45559 Task-number: QTBUG-40890 Done-with: Eirik Aavitsland Change-Id: Id2b3ce078f67ac6ebf75ab0cc463dc719af83393 Reviewed-by: aavit --- src/gui/image/qbmphandler.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp index f124cede36..ef12b23caa 100644 --- a/src/gui/image/qbmphandler.cpp +++ b/src/gui/image/qbmphandler.cpp @@ -212,6 +212,9 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int int blue_scale = 0; int alpha_scale = 0; + if (!d->isSequential()) + d->seek(startpos + BMP_FILEHDR_SIZE + (bi.biSize >= BMP_WIN4 ? BMP_WIN : bi.biSize)); // goto start of colormap or masks + if (bi.biSize >= BMP_WIN4 || (comp == BMP_BITFIELDS && (nbits == 16 || nbits == 32))) { if (d->read((char *)&red_mask, sizeof(red_mask)) != sizeof(red_mask)) return false; @@ -299,9 +302,6 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int image.setDotsPerMeterX(bi.biXPelsPerMeter); image.setDotsPerMeterY(bi.biYPelsPerMeter); - if (!d->isSequential()) - d->seek(startpos + BMP_FILEHDR_SIZE + (bi.biSize >= BMP_WIN4? BMP_WIN : bi.biSize)); // goto start of colormap - if (ncols > 0) { // read color table uchar rgb[4]; int rgb_len = t == BMP_OLD ? 3 : 4; -- cgit v1.2.3 From bc32c0ebc0bc00db84ca2f28eb16ab2e5b53a1b6 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Fri, 24 Jul 2015 09:53:20 +0200 Subject: QNAM: Fix reply deadlocks on server closing connection The _q_readyRead can also be called from readMoreLater() because we implemented it so that bandwidth limited reading can be implemented. This can lead to a race condition if the socket is closing at the specific moment and then deadlock the channel: It will stay unusable with a zombie request. The fix in QHttpProtocolaHandler checks if there is actually bytes available to read from the socket and only then continue. The fix in the HTTP channel needs to be done to properly finish the reply in cases of a server replying with HTTP/1.0 or "Connection: close". The delayed incovation of _q_receiveReply will properly finish up the reply. Change-Id: I19ce2ae595f91d56386cc7406ccacc9935672b6b Reviewed-by: Richard J. Moore --- src/network/access/qhttpnetworkconnectionchannel.cpp | 4 ++++ src/network/access/qhttpprotocolhandler.cpp | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 7428f9bf5b..257aa13718 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -829,11 +829,15 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket if (!reply->d_func()->expectContent()) { // No content expected, this is a valid way to have the connection closed by the server + // We need to invoke this asynchronously to make sure the state() of the socket is on QAbstractSocket::UnconnectedState + QMetaObject::invokeMethod(this, "_q_receiveReply", Qt::QueuedConnection); return; } if (reply->contentLength() == -1 && !reply->d_func()->isChunked()) { // There was no content-length header and it's not chunked encoding, // so this is a valid way to have the connection closed by the server + // We need to invoke this asynchronously to make sure the state() of the socket is on QAbstractSocket::UnconnectedState + QMetaObject::invokeMethod(this, "_q_receiveReply", Qt::QueuedConnection); return; } // ok, we got a disconnect even though we did not expect it diff --git a/src/network/access/qhttpprotocolhandler.cpp b/src/network/access/qhttpprotocolhandler.cpp index ab2e3dac57..a2083158f1 100644 --- a/src/network/access/qhttpprotocolhandler.cpp +++ b/src/network/access/qhttpprotocolhandler.cpp @@ -237,7 +237,12 @@ void QHttpProtocolHandler::_q_readyRead() } if (m_channel->isSocketWaiting() || m_channel->isSocketReading()) { - m_channel->state = QHttpNetworkConnectionChannel::ReadingState; + if (m_socket->bytesAvailable()) { + // We might get a spurious call from readMoreLater() + // call of the QHttpNetworkConnection even while the socket is disconnecting. + // Therefore check if there is actually bytes available before changing the channel state. + m_channel->state = QHttpNetworkConnectionChannel::ReadingState; + } if (m_reply) _q_receiveReply(); } -- cgit v1.2.3 From b409b1a0e423fe690f038ca0140830b13970fa4d Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 18 Aug 2015 11:51:45 +0200 Subject: libinput: Fix key mapping Prevent generating 2 character long 'text' strings with some garbage as second char. This matches how xcb works. Change-Id: I88a248a89c80b0e100c1c4871cfab4f2c287535e Reviewed-by: Shawn Rutledge --- src/platformsupport/input/libinput/qlibinputkeyboard.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/platformsupport/input/libinput/qlibinputkeyboard.cpp b/src/platformsupport/input/libinput/qlibinputkeyboard.cpp index 3bb9107e16..ec7ea7ef0d 100644 --- a/src/platformsupport/input/libinput/qlibinputkeyboard.cpp +++ b/src/platformsupport/input/libinput/qlibinputkeyboard.cpp @@ -180,10 +180,13 @@ void QLibInputKeyboard::processKey(libinput_event_keyboard *e) const uint32_t k = libinput_event_keyboard_get_key(e) + 8; const bool pressed = libinput_event_keyboard_get_key_state(e) == LIBINPUT_KEY_STATE_PRESSED; - QByteArray chars; - chars.resize(1 + xkb_state_key_get_utf8(m_state, k, Q_NULLPTR, 0)); - xkb_state_key_get_utf8(m_state, k, chars.data(), chars.size()); - const QString text = QString::fromUtf8(chars); + QVarLengthArray chars(32); + const int size = xkb_state_key_get_utf8(m_state, k, chars.data(), chars.size()); + if (Q_UNLIKELY(size + 1 > chars.size())) { // +1 for NUL + chars.resize(size + 1); + xkb_state_key_get_utf8(m_state, k, chars.data(), chars.size()); + } + const QString text = QString::fromUtf8(chars.constData(), size); const xkb_keysym_t sym = xkb_state_key_get_one_sym(m_state, k); -- cgit v1.2.3 From 39c2b8c5c12dfb8560fa04ce346a129adb223e29 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 17 Jul 2015 22:23:50 -0700 Subject: Add support for same-file intrinsics with Clang 3.7 It supports the same feature that GCC does Change-Id: Ib306f8f647014b399b87ffff13f1f3159898741b Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/tools/qsimd_p.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h index dd93b4fd26..8523fb09c1 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -54,9 +54,9 @@ * for the x86 and ARM intrinsics: * - GCC: the -mXXX or march=YYY flag is necessary before #include * up to 4.8; GCC >= 4.9 can include unconditionally + * - Clang: same as GCC, with unconditional inclusion with version 3.7 * - Intel CC: #include can happen unconditionally * - MSVC: #include can happen unconditionally - * - RVCT: ??? * * We will try to include all headers possible under this configuration. * @@ -138,7 +138,8 @@ #define QT_COMPILER_SUPPORTS(x) (QT_COMPILER_SUPPORTS_ ## x - 0) #if (defined(Q_CC_INTEL) || defined(Q_CC_MSVC) \ - || (defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && (__GNUC__-0) * 100 + (__GNUC_MINOR__-0) >= 409)) \ + || (defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && (__GNUC__-0) * 100 + (__GNUC_MINOR__-0) >= 409) \ + || (defined(Q_CC_CLANG) && Q_CC_CLANG >= 307)) \ && !defined(QT_BOOTSTRAPPED) # define QT_COMPILER_SUPPORTS_SIMD_ALWAYS # define QT_COMPILER_SUPPORTS_HERE(x) QT_COMPILER_SUPPORTS(x) -- cgit v1.2.3 From 3997321199c67fc8ee6067f36d837997c7c19418 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 11 Aug 2015 00:42:41 -0700 Subject: Remove Q_DECLARE_TYPEINFO that causes a build error ICC doesn't like it qdbusintrospection_p.h(162): error: explicit specialization of class "QTypeInfo" must precede its first use It's used by the QVector in the same class Change-Id: I7de033f80b0e4431b7f1ffff13f958971617b657 Reviewed-by: Thiago Macieira --- src/dbus/qdbusintrospection_p.h | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/dbus/qdbusintrospection_p.h b/src/dbus/qdbusintrospection_p.h index 572a39b140..f34e336eb3 100644 --- a/src/dbus/qdbusintrospection_p.h +++ b/src/dbus/qdbusintrospection_p.h @@ -158,7 +158,6 @@ public: private: QDBusIntrospection(); }; -Q_DECLARE_TYPEINFO(QDBusIntrospection::Argument, Q_MOVABLE_TYPE); QT_END_NAMESPACE -- cgit v1.2.3 From 53251e23cf3f82950c5de1c2208d9f376b5bb5f0 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 20 Aug 2015 11:18:56 +0200 Subject: Set QAction::NoRole on dock widget view actions. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prevent the actions from being shuffled around in OS X menus since the default is QAction::TextHeuristicRole. Task-number: QTBUG-47739 Change-Id: Ib68bb7c51eb9278a99d277473f9d4cfcf740431c Reviewed-by: Oswald Buddenhagen Reviewed-by: Morten Johan Sørvig --- src/widgets/widgets/qdockwidget.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp index 6ea92e4c4d..8b0263fc0c 100644 --- a/src/widgets/widgets/qdockwidget.cpp +++ b/src/widgets/widgets/qdockwidget.cpp @@ -614,6 +614,7 @@ void QDockWidgetPrivate::init() #ifndef QT_NO_ACTION toggleViewAction = new QAction(q); toggleViewAction->setCheckable(true); + toggleViewAction->setMenuRole(QAction::NoRole); fixedWindowTitle = qt_setWindowTitle_helperHelper(q->windowTitle(), q); toggleViewAction->setText(fixedWindowTitle); QObject::connect(toggleViewAction, SIGNAL(triggered(bool)), -- cgit v1.2.3 From 89efa7333db4b5877cb58b16e511b690fe43507c Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 10 Mar 2015 15:01:21 -0700 Subject: QAbstractSocketEngine: introduce QIpPacketHeader for datagrams This commit changes the readDatagram() and writeDatagram() virtual functions to take a QIpPacketHeader as meta data, instead of a QHostAddress/quint16 pair. As previously, the header is an "out" parameter for readDatagram() and an "in" parameter for writeDatagram(). The header pointer in readDatagram() is allowed to be null if the PacketHeaderOptions indicates WantNone. Otherwise, it must not be null. The extra options parameter is introduced because we may not always want all the metadata upon reception. For sending, we know what to include or not based on what's set in the incoming header parameter. QIpPacketHeader splits sender and destination because we'll be able to return both on datagram reception. Change-Id: Iee8cbc07c4434ce9b560ffff13ca4213255008c7 Reviewed-by: Richard J. Moore --- src/network/socket/qabstractsocketengine_p.h | 38 +++++++++++++++++-- src/network/socket/qhttpsocketengine.cpp | 6 +-- src/network/socket/qhttpsocketengine_p.h | 7 ++-- src/network/socket/qnativesocketengine.cpp | 48 +++++++++++++++++------- src/network/socket/qnativesocketengine_p.h | 14 +++---- src/network/socket/qnativesocketengine_unix.cpp | 16 +++++--- src/network/socket/qnativesocketengine_win.cpp | 14 ++++--- src/network/socket/qnativesocketengine_winrt.cpp | 21 ++++++----- src/network/socket/qnativesocketengine_winrt_p.h | 9 ++--- src/network/socket/qsocks5socketengine.cpp | 18 ++++----- src/network/socket/qsocks5socketengine_p.h | 7 ++-- src/network/socket/qudpsocket.cpp | 17 ++++++++- 12 files changed, 138 insertions(+), 77 deletions(-) (limited to 'src') diff --git a/src/network/socket/qabstractsocketengine_p.h b/src/network/socket/qabstractsocketengine_p.h index f2a3149678..c485e80f5d 100644 --- a/src/network/socket/qabstractsocketengine_p.h +++ b/src/network/socket/qabstractsocketengine_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Intel Corporation. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtNetwork module of the Qt Toolkit. @@ -58,6 +59,26 @@ class QNetworkInterface; #endif class QNetworkProxy; +class QIpPacketHeader +{ +public: + QIpPacketHeader(const QHostAddress &dstAddr = QHostAddress(), quint16 port = 0) + : destinationAddress(dstAddr), destinationPort(port) + {} + + void clear() + { + senderAddress.clear(); + destinationAddress.clear(); + } + + QHostAddress senderAddress; + QHostAddress destinationAddress; + + quint16 senderPort; + quint16 destinationPort; +}; + class QAbstractSocketEngineReceiver { public: virtual ~QAbstractSocketEngineReceiver(){} @@ -96,6 +117,14 @@ public: TypeOfServiceOption }; + enum PacketHeaderOption { + WantNone = 0, + WantDatagramSender, + + WantAll = 0xff + }; + Q_DECLARE_FLAGS(PacketHeaderOptions, PacketHeaderOption) + virtual bool initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::IPv4Protocol) = 0; virtual bool initialize(qintptr socketDescriptor, QAbstractSocket::SocketState socketState = QAbstractSocket::ConnectedState) = 0; @@ -126,10 +155,9 @@ public: virtual bool setMulticastInterface(const QNetworkInterface &iface) = 0; #endif // QT_NO_NETWORKINTERFACE - virtual qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0, - quint16 *port = 0) = 0; - virtual qint64 writeDatagram(const char *data, qint64 len, const QHostAddress &addr, - quint16 port) = 0; + virtual qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader *header = 0, + PacketHeaderOptions = WantNone) = 0; + virtual qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &header) = 0; virtual bool hasPendingDatagrams() const = 0; virtual qint64 pendingDatagramSize() const = 0; #endif // QT_NO_UDPSOCKET @@ -225,6 +253,8 @@ private: friend class QAbstractSocketEngine; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QAbstractSocketEngine::PacketHeaderOptions) + QT_END_NAMESPACE #endif // QABSTRACTSOCKETENGINE_P_H diff --git a/src/network/socket/qhttpsocketengine.cpp b/src/network/socket/qhttpsocketengine.cpp index 23347ce08b..1a90abd22c 100644 --- a/src/network/socket/qhttpsocketengine.cpp +++ b/src/network/socket/qhttpsocketengine.cpp @@ -271,14 +271,12 @@ bool QHttpSocketEngine::setMulticastInterface(const QNetworkInterface &) } #endif // QT_NO_NETWORKINTERFACE -qint64 QHttpSocketEngine::readDatagram(char *, qint64, QHostAddress *, - quint16 *) +qint64 QHttpSocketEngine::readDatagram(char *, qint64, QIpPacketHeader *, PacketHeaderOptions) { return 0; } -qint64 QHttpSocketEngine::writeDatagram(const char *, qint64, const QHostAddress &, - quint16) +qint64 QHttpSocketEngine::writeDatagram(const char *, qint64, const QIpPacketHeader &) { return 0; } diff --git a/src/network/socket/qhttpsocketengine_p.h b/src/network/socket/qhttpsocketengine_p.h index 4d90487679..41c63fe11e 100644 --- a/src/network/socket/qhttpsocketengine_p.h +++ b/src/network/socket/qhttpsocketengine_p.h @@ -105,10 +105,9 @@ public: bool setMulticastInterface(const QNetworkInterface &iface) Q_DECL_OVERRIDE; #endif // QT_NO_NETWORKINTERFACE - qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0, - quint16 *port = 0) Q_DECL_OVERRIDE; - qint64 writeDatagram(const char *data, qint64 len, const QHostAddress &addr, - quint16 port) Q_DECL_OVERRIDE; + qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader *, + PacketHeaderOptions) Q_DECL_OVERRIDE; + qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &) Q_DECL_OVERRIDE; bool hasPendingDatagrams() const Q_DECL_OVERRIDE; qint64 pendingDatagramSize() const Q_DECL_OVERRIDE; #endif // QT_NO_UDPSOCKET diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp index 22151b8e56..901dab5473 100644 --- a/src/network/socket/qnativesocketengine.cpp +++ b/src/network/socket/qnativesocketengine.cpp @@ -88,6 +88,25 @@ errorString() can be called to determine the cause of the error. */ +/*! + \enum QAbstractSocketEngine::PacketHeaderOption + + Specifies which fields in the IP packet header are desired in the call to + readDatagram(). + + \value WantNone caller isn't interested in the packet metadata + \value WantDatagramSender caller wants the sender address and port number + \value WantDatagramDestination caller wants the packet's destination address and port number + (this option is useful to distinguish multicast packets from unicast) + \value WantDatagramHopLimit caller wants the packet's remaining hop limit or time to live + (this option is useful in IPv4 multicasting, where the TTL is used + to indicate the realm) + \value WantAll this is a catch-all value to indicate the caller is + interested in all the available information + + \sa readDatagram(), QUdpDatagram +*/ + #include "qnativesocketengine_p.h" #include @@ -759,9 +778,8 @@ qint64 QNativeSocketEngine::pendingDatagramSize() const /*! Reads up to \a maxSize bytes of a datagram from the socket, stores it in \a data and returns the number of bytes read. The - address and port of the sender are stored in \a address and \a - port. If either of these pointers is 0, the corresponding value is - discarded. + address, port, and other IP header fields are stored in \a header + according to the request in \a options. To avoid unnecessarily loss of data, call pendingDatagramSize() to determine the size of the pending message before reading it. If \a @@ -771,20 +789,23 @@ qint64 QNativeSocketEngine::pendingDatagramSize() const \sa hasPendingDatagrams() */ -qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxSize, QHostAddress *address, - quint16 *port) +qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxSize, QIpPacketHeader *header, + PacketHeaderOptions options) { Q_D(QNativeSocketEngine); Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::readDatagram(), -1); Q_CHECK_TYPE(QNativeSocketEngine::readDatagram(), QAbstractSocket::UdpSocket, -1); - return d->nativeReceiveDatagram(data, maxSize, address, port); + return d->nativeReceiveDatagram(data, maxSize, header, options); } /*! Writes a UDP datagram of size \a size bytes to the socket from - \a data to the address \a host on port \a port, and returns the - number of bytes written, or -1 if an error occurred. + \a data to the destination contained in \a header, and returns the + number of bytes written, or -1 if an error occurred. If \a header + contains other settings like hop limit or source address, this function + will try to pass them to the operating system too, but will not + indicate an error if it could not pass them. Only one datagram is sent, and if there is too much data to fit into a single datagram, the operation will fail and error() @@ -794,18 +815,19 @@ qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxSize, QHostAddres disadvised, as even if they are sent successfully, they are likely to be fragmented before arriving at their destination. - Experience has shown that it is in general safe to send datagrams - no larger than 512 bytes. + Experience has shown that it is in general safe to send IPv4 datagrams + no larger than 512 bytes or IPv6 datagrams no larger than 1280 (the + minimum MTU). \sa readDatagram() */ -qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 size, - const QHostAddress &host, quint16 port) +qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 size, const QIpPacketHeader &header) { Q_D(QNativeSocketEngine); Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::writeDatagram(), -1); Q_CHECK_TYPE(QNativeSocketEngine::writeDatagram(), QAbstractSocket::UdpSocket, -1); - return d->nativeSendDatagram(data, size, d->adjustAddressProtocol(host), port); + + return d->nativeSendDatagram(data, size, header); } /*! diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h index 653309302c..fb36ce6204 100644 --- a/src/network/socket/qnativesocketengine_p.h +++ b/src/network/socket/qnativesocketengine_p.h @@ -133,10 +133,9 @@ public: qint64 read(char *data, qint64 maxlen) Q_DECL_OVERRIDE; qint64 write(const char *data, qint64 len) Q_DECL_OVERRIDE; - qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0, - quint16 *port = 0) Q_DECL_OVERRIDE; - qint64 writeDatagram(const char *data, qint64 len, const QHostAddress &addr, - quint16 port) Q_DECL_OVERRIDE; + qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader * = 0, + PacketHeaderOptions = WantNone) Q_DECL_OVERRIDE; + qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &) Q_DECL_OVERRIDE; bool hasPendingDatagrams() const Q_DECL_OVERRIDE; qint64 pendingDatagramSize() const Q_DECL_OVERRIDE; @@ -242,10 +241,9 @@ public: bool nativeHasPendingDatagrams() const; qint64 nativePendingDatagramSize() const; - qint64 nativeReceiveDatagram(char *data, qint64 maxLength, - QHostAddress *address, quint16 *port); - qint64 nativeSendDatagram(const char *data, qint64 length, - const QHostAddress &host, quint16 port); + qint64 nativeReceiveDatagram(char *data, qint64 maxLength, QIpPacketHeader *header, + QAbstractSocketEngine::PacketHeaderOptions options); + qint64 nativeSendDatagram(const char *data, qint64 length, const QIpPacketHeader &header); qint64 nativeRead(char *data, qint64 maxLength); qint64 nativeWrite(const char *data, qint64 length); int nativeSelect(int timeout, bool selectForRead) const; diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 5c4e4e885b..0e04096296 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -844,8 +844,8 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const return qint64(recvResult); } -qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize, - QHostAddress *address, quint16 *port) +qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize, QIpPacketHeader *header, + QAbstractSocketEngine::PacketHeaderOptions options) { qt_sockaddr aa; memset(&aa, 0, sizeof(aa)); @@ -861,8 +861,11 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS if (recvFromResult == -1) { setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString); - } else if (port || address) { - qt_socket_getPortAndAddress(&aa, port, address); + if (header) + header->clear(); + } else if (options != QAbstractSocketEngine::WantNone) { + Q_ASSERT(header); + qt_socket_getPortAndAddress(&aa, &header->senderPort, &header->senderAddress); } #if defined (QNATIVESOCKETENGINE_DEBUG) @@ -875,14 +878,15 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS return qint64(maxSize ? recvFromResult : recvFromResult == -1 ? -1 : 0); } -qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len, - const QHostAddress &host, quint16 port) +qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len, const QIpPacketHeader &header) { struct sockaddr_in sockAddrIPv4; struct sockaddr *sockAddrPtr = 0; QT_SOCKLEN_T sockAddrSize = 0; struct sockaddr_in6 sockAddrIPv6; + const QHostAddress &host = header.destinationAddress; + quint16 port = header.destinationPort; if (host.protocol() == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) { diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 8c3f68f04f..ed376eed95 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -1197,8 +1197,8 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const } -qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxLength, - QHostAddress *address, quint16 *port) +qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxLength, QIpPacketHeader *header, + QAbstractSocketEngine::PacketHeaderOptions options) { qint64 ret = 0; @@ -1232,12 +1232,15 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxL WS_ERROR_DEBUG(err); setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString); ret = -1; + if (header) + header->clear(); } } else { ret = qint64(bytesRead); + if (options & QNativeSocketEngine::WantDatagramSender) + qt_socket_getPortAndAddress(socketDescriptor, &aa, &header->senderPort, &header->senderAddress); } - qt_socket_getPortAndAddress(socketDescriptor, &aa, port, address); #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %li, %s, %i) == %li", @@ -1251,7 +1254,7 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxL qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len, - const QHostAddress &address, quint16 port) + const QIpPacketHeader &header) { qint64 ret = -1; struct sockaddr_in sockAddrIPv4; @@ -1259,7 +1262,8 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l struct sockaddr *sockAddrPtr = 0; QT_SOCKLEN_T sockAddrSize = 0; - setPortAndAddress(&sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize); + setPortAndAddress(&sockAddrIPv4, &sockAddrIPv6, header.destinationPort, + header.destinationAddress, &sockAddrPtr, &sockAddrSize); WSABUF buf; #if !defined(Q_OS_WINCE) diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index 2d04946601..4a92ca5a95 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -538,18 +538,19 @@ qint64 QNativeSocketEngine::write(const char *data, qint64 len) return bytesWritten; } -qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QHostAddress *addr, quint16 *port) +qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QIpPacketHeader *header, + PacketHeaderOptions options) { Q_D(QNativeSocketEngine); - if (d->socketType != QAbstractSocket::UdpSocket || d->pendingDatagrams.isEmpty()) + if (d->socketType != QAbstractSocket::UdpSocket || d->pendingDatagrams.isEmpty()) { + if (header) + header->clear(); return -1; + } WinRtDatagram datagram = d->pendingDatagrams.takeFirst(); - if (addr) - *addr = datagram.address; - - if (port) - *port = datagram.port; + if (header) + *header = datagram.header; QByteArray readOrigin; // Do not read the whole datagram. Put the rest of it back into the "queue" @@ -564,7 +565,7 @@ qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QHostAddress return readOrigin.length(); } -qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 len, const QHostAddress &addr, quint16 port) +qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 len, const QIpPacketHeader &header) { Q_D(QNativeSocketEngine); if (d->socketType != QAbstractSocket::UdpSocket) @@ -1230,11 +1231,11 @@ HRESULT QNativeSocketEnginePrivate::handleNewDatagram(IDatagramSocket *socket, I remoteHost->get_CanonicalName(remoteHostString.GetAddressOf()); RETURN_OK_IF_FAILED("Could not obtain remote host's canonical name"); returnAddress.setAddress(qt_QStringFromHString(remoteHostString)); - datagram.address = returnAddress; + datagram.header.senderAddress = returnAddress; HString remotePort; hr = args->get_RemotePort(remotePort.GetAddressOf()); RETURN_OK_IF_FAILED("Could not obtain remote port"); - datagram.port = qt_QStringFromHString(remotePort).toInt(); + datagram.header.senderPort = qt_QStringFromHString(remotePort).toInt(); ComPtr reader; hr = args->GetDataReader(&reader); diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h index eb032bc977..4286ff6373 100644 --- a/src/network/socket/qnativesocketengine_winrt_p.h +++ b/src/network/socket/qnativesocketengine_winrt_p.h @@ -58,8 +58,7 @@ class QNativeSocketEnginePrivate; struct WinRtDatagram { QByteArray data; - int port; - QHostAddress address; + QIpPacketHeader header; }; class Q_AUTOTEST_EXPORT QNativeSocketEngine : public QAbstractSocketEngine @@ -97,10 +96,8 @@ public: qint64 read(char *data, qint64 maxlen); qint64 write(const char *data, qint64 len); - qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0, - quint16 *port = 0); - qint64 writeDatagram(const char *data, qint64 len, const QHostAddress &addr, - quint16 port); + qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader *, PacketHeaderOptions); + qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &header); bool hasPendingDatagrams() const; qint64 pendingDatagramSize() const; diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp index a6eafd2601..26543883cc 100644 --- a/src/network/socket/qsocks5socketengine.cpp +++ b/src/network/socket/qsocks5socketengine.cpp @@ -1383,7 +1383,7 @@ bool QSocks5SocketEngine::bind(const QHostAddress &addr, quint16 port) #endif dummy.setProxy(QNetworkProxy::NoProxy); if (!dummy.bind() - || writeDatagram(0,0, d->data->controlSocket->localAddress(), dummy.localPort()) != 0 + || writeDatagram(0,0, QIpPacketHeader(d->data->controlSocket->localAddress(), dummy.localPort())) != 0 || !dummy.waitForReadyRead(qt_subtract_from_timeout(msecs, stopWatch.elapsed())) || dummy.readDatagram(0,0, &d->localAddress, &d->localPort) != 0) { QSOCKS5_DEBUG << "udp actual address and port lookup failed"; @@ -1555,7 +1555,7 @@ qint64 QSocks5SocketEngine::write(const char *data, qint64 len) #ifndef QT_NO_UDPSOCKET } else if (d->mode == QSocks5SocketEnginePrivate::UdpAssociateMode) { // send to connected address - return writeDatagram(data, len, d->peerAddress, d->peerPort); + return writeDatagram(data, len, QIpPacketHeader(d->peerAddress, d->peerPort)); #endif } //### set an error ??? @@ -1594,8 +1594,7 @@ bool QSocks5SocketEngine::setMulticastInterface(const QNetworkInterface &) } #endif // QT_NO_NETWORKINTERFACE -qint64 QSocks5SocketEngine::readDatagram(char *data, qint64 maxlen, QHostAddress *addr, - quint16 *port) +qint64 QSocks5SocketEngine::readDatagram(char *data, qint64 maxlen, QIpPacketHeader *header, PacketHeaderOptions) { Q_D(QSocks5SocketEngine); @@ -1607,15 +1606,12 @@ qint64 QSocks5SocketEngine::readDatagram(char *data, qint64 maxlen, QHostAddress QSocks5RevivedDatagram datagram = d->udpData->pendingDatagrams.dequeue(); int copyLen = qMin(maxlen, datagram.data.size()); memcpy(data, datagram.data.constData(), copyLen); - if (addr) - *addr = datagram.address; - if (port) - *port = datagram.port; + header->senderAddress = datagram.address; + header->senderPort = datagram.port; return copyLen; } -qint64 QSocks5SocketEngine::writeDatagram(const char *data, qint64 len, const QHostAddress &address, - quint16 port) +qint64 QSocks5SocketEngine::writeDatagram(const char *data, qint64 len, const QIpPacketHeader &header) { Q_D(QSocks5SocketEngine); @@ -1634,7 +1630,7 @@ qint64 QSocks5SocketEngine::writeDatagram(const char *data, qint64 len, const QH outBuf[0] = 0x00; outBuf[1] = 0x00; outBuf[2] = 0x00; - if (!qt_socks5_set_host_address_and_port(address, port, &outBuf)) { + if (!qt_socks5_set_host_address_and_port(header.destinationAddress, header.destinationPort, &outBuf)) { } outBuf += QByteArray(data, len); QSOCKS5_DEBUG << "sending" << dump(outBuf); diff --git a/src/network/socket/qsocks5socketengine_p.h b/src/network/socket/qsocks5socketengine_p.h index c97b0e89ce..de20e0ef0e 100644 --- a/src/network/socket/qsocks5socketengine_p.h +++ b/src/network/socket/qsocks5socketengine_p.h @@ -93,10 +93,9 @@ public: bool setMulticastInterface(const QNetworkInterface &iface) Q_DECL_OVERRIDE; #endif // QT_NO_NETWORKINTERFACE - qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0, - quint16 *port = 0) Q_DECL_OVERRIDE; - qint64 writeDatagram(const char *data, qint64 len, const QHostAddress &addr, - quint16 port) Q_DECL_OVERRIDE; + qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader * = 0, + PacketHeaderOptions = WantNone) Q_DECL_OVERRIDE; + qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &) Q_DECL_OVERRIDE; bool hasPendingDatagrams() const Q_DECL_OVERRIDE; qint64 pendingDatagramSize() const Q_DECL_OVERRIDE; #endif // QT_NO_UDPSOCKET diff --git a/src/network/socket/qudpsocket.cpp b/src/network/socket/qudpsocket.cpp index 87686f94e1..f4e7d20b03 100644 --- a/src/network/socket/qudpsocket.cpp +++ b/src/network/socket/qudpsocket.cpp @@ -333,7 +333,7 @@ qint64 QUdpSocket::writeDatagram(const char *data, qint64 size, const QHostAddre if (state() == UnconnectedState) bind(); - qint64 sent = d->socketEngine->writeDatagram(data, size, address, port); + qint64 sent = d->socketEngine->writeDatagram(data, size, QIpPacketHeader(address, port)); d->cachedSocketDescriptor = d->socketEngine->socketDescriptor(); if (sent >= 0) { @@ -379,7 +379,20 @@ qint64 QUdpSocket::readDatagram(char *data, qint64 maxSize, QHostAddress *addres qDebug("QUdpSocket::readDatagram(%p, %llu, %p, %p)", data, maxSize, address, port); #endif QT_CHECK_BOUND("QUdpSocket::readDatagram()", -1); - qint64 readBytes = d->socketEngine->readDatagram(data, maxSize, address, port); + + qint64 readBytes; + if (address || port) { + QIpPacketHeader header; + readBytes = d->socketEngine->readDatagram(data, maxSize, &header, + QAbstractSocketEngine::WantDatagramSender); + if (address) + *address = header.senderAddress; + if (port) + *port = header.senderPort; + } else { + readBytes = d->socketEngine->readDatagram(data, maxSize); + } + d_func()->socketEngine->setReadNotificationEnabled(true); if (readBytes < 0) { d->socketError = d->socketEngine->error(); -- cgit v1.2.3 From ef05ad0ac500c10b1a3ae254d8a07968d6cf0c9e Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 10 Mar 2015 15:09:29 -0700 Subject: QNativeSocketEngine: use sendmsg/recvmsg instead of sendto/recvfrom We'll need to use these functions instead of the ones we're currently using in order to access the ancillary data. Note that on Windows the two functions aren't globals, but must be obtained via ioctl, which means they can fail. If they do, we fall back to using WSARecvFrom/WSASendTo Change-Id: Iee8cbc07c4434ce9b560ffff13ca4284acd24132 Reviewed-by: Richard J. Moore --- src/network/socket/qnativesocketengine_p.h | 35 ++++++++++ src/network/socket/qnativesocketengine_unix.cpp | 86 ++++++++++++++----------- src/network/socket/qnativesocketengine_win.cpp | 82 +++++++++++++++-------- src/network/socket/qnet_unix_p.h | 27 +------- 4 files changed, 142 insertions(+), 88 deletions(-) (limited to 'src') diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h index fb36ce6204..29063b3a85 100644 --- a/src/network/socket/qnativesocketengine_p.h +++ b/src/network/socket/qnativesocketengine_p.h @@ -51,6 +51,7 @@ # include #else # include +# include #endif QT_BEGIN_NAMESPACE @@ -70,6 +71,36 @@ struct qt_sockaddr_storage { #ifdef Q_OS_WIN #define QT_SOCKLEN_T int #define QT_SOCKOPTLEN_T int + +// The following definitions are copied from the MinGW header mswsock.h which +// was placed in the public domain. The WSASendMsg and WSARecvMsg functions +// were introduced with Windows Vista, so some Win32 headers are lacking them. +// There are no known versions of Windows CE or Embedded that contain them. +#ifndef Q_OS_WINCE +# ifndef WSAID_WSARECVMSG +typedef INT (WINAPI *LPFN_WSARECVMSG)(SOCKET s, LPWSAMSG lpMsg, + LPDWORD lpdwNumberOfBytesRecvd, + LPWSAOVERLAPPED lpOverlapped, + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine); +# define WSAID_WSARECVMSG {0xf689d7c8,0x6f1f,0x436b,{0x8a,0x53,0xe5,0x4f,0xe3,0x51,0xc3,0x22}} +# endif +# ifndef WSAID_WSASENDMSG +typedef struct { + LPWSAMSG lpMsg; + DWORD dwFlags; + LPDWORD lpNumberOfBytesSent; + LPWSAOVERLAPPED lpOverlapped; + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine; +} WSASENDMSG, *LPWSASENDMSG; + +typedef INT (WSAAPI *LPFN_WSASENDMSG)(SOCKET s, LPWSAMSG lpMsg, DWORD dwFlags, + LPDWORD lpNumberOfBytesSent, + LPWSAOVERLAPPED lpOverlapped, + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine); + +# define WSAID_WSASENDMSG {0xa441e712,0x754f,0x43ca,{0x84,0xa7,0x0d,0xee,0x44,0xcf,0x60,0x6d}} +# endif +#endif #endif // sockaddr_in6 size changed between old and new SDK @@ -185,6 +216,10 @@ public: QSocketNotifier *readNotifier, *writeNotifier, *exceptNotifier; +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) + LPFN_WSASENDMSG sendmsg; + LPFN_WSARECVMSG recvmsg; +# endif enum ErrorString { NonBlockingInitFailedErrorString, BroadcastingInitFailedErrorString, diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 0e04096296..37651dcbc3 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -847,19 +847,29 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize, QIpPacketHeader *header, QAbstractSocketEngine::PacketHeaderOptions options) { + struct msghdr msg; + struct iovec vec; qt_sockaddr aa; + char c; + memset(&msg, 0, sizeof(msg)); memset(&aa, 0, sizeof(aa)); - QT_SOCKLEN_T sz; - sz = sizeof(aa); - ssize_t recvFromResult = 0; + // we need to receive at least one byte, even if our user isn't interested in it + vec.iov_base = maxSize ? data : &c; + vec.iov_len = maxSize ? maxSize : 1; + msg.msg_iov = &vec; + msg.msg_iovlen = 1; + if (options & QAbstractSocketEngine::WantDatagramSender) { + msg.msg_name = &aa; + msg.msg_namelen = sizeof(aa); + } + + ssize_t recvResult = 0; do { - char c; - recvFromResult = ::recvfrom(socketDescriptor, maxSize ? data : &c, maxSize ? maxSize : 1, - 0, &aa.a, &sz); - } while (recvFromResult == -1 && errno == EINTR); + recvResult = ::recvmsg(socketDescriptor, &msg, 0); + } while (recvResult == -1 && errno == EINTR); - if (recvFromResult == -1) { + if (recvResult == -1) { setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString); if (header) header->clear(); @@ -870,46 +880,50 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %lli, %s, %i) == %lli", - data, qt_prettyDebug(data, qMin(recvFromResult, ssize_t(16)), recvFromResult).data(), maxSize, + data, qt_prettyDebug(data, qMin(recvResult, ssize_t(16)), recvResult).data(), maxSize, address ? address->toString().toLatin1().constData() : "(nil)", - port ? *port : 0, (qint64) recvFromResult); + port ? *port : 0, (qint64) recvResult); #endif - return qint64(maxSize ? recvFromResult : recvFromResult == -1 ? -1 : 0); + return qint64(maxSize ? recvResult : recvResult == -1 ? -1 : 0); } qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len, const QIpPacketHeader &header) { - struct sockaddr_in sockAddrIPv4; - struct sockaddr *sockAddrPtr = 0; - QT_SOCKLEN_T sockAddrSize = 0; + struct msghdr msg; + struct iovec vec; + qt_sockaddr aa; - struct sockaddr_in6 sockAddrIPv6; - const QHostAddress &host = header.destinationAddress; - quint16 port = header.destinationPort; - if (host.protocol() == QAbstractSocket::IPv6Protocol + memset(&msg, 0, sizeof(msg)); + memset(&aa, 0, sizeof(aa)); + vec.iov_base = const_cast(data); + vec.iov_len = len; + msg.msg_iov = &vec; + msg.msg_iovlen = 1; + msg.msg_name = &aa.a; + + if (header.destinationAddress.protocol() == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) { - memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6)); - sockAddrIPv6.sin6_family = AF_INET6; - sockAddrIPv6.sin6_port = htons(port); - sockAddrIPv6.sin6_scope_id = makeScopeId(host); - - Q_IPV6ADDR tmp = host.toIPv6Address(); - memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp)); - sockAddrSize = sizeof(sockAddrIPv6); - sockAddrPtr = (struct sockaddr *)&sockAddrIPv6; - } else if (host.protocol() == QAbstractSocket::IPv4Protocol) { - memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4)); - sockAddrIPv4.sin_family = AF_INET; - sockAddrIPv4.sin_port = htons(port); - sockAddrIPv4.sin_addr.s_addr = htonl(host.toIPv4Address()); - sockAddrSize = sizeof(sockAddrIPv4); - sockAddrPtr = (struct sockaddr *)&sockAddrIPv4; + aa.a6.sin6_family = AF_INET6; + aa.a6.sin6_port = htons(header.destinationPort); + aa.a6.sin6_scope_id = makeScopeId(header.destinationAddress); + + Q_IPV6ADDR tmp = header.destinationAddress.toIPv6Address(); + memcpy(&aa.a6.sin6_addr, &tmp, sizeof(tmp)); + msg.msg_namelen = sizeof(aa.a6); + } else if (header.destinationAddress.protocol() == QAbstractSocket::IPv4Protocol) { + aa.a4.sin_family = AF_INET; + aa.a4.sin_port = htons(header.destinationPort); + aa.a4.sin_addr.s_addr = htonl(header.destinationAddress.toIPv4Address()); + msg.msg_namelen = sizeof(aa.a4); + } else { + // Don't know what IP type this is, let's hope it sends + msg.msg_name = 0; + msg.msg_namelen = 0; } - ssize_t sentBytes = qt_safe_sendto(socketDescriptor, data, len, - 0, sockAddrPtr, sockAddrSize); + ssize_t sentBytes = qt_safe_sendmsg(socketDescriptor, &msg, 0); if (sentBytes < 0) { switch (errno) { diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index ed376eed95..9171ee36e0 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -420,6 +420,20 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc WS_ERROR_DEBUG(err); } } + + // get the pointer to sendmsg and recvmsg + DWORD bytesReturned; + GUID recvmsgguid = WSAID_WSARECVMSG; + if (WSAIoctl(socketDescriptor, SIO_GET_EXTENSION_FUNCTION_POINTER, + &recvmsgguid, sizeof(recvmsgguid), + &recvmsg, sizeof(recvmsg), &bytesReturned, NULL, NULL) == SOCKET_ERROR) + recvmsg = 0; + + GUID sendmsgguid = WSAID_WSASENDMSG; + if (WSAIoctl(socketDescriptor, SIO_GET_EXTENSION_FUNCTION_POINTER, + &sendmsgguid, sizeof(sendmsgguid), + &sendmsg, sizeof(sendmsg), &bytesReturned, NULL, NULL) == SOCKET_ERROR) + sendmsg = 0; #endif socketDescriptor = socket; @@ -1196,33 +1210,39 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const return ret; } +#ifdef Q_OS_WINCE +// Windows CE has no support for sendmsg or recvmsg. We set it to null here to simplify the code below. +static int (*const recvmsg)(...) = 0; +static int (*const sendmsg)(...) = 0; +#endif qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxLength, QIpPacketHeader *header, QAbstractSocketEngine::PacketHeaderOptions options) { - qint64 ret = 0; - + WSAMSG msg; + WSABUF buf; qt_sockaddr aa; + char c; + memset(&msg, 0, sizeof(msg)); memset(&aa, 0, sizeof(aa)); - QT_SOCKLEN_T sz; - sz = sizeof(aa); - WSABUF buf; - buf.buf = data; - buf.len = maxLength; -#if !defined(Q_OS_WINCE) - buf.buf = data; - buf.len = maxLength; -#else - char tmpChar; - buf.buf = data ? data : &tmpChar; - buf.len = maxLength; -#endif + // we need to receive at least one byte, even if our user isn't interested in it + buf.buf = maxLength ? data : &c; + buf.len = maxLength ? maxLength : 1; + msg.lpBuffers = &buf; + msg.dwBufferCount = 1; + msg.name = reinterpret_cast(&aa); + msg.namelen = sizeof(aa); DWORD flags = 0; DWORD bytesRead = 0; - int wsaRet = ::WSARecvFrom(socketDescriptor, &buf, 1, &bytesRead, &flags, &aa.a, &sz,0,0); - if (wsaRet == SOCKET_ERROR) { + qint64 ret; + + if (recvmsg) + ret = recvmsg(socketDescriptor, &msg, &bytesRead, 0,0); + else + ret = ::WSARecvFrom(socketDescriptor, &buf, 1, &bytesRead, &flags, msg.name, &msg.namelen,0,0); + if (ret == SOCKET_ERROR) { int err = WSAGetLastError(); if (err == WSAEMSGSIZE) { // it is ok the buffer was to small if bytesRead is larger than @@ -1256,26 +1276,34 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxL qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len, const QIpPacketHeader &header) { - qint64 ret = -1; - struct sockaddr_in sockAddrIPv4; - qt_sockaddr_in6 sockAddrIPv6; - struct sockaddr *sockAddrPtr = 0; - QT_SOCKLEN_T sockAddrSize = 0; - - setPortAndAddress(&sockAddrIPv4, &sockAddrIPv6, header.destinationPort, - header.destinationAddress, &sockAddrPtr, &sockAddrSize); - + WSAMSG msg; WSABUF buf; + qt_sockaddr aa; + + memset(&msg, 0, sizeof(msg)); + memset(&aa, 0, sizeof(aa)); #if !defined(Q_OS_WINCE) buf.buf = len ? (char*)data : 0; #else char tmp; buf.buf = len ? (char*)data : &tmp; #endif + msg.lpBuffers = &buf; + msg.dwBufferCount = 1; buf.len = len; + + setPortAndAddress(&aa.a4, &aa.a6, header.destinationPort, + header.destinationAddress, &msg.name, &msg.namelen); + DWORD flags = 0; DWORD bytesSent = 0; - if (::WSASendTo(socketDescriptor, &buf, 1, &bytesSent, flags, sockAddrPtr, sockAddrSize, 0,0) == SOCKET_ERROR) { + qint64 ret = -1; + if (sendmsg) { + ret = sendmsg(socketDescriptor, &msg, flags, &bytesSent, 0,0); + } else { + ret = ::WSASendTo(socketDescriptor, &buf, 1, &bytesSent, flags, msg.name, msg.namelen, 0,0); + } + if (ret == SOCKET_ERROR) { int err = WSAGetLastError(); WS_ERROR_DEBUG(err); switch (err) { diff --git a/src/network/socket/qnet_unix_p.h b/src/network/socket/qnet_unix_p.h index a5a87fc7c1..9626c53711 100644 --- a/src/network/socket/qnet_unix_p.h +++ b/src/network/socket/qnet_unix_p.h @@ -173,8 +173,7 @@ static inline in_addr_t qt_safe_inet_addr(const char *cp) #endif } -// VxWorks' headers do not specify any const modifiers -static inline int qt_safe_sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *to, QT_SOCKLEN_T tolen) +static inline int qt_safe_sendmsg(int sockfd, const struct msghdr *msg, int flags) { #ifdef MSG_NOSIGNAL flags |= MSG_NOSIGNAL; @@ -183,11 +182,7 @@ static inline int qt_safe_sendto(int sockfd, const void *buf, size_t len, int fl #endif int ret; -#ifdef Q_OS_VXWORKS - EINTR_LOOP(ret, ::sendto(sockfd, (char *) buf, len, flags, (struct sockaddr *) to, tolen)); -#else - EINTR_LOOP(ret, ::sendto(sockfd, buf, len, flags, to, tolen)); -#endif + EINTR_LOOP(ret, ::sendmsg(sockfd, msg, flags)); return ret; } @@ -199,24 +194,6 @@ static inline int qt_safe_recvmsg(int sockfd, struct msghdr *msg, int flags) return ret; } -// VxWorks' headers do not specify any const modifiers -static inline int qt_safe_sendmsg(int sockfd, const struct msghdr *msg, int flags) -{ -#ifdef MSG_NOSIGNAL - flags |= MSG_NOSIGNAL; -#else - qt_ignore_sigpipe(); -#endif - - int ret; -#ifdef Q_OS_VXWORKS - EINTR_LOOP(ret, ::sendmsg(sockfd, (struct msghdr *) msg, flags); -#else - EINTR_LOOP(ret, ::sendmsg(sockfd, msg, flags)); -#endif - return ret; -} - QT_END_NAMESPACE #endif // QNET_UNIX_P_H -- cgit v1.2.3 From abe269bb72233b360bccbc8f54d3f13e8dc10b5a Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 10 Mar 2015 16:20:20 -0700 Subject: QNativeSocketEngine: add code to receive IP header data Change-Id: Iee8cbc07c4434ce9b560ffff13ca466263abcb1b Reviewed-by: Richard J. Moore Reviewed-by: Rafael Roquetto Reviewed-by: Andrew Knight --- src/network/socket/qabstractsocketengine_p.h | 12 +++- src/network/socket/qnativesocketengine.cpp | 19 ++++-- src/network/socket/qnativesocketengine_unix.cpp | 87 +++++++++++++++++++++++- src/network/socket/qnativesocketengine_win.cpp | 58 ++++++++++++++++ src/network/socket/qnativesocketengine_winrt.cpp | 6 +- 5 files changed, 169 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/network/socket/qabstractsocketengine_p.h b/src/network/socket/qabstractsocketengine_p.h index c485e80f5d..d2b5882d18 100644 --- a/src/network/socket/qabstractsocketengine_p.h +++ b/src/network/socket/qabstractsocketengine_p.h @@ -63,18 +63,22 @@ class QIpPacketHeader { public: QIpPacketHeader(const QHostAddress &dstAddr = QHostAddress(), quint16 port = 0) - : destinationAddress(dstAddr), destinationPort(port) + : destinationAddress(dstAddr), ifindex(0), hopLimit(-1), destinationPort(port) {} void clear() { senderAddress.clear(); destinationAddress.clear(); + ifindex = 0; + hopLimit = -1; } QHostAddress senderAddress; QHostAddress destinationAddress; + uint ifindex; + qint16 hopLimit; quint16 senderPort; quint16 destinationPort; }; @@ -114,12 +118,16 @@ public: KeepAliveOption, MulticastTtlOption, MulticastLoopbackOption, - TypeOfServiceOption + TypeOfServiceOption, + ReceivePacketInformation, + ReceiveHopLimit }; enum PacketHeaderOption { WantNone = 0, WantDatagramSender, + WantDatagramDestination, + WantDatagramHopLimit, WantAll = 0xff }; diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp index 901dab5473..c11b889220 100644 --- a/src/network/socket/qnativesocketengine.cpp +++ b/src/network/socket/qnativesocketengine.cpp @@ -413,13 +413,18 @@ bool QNativeSocketEngine::initialize(QAbstractSocket::SocketType socketType, QAb return false; } - // Set the broadcasting flag if it's a UDP socket. - if (socketType == QAbstractSocket::UdpSocket - && !setOption(BroadcastSocketOption, 1)) { - d->setError(QAbstractSocket::UnsupportedSocketOperationError, - QNativeSocketEnginePrivate::BroadcastingInitFailedErrorString); - close(); - return false; + if (socketType == QAbstractSocket::UdpSocket) { + // Set the broadcasting flag if it's a UDP socket. + if (!setOption(BroadcastSocketOption, 1)) { + d->setError(QAbstractSocket::UnsupportedSocketOperationError, + QNativeSocketEnginePrivate::BroadcastingInitFailedErrorString); + close(); + return false; + } + + // Set some extra flags that are interesting to us, but accept failure + setOption(ReceivePacketInformation, 1); + setOption(ReceiveHopLimit, 1); } diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 37651dcbc3..7e794e8c0f 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -49,6 +49,9 @@ #ifdef QT_LINUXBASE #include #endif +#ifdef Q_OS_BSD4 +#include +#endif #if defined QNATIVESOCKETENGINE_DEBUG #include @@ -202,6 +205,32 @@ static void convertToLevelAndOption(QNativeSocketEngine::SocketOption opt, n = IP_TOS; } break; + case QNativeSocketEngine::ReceivePacketInformation: + if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) { + level = IPPROTO_IPV6; + n = IPV6_RECVPKTINFO; + } else if (socketProtocol == QAbstractSocket::IPv4Protocol) { + level = IPPROTO_IP; +#ifdef IP_PKTINFO + n = IP_PKTINFO; +#elif defined(IP_RECVDSTADDR) + // variant found in QNX and FreeBSD; it will get us only the + // destination address, not the interface; we need IP_RECVIF for that. + n = IP_RECVDSTADDR; +#endif + } + break; + case QNativeSocketEngine::ReceiveHopLimit: + if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) { + level = IPPROTO_IPV6; + n = IPV6_RECVHOPLIMIT; + } else if (socketProtocol == QAbstractSocket::IPv4Protocol) { +#ifdef IP_RECVTTL // IP_RECVTTL is a non-standard extension supported on some OS + level = IPPROTO_IP; + n = IP_RECVTTL; +#endif + } + break; } } @@ -285,7 +314,7 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co QT_SOCKOPTLEN_T len = sizeof(v); convertToLevelAndOption(opt, socketProtocol, level, n); - if (::getsockopt(socketDescriptor, level, n, (char *) &v, &len) != -1) + if (n != -1 && ::getsockopt(socketDescriptor, level, n, (char *) &v, &len) != -1) return v; return -1; @@ -847,6 +876,9 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize, QIpPacketHeader *header, QAbstractSocketEngine::PacketHeaderOptions options) { + // we use quintptr to force the alignment + quintptr cbuf[(CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int)) + sizeof(quintptr) - 1) / sizeof(quintptr)]; + struct msghdr msg; struct iovec vec; qt_sockaddr aa; @@ -863,6 +895,10 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS msg.msg_name = &aa; msg.msg_namelen = sizeof(aa); } + if (options & (QAbstractSocketEngine::WantDatagramHopLimit | QAbstractSocketEngine::WantDatagramDestination)) { + msg.msg_control = cbuf; + msg.msg_controllen = sizeof(cbuf); + } ssize_t recvResult = 0; do { @@ -876,6 +912,55 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS } else if (options != QAbstractSocketEngine::WantNone) { Q_ASSERT(header); qt_socket_getPortAndAddress(&aa, &header->senderPort, &header->senderAddress); + header->destinationPort = localPort; + + // parse the ancillary data + struct cmsghdr *cmsgptr; + for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; + cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) { + if (cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_PKTINFO + && cmsgptr->cmsg_len >= CMSG_LEN(sizeof(in6_pktinfo))) { + in6_pktinfo *info = reinterpret_cast(CMSG_DATA(cmsgptr)); + + header->destinationAddress.setAddress(reinterpret_cast(&info->ipi6_addr)); + header->ifindex = info->ipi6_ifindex; + if (header->ifindex) + header->destinationAddress.setScopeId(QString::number(info->ipi6_ifindex)); + } + +#ifdef IP_PKTINFO + if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_PKTINFO + && cmsgptr->cmsg_len >= CMSG_LEN(sizeof(in_pktinfo))) { + in_pktinfo *info = reinterpret_cast(CMSG_DATA(cmsgptr)); + + header->destinationAddress.setAddress(ntohl(info->ipi_addr.s_addr)); + header->ifindex = info->ipi_ifindex; + } +#else +# ifdef IP_RECVDSTADDR + if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_RECVDSTADDR + && cmsgptr->cmsg_len >= CMSG_LEN(sizeof(in_addr))) { + in_addr *addr = reinterpret_cast(CMSG_DATA(cmsgptr)); + + header->destinationAddress.setAddress(ntohl(addr->s_addr)); + } +# endif +# if defined(IP_RECVIF) && defined(Q_OS_BSD4) + if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_RECVIF + && cmsgptr->cmsg_len >= CMSG_LEN(sizeof(sockaddr_dl))) { + sockaddr_dl *sdl = reinterpret_cast(CMSG_DATA(cmsgptr)); + + header->ifindex = LLINDEX(sdl); + } +# endif +#endif + + if (cmsgptr->cmsg_len == CMSG_LEN(sizeof(int)) + && ((cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_HOPLIMIT) + || (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_TTL))) { + header->hopLimit = *reinterpret_cast(CMSG_DATA(cmsgptr)); + } + } } #if defined (QNATIVESOCKETENGINE_DEBUG) diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 9171ee36e0..2e505d62f0 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -59,6 +59,9 @@ QT_BEGIN_NAMESPACE #ifndef IPV6_V6ONLY #define IPV6_V6ONLY 27 #endif +#ifndef IP_HOPLIMIT +#define IP_HOPLIMIT 21 // Receive packet hop limit. +#endif #if defined(QNATIVESOCKETENGINE_DEBUG) @@ -252,6 +255,24 @@ static void convertToLevelAndOption(QNativeSocketEngine::SocketOption opt, n = IP_MULTICAST_LOOP; } break; + case QNativeSocketEngine::ReceivePacketInformation: + if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) { + level = IPPROTO_IPV6; + n = IPV6_PKTINFO; + } else if (socketProtocol == QAbstractSocket::IPv4Protocol) { + level = IPPROTO_IP; + n = IP_PKTINFO; + } + break; + case QNativeSocketEngine::ReceiveHopLimit: + if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) { + level = IPPROTO_IPV6; + n = IPV6_HOPLIMIT; + } else if (socketProtocol == QAbstractSocket::IPv4Protocol) { + level = IPPROTO_IP; + n = IP_HOPLIMIT; + } + break; } } @@ -1219,6 +1240,10 @@ static int (*const sendmsg)(...) = 0; qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxLength, QIpPacketHeader *header, QAbstractSocketEngine::PacketHeaderOptions options) { + union { + char cbuf[WSA_CMSG_SPACE(sizeof(struct in6_pktinfo)) + WSA_CMSG_SPACE(sizeof(int))]; + WSACMSGHDR align; // only to ensure alignment + }; WSAMSG msg; WSABUF buf; qt_sockaddr aa; @@ -1233,6 +1258,10 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxL msg.dwBufferCount = 1; msg.name = reinterpret_cast(&aa); msg.namelen = sizeof(aa); + if (options & (QAbstractSocketEngine::WantDatagramHopLimit | QAbstractSocketEngine::WantDatagramDestination)) { + msg.Control.buf = cbuf; + msg.Control.len = sizeof(cbuf); + } DWORD flags = 0; DWORD bytesRead = 0; @@ -1261,6 +1290,35 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxL qt_socket_getPortAndAddress(socketDescriptor, &aa, &header->senderPort, &header->senderAddress); } + if (ret != -1 && recvmsg) { + // get the ancillary data + WSACMSGHDR *cmsgptr; + for (cmsgptr = WSA_CMSG_FIRSTHDR(&msg); cmsgptr != NULL; + cmsgptr = WSA_CMSG_NXTHDR(&msg, cmsgptr)) { + if (cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_PKTINFO + && cmsgptr->cmsg_len >= WSA_CMSG_LEN(sizeof(in6_pktinfo))) { + in6_pktinfo *info = reinterpret_cast(WSA_CMSG_DATA(cmsgptr)); + QHostAddress target(reinterpret_cast(&info->ipi6_addr)); + if (info->ipi6_ifindex) + target.setScopeId(QString::number(info->ipi6_ifindex)); + } + if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_PKTINFO + && cmsgptr->cmsg_len >= WSA_CMSG_LEN(sizeof(in_pktinfo))) { + in_pktinfo *info = reinterpret_cast(WSA_CMSG_DATA(cmsgptr)); + u_long addr; + WSANtohl(socketDescriptor, info->ipi_addr.s_addr, &addr); + QHostAddress target(addr); + if (info->ipi_ifindex) + target.setScopeId(QString::number(info->ipi_ifindex)); + } + + if (cmsgptr->cmsg_len == WSA_CMSG_LEN(sizeof(int)) + && ((cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_HOPLIMIT) + || (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_TTL))) { + header->hopLimit = *reinterpret_cast(WSA_CMSG_DATA(cmsgptr)); + } + } + } #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %li, %s, %i) == %li", diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index 4a92ca5a95..025e3e5017 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -539,7 +539,7 @@ qint64 QNativeSocketEngine::write(const char *data, qint64 len) } qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QIpPacketHeader *header, - PacketHeaderOptions options) + PacketHeaderOptions) { Q_D(QNativeSocketEngine); if (d->socketType != QAbstractSocket::UdpSocket || d->pendingDatagrams.isEmpty()) { @@ -577,13 +577,13 @@ qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 len, const QI HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(), &hostNameFactory); RETURN_IF_FAILED("Could not obtain hostname factory", return -1); - const QString addressString = addr.toString(); + const QString addressString = header.destinationAddress.toString(); HStringReference hostNameRef(reinterpret_cast(addressString.utf16())); hostNameFactory->CreateHostName(hostNameRef.Get(), &remoteHost); ComPtr> streamOperation; ComPtr stream; - const QString portString = QString::number(port); + const QString portString = QString::number(header.destinationPort); HStringReference portRef(reinterpret_cast(portString.utf16())); hr = d->udpSocket()->GetOutputStreamAsync(remoteHost.Get(), portRef.Get(), &streamOperation); RETURN_IF_FAILED("Failed to get output stream to socket", return -1); -- cgit v1.2.3 From 28dfc33c3a10c7bc195bbca179891118b0e2f14d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 10 Mar 2015 17:03:42 -0700 Subject: QNativeSocketEngine: add code to send extra IP header data Change-Id: Iee8cbc07c4434ce9b560ffff13ca48c053bd88ed Reviewed-by: Richard J. Moore --- src/network/socket/qnativesocketengine_unix.cpp | 58 +++++++++++++++++++++++++ src/network/socket/qnativesocketengine_win.cpp | 58 +++++++++++++++++++++++++ 2 files changed, 116 insertions(+) (limited to 'src') diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 7e794e8c0f..f2fac66cd6 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -975,6 +975,10 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len, const QIpPacketHeader &header) { + // we use quintptr to force the alignment + quintptr cbuf[(CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int)) + sizeof(quintptr) - 1) / sizeof(quintptr)]; + + struct cmsghdr *cmsgptr = reinterpret_cast(cbuf); struct msghdr msg; struct iovec vec; qt_sockaddr aa; @@ -986,6 +990,7 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l msg.msg_iov = &vec; msg.msg_iovlen = 1; msg.msg_name = &aa.a; + msg.msg_control = &cbuf; if (header.destinationAddress.protocol() == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::IPv6Protocol @@ -997,17 +1002,70 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l Q_IPV6ADDR tmp = header.destinationAddress.toIPv6Address(); memcpy(&aa.a6.sin6_addr, &tmp, sizeof(tmp)); msg.msg_namelen = sizeof(aa.a6); + + if (header.hopLimit != -1) { + msg.msg_controllen += CMSG_SPACE(sizeof(int)); + cmsgptr->cmsg_len = CMSG_LEN(sizeof(int)); + cmsgptr->cmsg_level = IPPROTO_IPV6; + cmsgptr->cmsg_type = IPV6_HOPLIMIT; + memcpy(CMSG_DATA(cmsgptr), &header.hopLimit, sizeof(int)); + cmsgptr = reinterpret_cast(reinterpret_cast(cmsgptr) + CMSG_SPACE(sizeof(int))); + } + if (header.ifindex != 0 || !header.senderAddress.isNull()) { + struct in6_pktinfo *data = reinterpret_cast(CMSG_DATA(cmsgptr)); + memset(data, 0, sizeof(*data)); + msg.msg_controllen += CMSG_SPACE(sizeof(*data)); + cmsgptr->cmsg_len = CMSG_LEN(sizeof(*data)); + cmsgptr->cmsg_level = IPPROTO_IPV6; + cmsgptr->cmsg_type = IPV6_PKTINFO; + data->ipi6_ifindex = header.ifindex; + + tmp = header.senderAddress.toIPv6Address(); + memcpy(&data->ipi6_addr, &tmp, sizeof(tmp)); + cmsgptr = reinterpret_cast(reinterpret_cast(cmsgptr) + CMSG_SPACE(sizeof(*data))); + } } else if (header.destinationAddress.protocol() == QAbstractSocket::IPv4Protocol) { aa.a4.sin_family = AF_INET; aa.a4.sin_port = htons(header.destinationPort); aa.a4.sin_addr.s_addr = htonl(header.destinationAddress.toIPv4Address()); msg.msg_namelen = sizeof(aa.a4); + + if (header.hopLimit != -1) { + msg.msg_controllen += CMSG_SPACE(sizeof(int)); + cmsgptr->cmsg_len = CMSG_LEN(sizeof(int)); + cmsgptr->cmsg_level = IPPROTO_IP; + cmsgptr->cmsg_type = IP_TTL; + memcpy(CMSG_DATA(cmsgptr), &header.hopLimit, sizeof(int)); + cmsgptr = reinterpret_cast(reinterpret_cast(cmsgptr) + CMSG_SPACE(sizeof(int))); + } + +#if defined(IP_PKTINFO) || defined(IP_SENDSRCADDR) + if (header.ifindex != 0 || !header.senderAddress.isNull()) { +# ifdef IP_PKTINFO + struct in_pktinfo *data = reinterpret_cast(CMSG_DATA(cmsgptr)); + memset(data, 0, sizeof(*data)); + cmsgptr->cmsg_type = IP_PKTINFO; + data->ipi_ifindex = header.ifindex; + data->ipi_addr.s_addr = htonl(header.senderAddress.toIPv4Address()); +# elif defined(IP_SENDSRCADDR) + struct in_addr *data = reinterpret_cast(CMSG_DATA(cmsgptr)); + cmsgptr->cmsg_type = IP_SENDSRCADDR; + addr->s_addr = htonl(header.senderAddress.toIPv4Address()); +# endif + cmsgptr->cmsg_level = IPPROTO_IP; + msg.msg_controllen += CMSG_SPACE(sizeof(*data)); + cmsgptr->cmsg_len = CMSG_LEN(sizeof(*data)); + cmsgptr = reinterpret_cast(reinterpret_cast(cmsgptr) + CMSG_SPACE(sizeof(*data))); + } +#endif } else { // Don't know what IP type this is, let's hope it sends msg.msg_name = 0; msg.msg_namelen = 0; } + if (msg.msg_controllen == 0) + msg.msg_control = 0; ssize_t sentBytes = qt_safe_sendmsg(socketDescriptor, &msg, 0); if (sentBytes < 0) { diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 2e505d62f0..ebaa3f0c66 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -1334,6 +1334,11 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxL qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len, const QIpPacketHeader &header) { + union { + char cbuf[WSA_CMSG_SPACE(sizeof(struct in6_pktinfo)) + WSA_CMSG_SPACE(sizeof(int))]; + WSACMSGHDR align; // ensures alignment + }; + WSACMSGHDR *cmsgptr = &align; WSAMSG msg; WSABUF buf; qt_sockaddr aa; @@ -1353,6 +1358,59 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l setPortAndAddress(&aa.a4, &aa.a6, header.destinationPort, header.destinationAddress, &msg.name, &msg.namelen); + if (msg.namelen == sizeof(aa.a6)) { + // sending IPv6 + if (header.hopLimit != -1) { + msg.Control.len += WSA_CMSG_SPACE(sizeof(int)); + cmsgptr->cmsg_len = WSA_CMSG_LEN(sizeof(int)); + cmsgptr->cmsg_level = IPPROTO_IPV6; + cmsgptr->cmsg_type = IPV6_HOPLIMIT; + memcpy(WSA_CMSG_DATA(cmsgptr), &header.hopLimit, sizeof(int)); + cmsgptr = reinterpret_cast(reinterpret_cast(cmsgptr) + + WSA_CMSG_SPACE(sizeof(int))); + } + if (header.ifindex != 0 || !header.senderAddress.isNull()) { + struct in6_pktinfo *data = reinterpret_cast(WSA_CMSG_DATA(cmsgptr)); + memset(data, 0, sizeof(*data)); + msg.Control.len += WSA_CMSG_SPACE(sizeof(*data)); + cmsgptr->cmsg_len = WSA_CMSG_LEN(sizeof(*data)); + cmsgptr->cmsg_level = IPPROTO_IPV6; + cmsgptr->cmsg_type = IPV6_PKTINFO; + data->ipi6_ifindex = header.ifindex; + + Q_IPV6ADDR tmp = header.senderAddress.toIPv6Address(); + memcpy(&data->ipi6_addr, &tmp, sizeof(tmp)); + cmsgptr = reinterpret_cast(reinterpret_cast(cmsgptr) + + WSA_CMSG_SPACE(sizeof(*data))); + } + } else { + // sending IPv4 + if (header.hopLimit != -1) { + msg.Control.len += WSA_CMSG_SPACE(sizeof(int)); + cmsgptr->cmsg_len = WSA_CMSG_LEN(sizeof(int)); + cmsgptr->cmsg_level = IPPROTO_IP; + cmsgptr->cmsg_type = IP_TTL; + memcpy(WSA_CMSG_DATA(cmsgptr), &header.hopLimit, sizeof(int)); + cmsgptr = reinterpret_cast(reinterpret_cast(cmsgptr) + + WSA_CMSG_SPACE(sizeof(int))); + } + if (header.ifindex != 0 || !header.senderAddress.isNull()) { + struct in_pktinfo *data = reinterpret_cast(WSA_CMSG_DATA(cmsgptr)); + memset(data, 0, sizeof(*data)); + msg.Control.len += WSA_CMSG_SPACE(sizeof(*data)); + cmsgptr->cmsg_len = WSA_CMSG_LEN(sizeof(*data)); + cmsgptr->cmsg_level = IPPROTO_IP; + cmsgptr->cmsg_type = IP_PKTINFO; + data->ipi_ifindex = header.ifindex; + WSAHtonl(socketDescriptor, header.senderAddress.toIPv4Address(), &data->ipi_addr.s_addr); + cmsgptr = reinterpret_cast(reinterpret_cast(cmsgptr) + + WSA_CMSG_SPACE(sizeof(*data))); + } + } + + if (msg.Control.len != 0) + msg.Control.buf = cbuf; + DWORD flags = 0; DWORD bytesSent = 0; qint64 ret = -1; -- cgit v1.2.3 From f35b8c004e61dea8ee4ee15a8943ad2b0a0c97d0 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 11 Mar 2015 18:41:23 -0700 Subject: QNativeSocketEngine Windows: simplify the conversion to struct sockaddr We have qt_sockaddr, which has enough storage for our needs and is a union of all the types. We don't need them to be separate like that. Change-Id: Iee8cbc07c4434ce9b560ffff13ca9cb960ccf1d7 Reviewed-by: Richard J. Moore --- src/network/socket/qnativesocketengine_p.h | 3 +- src/network/socket/qnativesocketengine_win.cpp | 52 ++++++++++---------------- 2 files changed, 20 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h index 29063b3a85..c7e545df92 100644 --- a/src/network/socket/qnativesocketengine_p.h +++ b/src/network/socket/qnativesocketengine_p.h @@ -285,8 +285,7 @@ public: int nativeSelect(int timeout, bool checkRead, bool checkWrite, bool *selectForRead, bool *selectForWrite) const; #ifdef Q_OS_WIN - void setPortAndAddress(sockaddr_in * sockAddrIPv4, qt_sockaddr_in6 * sockAddrIPv6, - quint16 port, const QHostAddress & address, sockaddr ** sockAddrPtr, QT_SOCKLEN_T *sockAddrSize); + void setPortAndAddress(quint16 port, const QHostAddress &address, qt_sockaddr *aa, QT_SOCKLEN_T *sockAddrSize); #endif void nativeClose(); diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index ebaa3f0c66..9dba6693c8 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -280,33 +280,25 @@ static void convertToLevelAndOption(QNativeSocketEngine::SocketOption opt, Sets the port and address to a sockaddr. Requires that sa point to the IPv6 struct if the address is IPv6. */ -void QNativeSocketEnginePrivate::setPortAndAddress(sockaddr_in * sockAddrIPv4, qt_sockaddr_in6 * sockAddrIPv6, - quint16 port, const QHostAddress & address, sockaddr ** sockAddrPtr, QT_SOCKLEN_T *sockAddrSize) +void QNativeSocketEnginePrivate::setPortAndAddress(quint16 port, const QHostAddress &address, qt_sockaddr *aa, QT_SOCKLEN_T *sockAddrSize) { if (address.protocol() == QAbstractSocket::IPv6Protocol || address.protocol() == QAbstractSocket::AnyIPProtocol || socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) { - memset(sockAddrIPv6, 0, sizeof(qt_sockaddr_in6)); - sockAddrIPv6->sin6_family = AF_INET6; - sockAddrIPv6->sin6_scope_id = address.scopeId().toUInt(); - WSAHtons(socketDescriptor, port, &(sockAddrIPv6->sin6_port)); + memset(&aa->a6, 0, sizeof(qt_sockaddr_in6)); + aa->a6.sin6_family = AF_INET6; + aa->a6.sin6_scope_id = address.scopeId().toUInt(); + WSAHtons(socketDescriptor, port, &aa->a6.sin6_port); Q_IPV6ADDR tmp = address.toIPv6Address(); - memcpy(&(sockAddrIPv6->sin6_addr.qt_s6_addr), &tmp, sizeof(tmp)); + memcpy(&aa->a6.sin6_addr, &tmp, sizeof(tmp)); *sockAddrSize = sizeof(qt_sockaddr_in6); - *sockAddrPtr = (struct sockaddr *) sockAddrIPv6; - } else - - if (address.protocol() == QAbstractSocket::IPv4Protocol - || address.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) { - memset(sockAddrIPv4, 0, sizeof(sockaddr_in)); - sockAddrIPv4->sin_family = AF_INET; - WSAHtons(socketDescriptor, port, &(sockAddrIPv4->sin_port)); - WSAHtonl(socketDescriptor, address.toIPv4Address(), &(sockAddrIPv4->sin_addr.s_addr)); - *sockAddrSize = sizeof(sockaddr_in); - *sockAddrPtr = (struct sockaddr *) sockAddrIPv4; } else { - // unreachable + memset(&aa->a, 0, sizeof(sockaddr_in)); + aa->a4.sin_family = AF_INET; + WSAHtons(socketDescriptor, port, &aa->a4.sin_port); + WSAHtonl(socketDescriptor, address.toIPv4Address(), &aa->a4.sin_addr.s_addr); + *sockAddrSize = sizeof(sockaddr_in); } } @@ -646,12 +638,10 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &address, quin qDebug("QNativeSocketEnginePrivate::nativeConnect() to %s :: %i", address.toString().toLatin1().constData(), port); #endif - struct sockaddr_in sockAddrIPv4; - qt_sockaddr_in6 sockAddrIPv6; - struct sockaddr *sockAddrPtr = 0; + qt_sockaddr aa; QT_SOCKLEN_T sockAddrSize = 0; - setPortAndAddress(&sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize); + setPortAndAddress(port, address, &aa, &sockAddrSize); if ((socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) && address.toIPv4Address()) { //IPV6_V6ONLY option must be cleared to connect to a V4 mapped address @@ -662,7 +652,7 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &address, quin } forever { - int connectResult = ::WSAConnect(socketDescriptor, sockAddrPtr, sockAddrSize, 0,0,0,0); + int connectResult = ::WSAConnect(socketDescriptor, &aa.a, sockAddrSize, 0,0,0,0); if (connectResult == SOCKET_ERROR) { int err = WSAGetLastError(); WS_ERROR_DEBUG(err); @@ -816,15 +806,11 @@ bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &a, quint16 port) break; } - struct sockaddr_in sockAddrIPv4; - qt_sockaddr_in6 sockAddrIPv6; - struct sockaddr *sockAddrPtr = 0; + qt_sockaddr aa; QT_SOCKLEN_T sockAddrSize = 0; + setPortAndAddress(port, address, &aa, &sockAddrSize); - setPortAndAddress(&sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize); - - - int bindResult = ::bind(socketDescriptor, sockAddrPtr, sockAddrSize); + int bindResult = ::bind(socketDescriptor, &aa.a, sockAddrSize); if (bindResult == SOCKET_ERROR) { int err = WSAGetLastError(); WS_ERROR_DEBUG(err); @@ -1353,10 +1339,10 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l #endif msg.lpBuffers = &buf; msg.dwBufferCount = 1; + msg.name = &aa.a; buf.len = len; - setPortAndAddress(&aa.a4, &aa.a6, header.destinationPort, - header.destinationAddress, &msg.name, &msg.namelen); + setPortAndAddress(header.destinationPort, header.destinationAddress, &aa, &msg.namelen); if (msg.namelen == sizeof(aa.a6)) { // sending IPv6 -- cgit v1.2.3 From 2c64e05d497b460f95cd39ea20c4e805b2c8c402 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 11 Mar 2015 20:13:16 -0700 Subject: QNativeSocketEngine Windows: bring bind() in line with Unix The IPv4+IPv6 dual stack code that has been in Qt since 5.0 has been giving test failures for tst_qudpsocket: some binds that shouldn't succeed do succeed. Instead, copy the core code from the Unix version so the two OSes will behave the same way. The one difference in behavior between Windows and Unix is that on Unix you can bind an IPv4 address to a multicast IP and on Windows you can't. So I left the "correction" that was in the original code, but I'm unsure if it is the right thing to do. Are people expecting to join the multicast group this way? Change-Id: Iee8cbc07c4434ce9b560ffff13caa1c3d5a7e8fd Reviewed-by: Richard J. Moore --- src/network/socket/qnativesocketengine_win.cpp | 44 +++++++++++--------------- 1 file changed, 19 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 9dba6693c8..aecae40a44 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -775,42 +775,36 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &address, quin bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &a, quint16 port) { QHostAddress address = a; - DWORD ipv6only = 0; - switch (address.protocol()) { - case QAbstractSocket::IPv6Protocol: - if (address.toIPv6Address()[0] == 0xff) { - // binding to a multicast address - address = QHostAddress(QHostAddress::AnyIPv6); - } - //This is default in current windows versions, it may change in future so set it explicitly - if (QSysInfo::windowsVersion() >= QSysInfo::WV_6_0) { - ipv6only = 1; - ipv6only = ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) ); - } - break; - case QAbstractSocket::IPv4Protocol: + if (address.protocol() == QAbstractSocket::IPv4Protocol) { if ((address.toIPv4Address() & 0xffff0000) == 0xefff0000) { // binding to a multicast address address = QHostAddress(QHostAddress::AnyIPv4); } - break; - case QAbstractSocket::AnyIPProtocol: - if (QSysInfo::windowsVersion() >= QSysInfo::WV_6_0) { - ipv6only = ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) ); - } else { - address = QHostAddress(QHostAddress::AnyIPv4); //xp/WS2003 and earlier don't support dual stack, so bind to IPv4 - socketProtocol = QAbstractSocket::IPv4Protocol; - } - break; - default: - break; } qt_sockaddr aa; QT_SOCKLEN_T sockAddrSize = 0; setPortAndAddress(port, address, &aa, &sockAddrSize); + if (aa.a.sa_family == AF_INET6) { + // The default may change in future, so set it explicitly + int ipv6only = 0; + if (address.protocol() == QAbstractSocket::IPv6Protocol) + ipv6only = 1; + ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) ); + } + + int bindResult = ::bind(socketDescriptor, &aa.a, sockAddrSize); + if (bindResult == SOCKET_ERROR && WSAGetLastError() == WSAEAFNOSUPPORT + && address.protocol() == QAbstractSocket::AnyIPProtocol) { + // retry with v4 + aa.a4.sin_family = AF_INET; + aa.a4.sin_port = htons(port); + aa.a4.sin_addr.s_addr = htonl(address.toIPv4Address()); + sockAddrSize = sizeof(aa.a4); + bindResult = ::bind(socketDescriptor, &aa.a, sockAddrSize); + } if (bindResult == SOCKET_ERROR) { int err = WSAGetLastError(); WS_ERROR_DEBUG(err); -- cgit v1.2.3 From 452924c6ffc9624062bfb83eda8499044cc4719f Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 11 Mar 2015 18:58:29 -0700 Subject: QNativeSocketEngine Unix: do the same as for Windows Change-Id: Iee8cbc07c4434ce9b560ffff13ca9d9858cf7111 Reviewed-by: Richard J. Moore --- src/network/socket/qnativesocketengine_p.h | 32 ++++++- src/network/socket/qnativesocketengine_unix.cpp | 110 +++++------------------- src/network/socket/qnativesocketengine_win.cpp | 32 ++----- 3 files changed, 57 insertions(+), 117 deletions(-) (limited to 'src') diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h index c7e545df92..966f44f774 100644 --- a/src/network/socket/qnativesocketengine_p.h +++ b/src/network/socket/qnativesocketengine_p.h @@ -284,14 +284,40 @@ public: int nativeSelect(int timeout, bool selectForRead) const; int nativeSelect(int timeout, bool checkRead, bool checkWrite, bool *selectForRead, bool *selectForWrite) const; -#ifdef Q_OS_WIN - void setPortAndAddress(quint16 port, const QHostAddress &address, qt_sockaddr *aa, QT_SOCKLEN_T *sockAddrSize); -#endif void nativeClose(); bool checkProxy(const QHostAddress &address); bool fetchConnectionParameters(); + + static uint scopeIdFromString(const QString &scopeid); + + /*! \internal + Sets \a address and \a port in the \a aa sockaddr structure and the size in \a sockAddrSize. + The address \a is converted to IPv6 if the current socket protocol is also IPv6. + */ + void setPortAndAddress(quint16 port, const QHostAddress &address, qt_sockaddr *aa, QT_SOCKLEN_T *sockAddrSize) + { + if (address.protocol() == QAbstractSocket::IPv6Protocol + || address.protocol() == QAbstractSocket::AnyIPProtocol + || socketProtocol == QAbstractSocket::IPv6Protocol + || socketProtocol == QAbstractSocket::AnyIPProtocol) { + memset(&aa->a6, 0, sizeof(qt_sockaddr_in6)); + aa->a6.sin6_family = AF_INET6; + aa->a6.sin6_scope_id = scopeIdFromString(address.scopeId()); + aa->a6.sin6_port = htons(port); + Q_IPV6ADDR tmp = address.toIPv6Address(); + memcpy(&aa->a6.sin6_addr, &tmp, sizeof(tmp)); + *sockAddrSize = sizeof(qt_sockaddr_in6); + } else { + memset(&aa->a, 0, sizeof(sockaddr_in)); + aa->a4.sin_family = AF_INET; + aa->a4.sin_port = htons(port); + aa->a4.sin_addr.s_addr = htonl(address.toIPv4Address()); + *sockAddrSize = sizeof(sockaddr_in); + } + } + }; QT_END_NAMESPACE diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index f2fac66cd6..0e14c175c5 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -131,9 +131,9 @@ static inline void qt_socket_getPortAndAddress(const qt_sockaddr *s, quint16 *po } } -static inline uint makeScopeId(const QHostAddress &addr) +// inline on purpose +inline uint QNativeSocketEnginePrivate::scopeIdFromString(const QString &scopeid) { - QString scopeid = addr.scopeId(); if (scopeid.isEmpty()) return 0; @@ -389,37 +389,11 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 qDebug() << "QNativeSocketEnginePrivate::nativeConnect() " << socketDescriptor; #endif - struct sockaddr_in sockAddrIPv4; - struct sockaddr *sockAddrPtr = 0; - QT_SOCKLEN_T sockAddrSize = 0; - - struct sockaddr_in6 sockAddrIPv6; - - if (addr.protocol() == QAbstractSocket::IPv6Protocol) { - memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6)); - sockAddrIPv6.sin6_family = AF_INET6; - sockAddrIPv6.sin6_port = htons(port); - sockAddrIPv6.sin6_scope_id = makeScopeId(addr); - - Q_IPV6ADDR ip6 = addr.toIPv6Address(); - memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &ip6, sizeof(ip6)); - - sockAddrSize = sizeof(sockAddrIPv6); - sockAddrPtr = (struct sockaddr *) &sockAddrIPv6; - } else - if (addr.protocol() == QAbstractSocket::IPv4Protocol) { - memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4)); - sockAddrIPv4.sin_family = AF_INET; - sockAddrIPv4.sin_port = htons(port); - sockAddrIPv4.sin_addr.s_addr = htonl(addr.toIPv4Address()); - - sockAddrSize = sizeof(sockAddrIPv4); - sockAddrPtr = (struct sockaddr *) &sockAddrIPv4; - } else { - // unreachable - } + qt_sockaddr aa; + QT_SOCKLEN_T sockAddrSize; + setPortAndAddress(port, addr, &aa, &sockAddrSize); - int connectResult = qt_safe_connect(socketDescriptor, sockAddrPtr, sockAddrSize); + int connectResult = qt_safe_connect(socketDescriptor, &aa.a, sockAddrSize); #if defined (QNATIVESOCKETENGINE_DEBUG) int ecopy = errno; #endif @@ -491,51 +465,28 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 port) { - struct sockaddr_in sockAddrIPv4; - struct sockaddr *sockAddrPtr = 0; - QT_SOCKLEN_T sockAddrSize = 0; - - - struct sockaddr_in6 sockAddrIPv6; + qt_sockaddr aa; + QT_SOCKLEN_T sockAddrSize; + setPortAndAddress(port, address, &aa, &sockAddrSize); - if (address.protocol() == QAbstractSocket::IPv6Protocol || address.protocol() == QAbstractSocket::AnyIPProtocol) { #ifdef IPV6_V6ONLY + if (aa.a.sa_family == AF_INET6) { int ipv6only = 0; if (address.protocol() == QAbstractSocket::IPv6Protocol) ipv6only = 1; //default value of this socket option varies depending on unix variant (or system configuration on BSD), so always set it explicitly ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) ); + } #endif - memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6)); - sockAddrIPv6.sin6_family = AF_INET6; - sockAddrIPv6.sin6_port = htons(port); - sockAddrIPv6.sin6_scope_id = makeScopeId(address); - - Q_IPV6ADDR tmp = address.toIPv6Address(); - memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp)); - sockAddrSize = sizeof(sockAddrIPv6); - sockAddrPtr = (struct sockaddr *) &sockAddrIPv6; - } else - if (address.protocol() == QAbstractSocket::IPv4Protocol) { - memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4)); - sockAddrIPv4.sin_family = AF_INET; - sockAddrIPv4.sin_port = htons(port); - sockAddrIPv4.sin_addr.s_addr = htonl(address.toIPv4Address()); - sockAddrSize = sizeof(sockAddrIPv4); - sockAddrPtr = (struct sockaddr *) &sockAddrIPv4; - } else { - // unreachable - } - int bindResult = QT_SOCKET_BIND(socketDescriptor, sockAddrPtr, sockAddrSize); + int bindResult = QT_SOCKET_BIND(socketDescriptor, &aa.a, sockAddrSize); if (bindResult < 0 && errno == EAFNOSUPPORT && address.protocol() == QAbstractSocket::AnyIPProtocol) { - memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4)); - sockAddrIPv4.sin_family = AF_INET; - sockAddrIPv4.sin_port = htons(port); - sockAddrIPv4.sin_addr.s_addr = htonl(address.toIPv4Address()); - sockAddrSize = sizeof(sockAddrIPv4); - sockAddrPtr = (struct sockaddr *) &sockAddrIPv4; - bindResult = QT_SOCKET_BIND(socketDescriptor, sockAddrPtr, sockAddrSize); + // retry with v4 + aa.a4.sin_family = AF_INET; + aa.a4.sin_port = htons(port); + aa.a4.sin_addr.s_addr = htonl(address.toIPv4Address()); + sockAddrSize = sizeof(aa.a4); + bindResult = QT_SOCKET_BIND(socketDescriptor, &aa.a, sockAddrSize); } if (bindResult < 0) { @@ -992,17 +943,9 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l msg.msg_name = &aa.a; msg.msg_control = &cbuf; - if (header.destinationAddress.protocol() == QAbstractSocket::IPv6Protocol - || socketProtocol == QAbstractSocket::IPv6Protocol - || socketProtocol == QAbstractSocket::AnyIPProtocol) { - aa.a6.sin6_family = AF_INET6; - aa.a6.sin6_port = htons(header.destinationPort); - aa.a6.sin6_scope_id = makeScopeId(header.destinationAddress); - - Q_IPV6ADDR tmp = header.destinationAddress.toIPv6Address(); - memcpy(&aa.a6.sin6_addr, &tmp, sizeof(tmp)); - msg.msg_namelen = sizeof(aa.a6); + setPortAndAddress(header.destinationPort, header.destinationAddress, &aa, &msg.msg_namelen); + if (msg.msg_namelen == sizeof(aa.a6)) { if (header.hopLimit != -1) { msg.msg_controllen += CMSG_SPACE(sizeof(int)); cmsgptr->cmsg_len = CMSG_LEN(sizeof(int)); @@ -1020,16 +963,11 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l cmsgptr->cmsg_type = IPV6_PKTINFO; data->ipi6_ifindex = header.ifindex; - tmp = header.senderAddress.toIPv6Address(); + QIPv6Address tmp = header.senderAddress.toIPv6Address(); memcpy(&data->ipi6_addr, &tmp, sizeof(tmp)); cmsgptr = reinterpret_cast(reinterpret_cast(cmsgptr) + CMSG_SPACE(sizeof(*data))); } - } else if (header.destinationAddress.protocol() == QAbstractSocket::IPv4Protocol) { - aa.a4.sin_family = AF_INET; - aa.a4.sin_port = htons(header.destinationPort); - aa.a4.sin_addr.s_addr = htonl(header.destinationAddress.toIPv4Address()); - msg.msg_namelen = sizeof(aa.a4); - + } else { if (header.hopLimit != -1) { msg.msg_controllen += CMSG_SPACE(sizeof(int)); cmsgptr->cmsg_len = CMSG_LEN(sizeof(int)); @@ -1058,10 +996,6 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l cmsgptr = reinterpret_cast(reinterpret_cast(cmsgptr) + CMSG_SPACE(sizeof(*data))); } #endif - } else { - // Don't know what IP type this is, let's hope it sends - msg.msg_name = 0; - msg.msg_namelen = 0; } if (msg.msg_controllen == 0) diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index aecae40a44..5e198098df 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -276,32 +276,6 @@ static void convertToLevelAndOption(QNativeSocketEngine::SocketOption opt, } } -/*! \internal - - Sets the port and address to a sockaddr. Requires that sa point to the IPv6 struct if the address is IPv6. -*/ -void QNativeSocketEnginePrivate::setPortAndAddress(quint16 port, const QHostAddress &address, qt_sockaddr *aa, QT_SOCKLEN_T *sockAddrSize) -{ - if (address.protocol() == QAbstractSocket::IPv6Protocol - || address.protocol() == QAbstractSocket::AnyIPProtocol - || socketProtocol == QAbstractSocket::IPv6Protocol - || socketProtocol == QAbstractSocket::AnyIPProtocol) { - memset(&aa->a6, 0, sizeof(qt_sockaddr_in6)); - aa->a6.sin6_family = AF_INET6; - aa->a6.sin6_scope_id = address.scopeId().toUInt(); - WSAHtons(socketDescriptor, port, &aa->a6.sin6_port); - Q_IPV6ADDR tmp = address.toIPv6Address(); - memcpy(&aa->a6.sin6_addr, &tmp, sizeof(tmp)); - *sockAddrSize = sizeof(qt_sockaddr_in6); - } else { - memset(&aa->a, 0, sizeof(sockaddr_in)); - aa->a4.sin_family = AF_INET; - WSAHtons(socketDescriptor, port, &aa->a4.sin_port); - WSAHtonl(socketDescriptor, address.toIPv4Address(), &aa->a4.sin_addr.s_addr); - *sockAddrSize = sizeof(sockaddr_in); - } -} - /*! \internal */ @@ -348,6 +322,12 @@ static inline int qt_socket_getMaxMsgSize(qintptr socketDescriptor) # define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12) #endif +// inline on purpose +inline uint QNativeSocketEnginePrivate::scopeIdFromString(const QString &scopeid) +{ + return scopeid.toUInt(); +} + bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol &socketProtocol) { -- cgit v1.2.3 From b626a5859abef9a1b47ba02ffab0fd8d08f79a21 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 9 Aug 2015 21:56:26 -0700 Subject: Remove vestiges of Qt's own sockaddr_in6 and sockaddr_storage We weren't using qt_sockaddr_storage, so it's not a problem. But since we're not using it anyway, we don't really need it. The storage is only needed if we needed to get a bigger socket address and that only happens with Unix sockets (paths). sockaddr_in6, however, was just wrong. Some systems derived from BSD, like OS X, have a sXX_len field containing the length of the socket address structure and our qt_sockaddr_in6 was missing sin6_len. As a result, setting sin6_family was just plain wrong on little-endian systems. Like all modern systems running BSDs and OS X... Change-Id: I7de033f80b0e4431b7f1ffff13f900f004c55443 Reviewed-by: Richard J. Moore --- src/network/kernel/qhostinfo_win.cpp | 6 ++--- src/network/kernel/qnetworkinterface_win.cpp | 6 +++-- src/network/kernel/qnetworkinterface_win_p.h | 11 --------- src/network/socket/qnativesocketengine_p.h | 34 +++----------------------- src/network/socket/qnativesocketengine_win.cpp | 4 +-- 5 files changed, 13 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/network/kernel/qhostinfo_win.cpp b/src/network/kernel/qhostinfo_win.cpp index fc65ce9fa2..da28cd48c1 100644 --- a/src/network/kernel/qhostinfo_win.cpp +++ b/src/network/kernel/qhostinfo_win.cpp @@ -136,7 +136,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) // Reverse lookup if (local_getnameinfo) { sockaddr_in sa4; - qt_sockaddr_in6 sa6; + sockaddr_in6 sa6; sockaddr *sa; QT_SOCKLEN_T saSize; if (address.protocol() == QAbstractSocket::IPv4Protocol) { @@ -150,7 +150,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) saSize = sizeof(sa6); memset(&sa6, 0, sizeof(sa6)); sa6.sin6_family = AF_INET6; - memcpy(sa6.sin6_addr.qt_s6_addr, address.toIPv6Address().c, sizeof(sa6.sin6_addr.qt_s6_addr)); + memcpy(&sa6.sin6_addr, address.toIPv6Address().c, sizeof(sa6.sin6_addr)); } char hbuf[NI_MAXHOST]; @@ -197,7 +197,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) break; case AF_INET6: { QHostAddress addr; - addr.setAddress(((qt_sockaddr_in6 *) p->ai_addr)->sin6_addr.qt_s6_addr); + addr.setAddress(((sockaddr_in6 *) p->ai_addr)->sin6_addr.s6_addr); if (!addresses.contains(addr)) addresses.append(addr); } diff --git a/src/network/kernel/qnetworkinterface_win.cpp b/src/network/kernel/qnetworkinterface_win.cpp index a07840a848..dfcfdcc91f 100644 --- a/src/network/kernel/qnetworkinterface_win.cpp +++ b/src/network/kernel/qnetworkinterface_win.cpp @@ -43,6 +43,8 @@ #include #include +#include + QT_BEGIN_NAMESPACE typedef DWORD (WINAPI *PtrGetAdaptersInfo)(PIP_ADAPTER_INFO, PULONG); @@ -86,8 +88,8 @@ static QHostAddress addressFromSockaddr(sockaddr *sa) if (sa->sa_family == AF_INET) address.setAddress(htonl(((sockaddr_in *)sa)->sin_addr.s_addr)); else if (sa->sa_family == AF_INET6) { - address.setAddress(((qt_sockaddr_in6 *)sa)->sin6_addr.qt_s6_addr); - int scope = ((qt_sockaddr_in6 *)sa)->sin6_scope_id; + address.setAddress(((sockaddr_in6 *)sa)->sin6_addr.s6_addr); + int scope = ((sockaddr_in6 *)sa)->sin6_scope_id; if (scope) address.setScopeId(QString::number(scope)); } else diff --git a/src/network/kernel/qnetworkinterface_win_p.h b/src/network/kernel/qnetworkinterface_win_p.h index 88c1945fe6..55d98d2407 100644 --- a/src/network/kernel/qnetworkinterface_win_p.h +++ b/src/network/kernel/qnetworkinterface_win_p.h @@ -91,17 +91,6 @@ QT_BEGIN_NAMESPACE #define IF_TYPE_PPP 23 #endif -// copied from qnativesocketengine_win.cpp -struct qt_in6_addr { - u_char qt_s6_addr[16]; -}; -typedef struct { - short sin6_family; /* AF_INET6 */ - u_short sin6_port; /* Transport level port number */ - u_long sin6_flowinfo; /* IPv6 flow information */ - struct qt_in6_addr sin6_addr; /* IPv6 address */ - u_long sin6_scope_id; /* set of interfaces for a scope */ -} qt_sockaddr_in6; // copied from MSDN online help typedef enum { diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h index 966f44f774..0fa1d8f96e 100644 --- a/src/network/socket/qnativesocketengine_p.h +++ b/src/network/socket/qnativesocketengine_p.h @@ -51,23 +51,12 @@ # include #else # include +# include # include #endif QT_BEGIN_NAMESPACE -// Use our own defines and structs which we know are correct -# define QT_SS_MAXSIZE 128 -# define QT_SS_ALIGNSIZE (sizeof(qint64)) -# define QT_SS_PAD1SIZE (QT_SS_ALIGNSIZE - sizeof (short)) -# define QT_SS_PAD2SIZE (QT_SS_MAXSIZE - (sizeof (short) + QT_SS_PAD1SIZE + QT_SS_ALIGNSIZE)) -struct qt_sockaddr_storage { - short ss_family; - char __ss_pad1[QT_SS_PAD1SIZE]; - qint64 __ss_align; - char __ss_pad2[QT_SS_PAD2SIZE]; -}; - #ifdef Q_OS_WIN #define QT_SOCKLEN_T int #define QT_SOCKOPTLEN_T int @@ -103,25 +92,10 @@ typedef INT (WSAAPI *LPFN_WSASENDMSG)(SOCKET s, LPWSAMSG lpMsg, DWORD dwFlags, #endif #endif -// sockaddr_in6 size changed between old and new SDK -// Only the new version is the correct one, so always -// use this structure. -struct qt_in6_addr { - quint8 qt_s6_addr[16]; -}; -struct qt_sockaddr_in6 { - short sin6_family; /* AF_INET6 */ - quint16 sin6_port; /* Transport level port number */ - quint32 sin6_flowinfo; /* IPv6 flow information */ - struct qt_in6_addr sin6_addr; /* IPv6 address */ - quint32 sin6_scope_id; /* set of interfaces for a scope */ -}; - union qt_sockaddr { sockaddr a; sockaddr_in a4; - qt_sockaddr_in6 a6; - qt_sockaddr_storage storage; + sockaddr_in6 a6; }; class QNativeSocketEnginePrivate; @@ -302,13 +276,13 @@ public: || address.protocol() == QAbstractSocket::AnyIPProtocol || socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) { - memset(&aa->a6, 0, sizeof(qt_sockaddr_in6)); + memset(&aa->a6, 0, sizeof(sockaddr_in6)); aa->a6.sin6_family = AF_INET6; aa->a6.sin6_scope_id = scopeIdFromString(address.scopeId()); aa->a6.sin6_port = htons(port); Q_IPV6ADDR tmp = address.toIPv6Address(); memcpy(&aa->a6.sin6_addr, &tmp, sizeof(tmp)); - *sockAddrSize = sizeof(qt_sockaddr_in6); + *sockAddrSize = sizeof(sockaddr_in6); } else { memset(&aa->a, 0, sizeof(sockaddr_in)); aa->a4.sin_family = AF_INET; diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 5e198098df..2e905ad610 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -171,10 +171,10 @@ static QByteArray qt_prettyDebug(const char *data, int len, int maxLength) static inline void qt_socket_getPortAndAddress(SOCKET socketDescriptor, const qt_sockaddr *sa, quint16 *port, QHostAddress *address) { if (sa->a.sa_family == AF_INET6) { - const qt_sockaddr_in6 *sa6 = &sa->a6; + const sockaddr_in6 *sa6 = &sa->a6; Q_IPV6ADDR tmp; for (int i = 0; i < 16; ++i) - tmp.c[i] = sa6->sin6_addr.qt_s6_addr[i]; + tmp.c[i] = sa6->sin6_addr.s6_addr[i]; if (address) { QHostAddress a; a.setAddress(tmp); -- cgit v1.2.3 From 5c95c2077ce480a2a0192babbe5efe1e23731633 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Sun, 23 Aug 2015 23:51:26 +0300 Subject: winphone: Fix keyboard show/hide calls These need to occur on the XAML thread. Change-Id: Id42a37df95b09e6d3c0a1b6e593bbf8cbfe5a129 Reviewed-by: Samuel Nevala Reviewed-by: Maurice Kalinowski --- src/plugins/platforms/winrt/qwinrtinputcontext.cpp | 26 +++++++++++++++------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp index 7bd9e87ca6..f3b390b4d6 100644 --- a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp +++ b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp @@ -37,7 +37,9 @@ #include "qwinrtinputcontext.h" #include "qwinrtscreen.h" #include +#include +#include #include #include #include @@ -163,10 +165,14 @@ void QWinRTInputContext::showInputPanel() if (FAILED(hr)) return; - boolean success; - hr = inputPane->TryShow(&success); - if (FAILED(hr)) - qErrnoWarning(hr, "Failed to show input panel."); + QEventDispatcherWinRT::runOnXamlThread([&inputPane]() { + HRESULT hr; + boolean success; + hr = inputPane->TryShow(&success); + if (FAILED(hr) || !success) + qErrnoWarning(hr, "Failed to show input panel."); + return hr; + }); } void QWinRTInputContext::hideInputPanel() @@ -176,10 +182,14 @@ void QWinRTInputContext::hideInputPanel() if (FAILED(hr)) return; - boolean success; - hr = inputPane->TryHide(&success); - if (FAILED(hr)) - qErrnoWarning(hr, "Failed to hide input panel."); + QEventDispatcherWinRT::runOnXamlThread([&inputPane]() { + HRESULT hr; + boolean success; + hr = inputPane->TryHide(&success); + if (FAILED(hr) || !success) + qErrnoWarning(hr, "Failed to hide input panel."); + return hr; + }); } #endif // Q_OS_WINPHONE -- cgit v1.2.3 From cb6ab056480e39ed347d5a75e4b1b1f34443148c Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Fri, 19 Jun 2015 13:38:58 +0200 Subject: QLoggingRegistry: Look up logging configuration in Qt data path Distributions like Fedora would like to disable logging globally, without having to patch Qt. Fedora right now therefore adds a /etc/xdg/qtlogging.ini file, which unfortunately though also messes with Qt versions compiled by the user. This patch lets QLoggingRegistry look up logging configurations also in QLibraryInfo::DataPath, which would allow to tweak the values per Qt installation. See also https://bugzilla.redhat.com/show_bug.cgi?id=1227295 Change-Id: I0fca304a47f45739d0c08a9e4e715673bf10aa80 Reviewed-by: Alex Blasche --- src/corelib/io/qloggingcategory.cpp | 1 + src/corelib/io/qloggingregistry.cpp | 64 ++++++++++++++++++++----------------- src/corelib/io/qloggingregistry_p.h | 1 + 3 files changed, 37 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qloggingcategory.cpp b/src/corelib/io/qloggingcategory.cpp index 1d06e2a912..b51085ef42 100644 --- a/src/corelib/io/qloggingcategory.cpp +++ b/src/corelib/io/qloggingcategory.cpp @@ -157,6 +157,7 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift) Order of evaluation: \list + \li [QLibraryInfo::DataPath]/qtlogging.ini \li QtProject/qtlogging.ini \li \l setFilterRules() \li \c QT_LOGGING_CONF diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp index f0b72cd9be..b53e251102 100644 --- a/src/corelib/io/qloggingregistry.cpp +++ b/src/corelib/io/qloggingregistry.cpp @@ -34,6 +34,7 @@ #include "qloggingregistry_p.h" #include +#include #include #include #include @@ -247,6 +248,21 @@ static bool qtLoggingDebug() return debugEnv; } +static QVector loadRulesFromFile(const QString &filePath) +{ + QFile file(filePath); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + if (qtLoggingDebug()) + debugMsg("Loading \"%s\" ...", + QDir::toNativeSeparators(file.fileName()).toUtf8().constData()); + QTextStream stream(&file); + QLoggingSettingsParser parser; + parser.setContent(stream); + return parser.rules(); + } + return QVector(); +} + /*! \internal Initializes the rules database by loading @@ -256,18 +272,9 @@ void QLoggingRegistry::init() { // get rules from environment const QByteArray rulesFilePath = qgetenv("QT_LOGGING_CONF"); - if (!rulesFilePath.isEmpty()) { - QFile file(QFile::decodeName(rulesFilePath)); - if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { - if (qtLoggingDebug()) - debugMsg("Loading \"%s\" ...", - QDir::toNativeSeparators(file.fileName()).toUtf8().constData()); - QTextStream stream(&file); - QLoggingSettingsParser parser; - parser.setContent(stream); - envRules = parser.rules(); - } - } + if (!rulesFilePath.isEmpty()) + envRules = loadRulesFromFile(QFile::decodeName(rulesFilePath)); + const QByteArray rulesSrc = qgetenv("QT_LOGGING_RULES").replace(';', '\n'); if (!rulesSrc.isEmpty()) { QTextStream stream(rulesSrc); @@ -277,23 +284,22 @@ void QLoggingRegistry::init() envRules += parser.rules(); } - // get rules from qt configuration - QString envPath = QStandardPaths::locate(QStandardPaths::GenericConfigLocation, - QStringLiteral("QtProject/qtlogging.ini")); - if (!envPath.isEmpty()) { - QFile file(envPath); - if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { - if (qtLoggingDebug()) - debugMsg("Loading \"%s\" ...", - QDir::toNativeSeparators(envPath).toUtf8().constData()); - QTextStream stream(&file); - QLoggingSettingsParser parser; - parser.setContent(stream); - configRules = parser.rules(); - } - } + const QString configFileName = QStringLiteral("qtlogging.ini"); + +#if !defined(QT_BOOTSTRAPPED) + // get rules from Qt data configuration path + const QString qtConfigPath + = QDir(QLibraryInfo::location(QLibraryInfo::DataPath)).absoluteFilePath(configFileName); + qtConfigRules = loadRulesFromFile(qtConfigPath); +#endif + + // get rules from user's/system configuration + const QString envPath = QStandardPaths::locate(QStandardPaths::GenericConfigLocation, + QString::fromLatin1("QtProject/") + configFileName); + if (!envPath.isEmpty()) + configRules = loadRulesFromFile(envPath); - if (!envRules.isEmpty() || !configRules.isEmpty()) { + if (!envRules.isEmpty() || !qtConfigRules.isEmpty() || !configRules.isEmpty()) { QMutexLocker locker(®istryMutex); updateRules(); } @@ -356,7 +362,7 @@ void QLoggingRegistry::updateRules() if (categoryFilter != defaultCategoryFilter) return; - rules = configRules + apiRules + envRules; + rules = qtConfigRules + configRules + apiRules + envRules; foreach (QLoggingCategory *cat, categories.keys()) (*categoryFilter)(cat); diff --git a/src/corelib/io/qloggingregistry_p.h b/src/corelib/io/qloggingregistry_p.h index 718e09d9bb..bb32a4996d 100644 --- a/src/corelib/io/qloggingregistry_p.h +++ b/src/corelib/io/qloggingregistry_p.h @@ -122,6 +122,7 @@ private: QMutex registryMutex; + QVector qtConfigRules; QVector configRules; QVector envRules; QVector apiRules; -- cgit v1.2.3 From 5c9e94fb9b2c33790f04b497ca1e24ea54707c7c Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 19 Aug 2015 14:27:51 +0200 Subject: Windows: set QTabletEvent's timestamp from the window system event Task-number: QTBUG-39459 Change-Id: I8439846482a52b358bcdc4d8a5f6f4b9bbe55fa5 Reviewed-by: Laszlo Agocs --- .../platforms/windows/qwindowstabletsupport.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp index 05bddec530..3951401273 100644 --- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp +++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp @@ -54,7 +54,7 @@ #include // Note: The definition of the PACKET structure in pktdef.h depends on this define. -#define PACKETDATA (PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION | PK_CURSOR | PK_Z) +#define PACKETDATA (PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION | PK_CURSOR | PK_Z | PK_TIME) #include QT_BEGIN_NAMESPACE @@ -342,17 +342,18 @@ QWindowsTabletDeviceData QWindowsTabletSupport::tabletInit(const quint64 uniqueI bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, LPARAM lParam) { + PACKET proximityBuffer[1]; // we are only interested in the first packet in this case + const int totalPacks = QWindowsTabletSupport::m_winTab32DLL.wTPacketsGet(m_context, 1, proximityBuffer); + if (!totalPacks) + return false; if (!LOWORD(lParam)) { qCDebug(lcQpaTablet) << "leave proximity for device #" << m_currentDevice; - QWindowSystemInterface::handleTabletLeaveProximityEvent(m_devices.at(m_currentDevice).currentDevice, + QWindowSystemInterface::handleTabletLeaveProximityEvent(proximityBuffer[0].pkTime, + m_devices.at(m_currentDevice).currentDevice, m_devices.at(m_currentDevice).currentPointerType, m_devices.at(m_currentDevice).uniqueId); return true; } - PACKET proximityBuffer[1]; // we are only interested in the first packet in this case - const int totalPacks = QWindowsTabletSupport::m_winTab32DLL.wTPacketsGet(m_context, 1, proximityBuffer); - if (!totalPacks) - return false; const UINT currentCursor = proximityBuffer[0].pkCursor; UINT physicalCursorId; QWindowsTabletSupport::m_winTab32DLL.wTInfo(WTI_CURSORS + currentCursor, CSR_PHYSID, &physicalCursorId); @@ -370,7 +371,8 @@ bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, L m_devices[m_currentDevice].currentPointerType = pointerType(currentCursor); qCDebug(lcQpaTablet) << "enter proximity for device #" << m_currentDevice << m_devices.at(m_currentDevice); - QWindowSystemInterface::handleTabletEnterProximityEvent(m_devices.at(m_currentDevice).currentDevice, + QWindowSystemInterface::handleTabletEnterProximityEvent(proximityBuffer[0].pkTime, + m_devices.at(m_currentDevice).currentDevice, m_devices.at(m_currentDevice).currentPointerType, m_devices.at(m_currentDevice).uniqueId); return true; @@ -473,7 +475,7 @@ bool QWindowsTabletSupport::translateTabletPacketEvent() << tiltY << "tanP:" << tangentialPressure << "rotation:" << rotation; } - QWindowSystemInterface::handleTabletEvent(target, QPointF(localPos), globalPosF, + QWindowSystemInterface::handleTabletEvent(target, packet.pkTime, QPointF(localPos), globalPosF, currentDevice, currentPointer, static_cast(packet.pkButtons), pressureNew, tiltX, tiltY, -- cgit v1.2.3 From bd2ebbdb9a759b6f078cf7fb2fe6a0ac9d48b4fe Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 19 Aug 2015 13:57:20 +0200 Subject: QInputEvent: document that timestamp() is in milliseconds Task-number: QTBUG-39459 Change-Id: Ie76f3c2f6fe81746d3ea646f0c2f0d47ec3ef252 Reviewed-by: Laszlo Agocs --- src/gui/kernel/qevent.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 3873976144..780a102644 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -171,6 +171,8 @@ QInputEvent::~QInputEvent() \fn ulong QInputEvent::timestamp() const Returns the window system's timestamp for this event. + It will normally be in milliseconds since some arbitrary point + in time, such as the time when the system was started. */ /*! \fn void QInputEvent::setTimestamp(ulong atimestamp) -- cgit v1.2.3 From bc8d3259263533373db52352aaad4df136961d14 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 19 Aug 2015 13:39:23 +0200 Subject: xcb: set QTabletEvent's timestamp from the window system event The intention is for it not to include any delays that Qt's event processing has introduced. And we are already doing it this way for touch and scroll events. Task-number: QTBUG-39459 Change-Id: Ie01cc2f8c6290ab66ef1b9180471afaa3da2e9da Reviewed-by: Laszlo Agocs --- src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 5a2ea74258..6ca369326b 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -1029,9 +1029,8 @@ bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData, Q tabletData->inProximity = true; tabletData->tool = toolIdToTabletDevice(tool); tabletData->serialId = qint64(ptr[_WACSER_USB_ID]) << 32 | qint64(ptr[_WACSER_TOOL_SERIAL]); - QWindowSystemInterface::handleTabletEnterProximityEvent(tabletData->tool, - tabletData->pointerType, - tabletData->serialId); + QWindowSystemInterface::handleTabletEnterProximityEvent(ev->time, + tabletData->tool, tabletData->pointerType, tabletData->serialId); } else { tabletData->inProximity = false; tabletData->tool = toolIdToTabletDevice(ptr[_WACSER_LAST_TOOL_ID]); @@ -1040,9 +1039,8 @@ bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData, Q if (!tabletData->tool) tabletData->tool = toolIdToTabletDevice(ptr[_WACSER_LAST_TOOL_SERIAL]); tabletData->serialId = qint64(ptr[_WACSER_USB_ID]) << 32 | qint64(ptr[_WACSER_LAST_TOOL_SERIAL]); - QWindowSystemInterface::handleTabletLeaveProximityEvent(tabletData->tool, - tabletData->pointerType, - tabletData->serialId); + QWindowSystemInterface::handleTabletLeaveProximityEvent(ev->time, + tabletData->tool, tabletData->pointerType, tabletData->serialId); } // TODO maybe have a hash of tabletData->deviceId to device data so we can // look up the tablet name here, and distinguish multiple tablets @@ -1110,13 +1108,14 @@ void QXcbConnection::xi2ReportTabletEvent(TabletData &tabletData, void *event) } if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled())) - qCDebug(lcQpaXInput, "XI2 event on tablet %d with tool %d type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f buttons 0x%x pressure %4.2lf tilt %d, %d rotation %6.2lf", - tabletData.deviceId, tabletData.tool, ev->evtype, ev->sequenceNumber, ev->detail, + qCDebug(lcQpaXInput, "XI2 event on tablet %d with tool %d type %d seq %d detail %d time %d " + "pos %6.1f, %6.1f root pos %6.1f, %6.1f buttons 0x%x pressure %4.2lf tilt %d, %d rotation %6.2lf", + tabletData.deviceId, tabletData.tool, ev->evtype, ev->sequenceNumber, ev->detail, ev->time, fixed1616ToReal(ev->event_x), fixed1616ToReal(ev->event_y), fixed1616ToReal(ev->root_x), fixed1616ToReal(ev->root_y), (int)tabletData.buttons, pressure, xTilt, yTilt, rotation); - QWindowSystemInterface::handleTabletEvent(window, local, global, + QWindowSystemInterface::handleTabletEvent(window, ev->time, local, global, tabletData.tool, tabletData.pointerType, tabletData.buttons, pressure, xTilt, yTilt, tangentialPressure, -- cgit v1.2.3 From 2f43ac9dcdf4681267538f046a3d1b2c82ae0746 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 21 Aug 2015 10:28:50 +0200 Subject: Fix double initialization of QRgba64 with C++14 Use constructors with C++11/C++14 where it is allowed to avoid hack that caused double initialization and thereby performance regression with C++14. Change-Id: I7ae86df8aa34000b2c186e22bd9917303354b794 Reviewed-by: Thiago Macieira --- src/gui/painting/qrgba64.h | 47 +++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/gui/painting/qrgba64.h b/src/gui/painting/qrgba64.h index b701b224be..cca9019959 100644 --- a/src/gui/painting/qrgba64.h +++ b/src/gui/painting/qrgba64.h @@ -58,33 +58,34 @@ class QRgba64 { #endif }; + // No constructors are allowed in C++98, since this needs to be usable in a union. + // We however require one for constexprs in C++11/C++14 +#ifdef Q_COMPILER_CONSTEXPR + explicit Q_ALWAYS_INLINE Q_DECL_CONSTEXPR QRgba64(quint64 c) : rgba(c) { } +#endif public: - // No constructors are allowed, since this needs to be usable in a union in no-c++11 mode. - // When c++11 is mandatory, we can add all but a copy constructor. - Q_DECL_RELAXED_CONSTEXPR static - QRgba64 fromRgba64(quint16 red, quint16 green, quint16 blue, quint16 alpha) - { - QRgba64 rgba64 -#ifdef Q_COMPILER_UNIFORM_INIT - = {} +#ifdef Q_COMPILER_CONSTEXPR + Q_ALWAYS_INLINE Q_DECL_CONSTEXPR QRgba64() : rgba(0) { } #endif - ; - rgba64.rgba = quint64(red) << RedShift - | quint64(green) << GreenShift - | quint64(blue) << BlueShift - | quint64(alpha) << AlphaShift; - return rgba64; - } - Q_DECL_RELAXED_CONSTEXPR static + + Q_DECL_CONSTEXPR static QRgba64 fromRgba64(quint64 c) { - QRgba64 rgba64 -#ifdef Q_COMPILER_UNIFORM_INIT - = {} -#endif - ; +#ifdef Q_COMPILER_CONSTEXPR + return QRgba64(c); +#else + QRgba64 rgba64; rgba64.rgba = c; return rgba64; +#endif + } + Q_DECL_CONSTEXPR static + QRgba64 fromRgba64(quint16 red, quint16 green, quint16 blue, quint16 alpha) + { + return fromRgba64(quint64(red) << RedShift + | quint64(green) << GreenShift + | quint64(blue) << BlueShift + | quint64(alpha) << AlphaShift); } Q_DECL_RELAXED_CONSTEXPR static QRgba64 fromRgba(quint8 red, quint8 green, quint8 blue, quint8 alpha) { @@ -190,12 +191,12 @@ private: Q_DECLARE_TYPEINFO(QRgba64, Q_PRIMITIVE_TYPE); -Q_DECL_RELAXED_CONSTEXPR inline QRgba64 qRgba64(quint16 r, quint16 g, quint16 b, quint16 a) +Q_DECL_CONSTEXPR inline QRgba64 qRgba64(quint16 r, quint16 g, quint16 b, quint16 a) { return QRgba64::fromRgba64(r, g, b, a); } -Q_DECL_RELAXED_CONSTEXPR inline QRgba64 qRgba64(quint64 c) +Q_DECL_CONSTEXPR inline QRgba64 qRgba64(quint64 c) { return QRgba64::fromRgba64(c); } -- cgit v1.2.3 From 1977855f3115ab9ad1642b522840ff3424a5f2fe Mon Sep 17 00:00:00 2001 From: Jocelyn Turcotte Date: Mon, 10 Aug 2015 21:39:04 +0200 Subject: Avoid recreating QVariantLists when extracted from a QVariant Wrapping a QVariantList in a QVariant to pass it to QML would trigger a deep copy each time QML would try to access elements in the list (specifically in QQmlListAccessor::at). This reverts a part of 8c4deff51c8064f5a15cae0342bfa66b6663662b by specifying the associative array conversions explicitly without including the current type in the list of types to convert through an iteration. Task-number: QTBUG-41403 Change-Id: If9fddfe6d36f789ac4aa61a7c32677cd1dd077d8 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qmetatype.h | 15 --------------- src/corelib/kernel/qvariant.h | 6 +++--- 2 files changed, 3 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 9e3e1e94fa..b7f01ca5ca 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -2244,21 +2244,6 @@ namespace QtPrivate { }; } -namespace QtMetaTypePrivate { -inline Q_DECL_CONSTEXPR bool isBuiltinSequentialType(int typeId) -{ - return typeId == qMetaTypeId() - || typeId == qMetaTypeId() - || typeId == qMetaTypeId(); -} - -inline Q_DECL_CONSTEXPR bool isBuiltinAssociativeType(int typeId) -{ - return typeId == qMetaTypeId() - || typeId == qMetaTypeId(); -} -} // QtMetaTypePrivate - QT_END_NAMESPACE #endif // QMETATYPE_H diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index 27b19982de..4c7e498280 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -750,7 +750,7 @@ namespace QtPrivate { static QVariantList invoke(const QVariant &v) { const int typeId = v.userType(); - if (QtMetaTypePrivate::isBuiltinSequentialType(typeId) || QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId())) { + if (typeId == qMetaTypeId() || typeId == qMetaTypeId() || QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId())) { QSequentialIterable iter = QVariantValueHelperInterface::invoke(v); QVariantList l; l.reserve(iter.size()); @@ -767,7 +767,7 @@ namespace QtPrivate { static QVariantHash invoke(const QVariant &v) { const int typeId = v.userType(); - if (QtMetaTypePrivate::isBuiltinAssociativeType(typeId) || QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId())) { + if (typeId == qMetaTypeId() || QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId())) { QAssociativeIterable iter = QVariantValueHelperInterface::invoke(v); QVariantHash l; l.reserve(iter.size()); @@ -784,7 +784,7 @@ namespace QtPrivate { static QVariantMap invoke(const QVariant &v) { const int typeId = v.userType(); - if (QtMetaTypePrivate::isBuiltinAssociativeType(typeId) || QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId())) { + if (typeId == qMetaTypeId() || QMetaType::hasRegisteredConverterFunction(typeId, qMetaTypeId())) { QAssociativeIterable iter = QVariantValueHelperInterface::invoke(v); QVariantMap l; for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it) -- cgit v1.2.3 From ad080fa3113b4898cb9f9437df9d42627fbc3638 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 21 Aug 2015 13:58:39 -0700 Subject: Fix compilation with ICC on Windows Unlike MSVC, ICC *does* support constexpr, but on Windows it will not define __GNUC__, so we ended up in the multi-line alternative. That is not permitted in C++11, only in C++14. qalgorithms.h(659): error: statement may not appear in a constexpr function Change-Id: I7de033f80b0e4431b7f1ffff13fc96245ee9a846 Reviewed-by: Kai Koehne Reviewed-by: Friedemann Kleint --- src/corelib/tools/qalgorithms.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qalgorithms.h b/src/corelib/tools/qalgorithms.h index 57fbdf0eba..ffa3082d5e 100755 --- a/src/corelib/tools/qalgorithms.h +++ b/src/corelib/tools/qalgorithms.h @@ -649,7 +649,7 @@ Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(unsigned long v) Q_D return qCountTrailingZeroBits(QIntegerForSizeof::Unsigned(v)); } -Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint32 v) Q_DECL_NOTHROW +Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint32 v) Q_DECL_NOTHROW { #if defined(Q_CC_GNU) return v ? __builtin_clz(v) : 32U; @@ -664,7 +664,7 @@ Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint32 v) Q_DECL_NOTHROW #endif } -Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint8 v) Q_DECL_NOTHROW +Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint8 v) Q_DECL_NOTHROW { #if defined(Q_CC_GNU) return v ? __builtin_clz(v)-24U : 8U; @@ -676,7 +676,7 @@ Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint8 v) Q_DECL_NOTHROW #endif } -Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint16 v) Q_DECL_NOTHROW +Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint16 v) Q_DECL_NOTHROW { #if defined(Q_CC_GNU) return v ? __builtin_clz(v)-16U : 16U; @@ -689,7 +689,7 @@ Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint16 v) Q_DECL_NOTHROW #endif } -Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint64 v) Q_DECL_NOTHROW +Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(quint64 v) Q_DECL_NOTHROW { #if defined(Q_CC_GNU) return v ? __builtin_clzll(v) : 64U; @@ -704,7 +704,7 @@ Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(quint64 v) Q_DECL_NOTHROW #endif } -Q_DECL_CONSTEXPR inline uint qCountLeadingZeroBits(unsigned long v) Q_DECL_NOTHROW +Q_DECL_RELAXED_CONSTEXPR inline uint qCountLeadingZeroBits(unsigned long v) Q_DECL_NOTHROW { return qCountLeadingZeroBits(QIntegerForSizeof::Unsigned(v)); } -- cgit v1.2.3 From b30feab6e0889f57683dc2a15b8c33fddbd0820f Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 21 Aug 2015 14:46:03 -0700 Subject: Fix permissions on qalgorithms.h Commit 046f3254838715079b853ab4e15eed4ef464fb30 accidentally made it executable. Change-Id: I7de033f80b0e4431b7f1ffff13fc9872fa64ae9d Reviewed-by: Robin Burchell --- src/corelib/tools/qalgorithms.h | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 src/corelib/tools/qalgorithms.h (limited to 'src') diff --git a/src/corelib/tools/qalgorithms.h b/src/corelib/tools/qalgorithms.h old mode 100755 new mode 100644 -- cgit v1.2.3 From b4a48d2578825fbbef444f4beba2b9a6a37fbd7d Mon Sep 17 00:00:00 2001 From: Louai Al-Khanji Date: Mon, 24 Aug 2015 10:24:18 +0300 Subject: Move QCoreApplication::quitLockEnabled documentation to single place MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moving the documentation to one spot reduces repetition, is more canonical, and avoids a warning due to undocumented function argument in the setter. Also document the default setting. Change-Id: Idcedacf4bf101909689025d044e96801255a3332 Reviewed-by: Topi Reiniö --- src/corelib/kernel/qcoreapplication.cpp | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 00d618745b..0de6f833d3 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -937,18 +937,14 @@ bool QCoreApplication::testAttribute(Qt::ApplicationAttribute attribute) /*! \property QCoreApplication::quitLockEnabled - Returns \c true if the use of the QEventLoopLocker feature can cause the - application to quit, otherwise returns \c false. + \brief Whether the use of the QEventLoopLocker feature can cause the + application to quit. + + The default is \c true. \sa QEventLoopLocker */ -/*! - Returns \c true if the use of the QEventLoopLocker feature can cause the - application to quit, otherwise returns \c false. - - \sa QEventLoopLocker - */ bool QCoreApplication::isQuitLockEnabled() { return quitLockRefEnabled; @@ -956,14 +952,6 @@ bool QCoreApplication::isQuitLockEnabled() static bool doNotify(QObject *, QEvent *); -/*! - Enables the ability of the QEventLoopLocker feature to quit - the application. - - If disabled, the use of QEventLoopLocker will not quit the application. - - \sa QEventLoopLocker - */ void QCoreApplication::setQuitLockEnabled(bool enabled) { quitLockRefEnabled = enabled; -- cgit v1.2.3 From 6c21a0ea0e561aaafc3dd0f9aecbcdaf5f867ec6 Mon Sep 17 00:00:00 2001 From: Louai Al-Khanji Date: Mon, 24 Aug 2015 10:26:57 +0300 Subject: Fix invalid documentation function reference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Iccf62e3f2f7843c14dd6540400241bdd264ad376 Reviewed-by: Topi Reiniö --- src/corelib/kernel/qcoreapplication.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 0de6f833d3..8f4774a1e0 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -1807,7 +1807,7 @@ void QCoreApplicationPrivate::maybeQuit() Tells the application to exit with return code 0 (success). Equivalent to calling QCoreApplication::exit(0). - It's common to connect the QApplication::lastWindowClosed() signal + It's common to connect the QGuiApplication::lastWindowClosed() signal to quit(), and you also often connect e.g. QAbstractButton::clicked() or signals in QAction, QMenu, or QMenuBar to it. @@ -1815,7 +1815,7 @@ void QCoreApplicationPrivate::maybeQuit() \snippet code/src_corelib_kernel_qcoreapplication.cpp 1 - \sa exit(), aboutToQuit(), QApplication::lastWindowClosed() + \sa exit(), aboutToQuit(), QGuiApplication::lastWindowClosed() */ void QCoreApplication::quit() -- cgit v1.2.3 From 789b79fd8a4557488b30bd21910a3b6a1ad417e1 Mon Sep 17 00:00:00 2001 From: Louai Al-Khanji Date: Mon, 24 Aug 2015 10:27:46 +0300 Subject: Fix warning due to undocumented function argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I00654b72a654c7b2a762ace773a9caef37b1bdd5 Reviewed-by: Topi Reiniö --- src/corelib/tools/qstring.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index c43a7be7fd..b16ae6a14a 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -2680,6 +2680,8 @@ bool operator==(const QString &s1, const QString &s2) /*! \overload operator==() + Returns \c true if this string is equal to \a other; otherwise + returns \c false. */ bool QString::operator==(QLatin1String other) const { -- cgit v1.2.3 From 16a506f41880a6e7b3329eae3383b5f631c019a4 Mon Sep 17 00:00:00 2001 From: Louai Al-Khanji Date: Mon, 24 Aug 2015 10:28:31 +0300 Subject: Fix warning due to undocumented function argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ia3a54f296b1edcdce5950bf7acad1b4436d9564a Reviewed-by: Topi Reiniö Reviewed-by: Thiago Macieira --- src/corelib/tools/qstring.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index b16ae6a14a..e3a3cc79c6 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -3616,9 +3616,14 @@ int QString::count(const QString &str, Qt::CaseSensitivity cs) const } /*! - \overload count() + \overload count() + + Returns the number of occurrences of character \a ch in the string. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. - Returns the number of occurrences of character \a ch in the string. + \sa contains(), indexOf() */ int QString::count(QChar ch, Qt::CaseSensitivity cs) const -- cgit v1.2.3 From 056328d3cb3727415764048470ad9918200ae32f Mon Sep 17 00:00:00 2001 From: Louai Al-Khanji Date: Mon, 24 Aug 2015 10:29:56 +0300 Subject: Add #ifdef to avoid qdoc missing function warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I1cba5543a519030a5b06bc80b6fd7410327c86c8 Reviewed-by: Topi Reiniö --- src/corelib/kernel/qpointer.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/corelib/kernel/qpointer.h b/src/corelib/kernel/qpointer.h index 72388f2bb7..52bd368301 100644 --- a/src/corelib/kernel/qpointer.h +++ b/src/corelib/kernel/qpointer.h @@ -66,6 +66,11 @@ public: // compiler-generated copy/move ctor/assignment operators are fine! // compiler-generated dtor is fine! +#ifdef Q_QDOC + // Stop qdoc from complaining about missing function + ~QPointer(); +#endif + inline void swap(QPointer &other) { wp.swap(other.wp); } inline QPointer &operator=(T* p) -- cgit v1.2.3 From a49477df9573b3d7cae328711877d625139eb2e9 Mon Sep 17 00:00:00 2001 From: Louai Al-Khanji Date: Mon, 24 Aug 2015 10:31:16 +0300 Subject: Fix qdoc warning by documenting function argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I3d80af0b1226fbe601619420dbb35106bb3d4eec Reviewed-by: Topi Reiniö --- src/corelib/tools/qbytearray.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 447e84b3d4..5ed72fc341 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -489,8 +489,8 @@ quint16 qChecksum(const char *data, uint len) \overload - Compresses the first \a nbytes of \a data and returns the - compressed data in a new byte array. + Compresses the first \a nbytes of \a data at compression level + \a compressionLevel and returns the compressed data in a new byte array. */ #ifndef QT_NO_COMPRESS -- cgit v1.2.3 From e6d5e4167cf04d5cab57e5aa54d92a39a47aeca5 Mon Sep 17 00:00:00 2001 From: Louai Al-Khanji Date: Mon, 24 Aug 2015 10:31:44 +0300 Subject: Fix documentation typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ic6271a19999555ef2a1dfa90cebfb92b270a3809 Reviewed-by: Topi Reiniö --- src/corelib/tools/qcommandlineoption.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/tools/qcommandlineoption.cpp b/src/corelib/tools/qcommandlineoption.cpp index 5eda114087..8c0ba8cb2b 100644 --- a/src/corelib/tools/qcommandlineoption.cpp +++ b/src/corelib/tools/qcommandlineoption.cpp @@ -391,7 +391,7 @@ QStringList QCommandLineOption::defaultValues() const /*! Sets whether to hide this option in the user-visible help output. - All options are visible by default. Setting \a hidden to true for + All options are visible by default. Setting \a hide to true for a particular option makes it internal, i.e. not listed in the help output. \since 5.6 -- cgit v1.2.3 From cf68d764ab5dd1b1d129e81ea69e739a9f682c1e Mon Sep 17 00:00:00 2001 From: Louai Al-Khanji Date: Mon, 24 Aug 2015 10:32:51 +0300 Subject: Document QStateMachine::running property in single place MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a number of qdoc warnings due to e.g. missing documentation for setter argument. Change-Id: If9ae43f70f0e42fe8b8a4f04f49d522cd7d69099 Reviewed-by: Kevin Funk Reviewed-by: Topi Reiniö --- src/corelib/statemachine/qstatemachine.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 237b19bc0e..687f676819 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -160,6 +160,8 @@ QT_BEGIN_NAMESPACE \since 5.4 \brief the running state of this state machine + + \sa start(), stop(), started(), stopped(), runningChanged() */ #ifndef QT_NO_ANIMATION @@ -2576,11 +2578,6 @@ void QStateMachine::removeState(QAbstractState *state) state->setParent(0); } -/*! - Returns whether this state machine is running. - - \sa start(), stop() -*/ bool QStateMachine::isRunning() const { Q_D(const QStateMachine); @@ -2643,11 +2640,6 @@ void QStateMachine::stop() } } -/*! - Convenience functions to start/stop this state machine. - - \sa start(), stop(), started(), finished(), stopped() -*/ void QStateMachine::setRunning(bool running) { if (running) -- cgit v1.2.3 From aab5698dd9739b2b1a42bf0b311df47574cc34e4 Mon Sep 17 00:00:00 2001 From: Louai Al-Khanji Date: Mon, 24 Aug 2015 11:44:58 +0300 Subject: Remove unused kms plugin The old kms plugin has been replaced by EGLFS's KMS backend. The EGLFS backend is smaller and has more features. The kms plugin cannot be built automatically since Qt 5.5 and is therefore also not tested for changes in QPA API by the CI. Therefore removing the plugin from the tree should not be a regression from the previous release. Change-Id: Icb9ea8c4a5d6421397a2e3f2e2195fb6bfad2293 Reviewed-by: Lars Knoll Reviewed-by: Laszlo Agocs --- src/plugins/platforms/kms/kms.json | 3 - src/plugins/platforms/kms/kms.pro | 37 --- src/plugins/platforms/kms/main.cpp | 58 ----- src/plugins/platforms/kms/qkmsbackingstore.cpp | 217 ----------------- src/plugins/platforms/kms/qkmsbackingstore.h | 72 ------ src/plugins/platforms/kms/qkmscontext.cpp | 136 ----------- src/plugins/platforms/kms/qkmscontext.h | 71 ------ src/plugins/platforms/kms/qkmscursor.cpp | 116 --------- src/plugins/platforms/kms/qkmscursor.h | 66 ------ src/plugins/platforms/kms/qkmsdevice.cpp | 118 ---------- src/plugins/platforms/kms/qkmsdevice.h | 81 ------- src/plugins/platforms/kms/qkmsintegration.cpp | 204 ---------------- src/plugins/platforms/kms/qkmsintegration.h | 108 --------- src/plugins/platforms/kms/qkmsnativeinterface.cpp | 135 ----------- src/plugins/platforms/kms/qkmsnativeinterface.h | 64 ----- src/plugins/platforms/kms/qkmsscreen.cpp | 275 ---------------------- src/plugins/platforms/kms/qkmsscreen.h | 122 ---------- src/plugins/platforms/kms/qkmswindow.cpp | 66 ------ src/plugins/platforms/kms/qkmswindow.h | 57 ----- 19 files changed, 2006 deletions(-) delete mode 100644 src/plugins/platforms/kms/kms.json delete mode 100644 src/plugins/platforms/kms/kms.pro delete mode 100644 src/plugins/platforms/kms/main.cpp delete mode 100644 src/plugins/platforms/kms/qkmsbackingstore.cpp delete mode 100644 src/plugins/platforms/kms/qkmsbackingstore.h delete mode 100644 src/plugins/platforms/kms/qkmscontext.cpp delete mode 100644 src/plugins/platforms/kms/qkmscontext.h delete mode 100644 src/plugins/platforms/kms/qkmscursor.cpp delete mode 100644 src/plugins/platforms/kms/qkmscursor.h delete mode 100644 src/plugins/platforms/kms/qkmsdevice.cpp delete mode 100644 src/plugins/platforms/kms/qkmsdevice.h delete mode 100644 src/plugins/platforms/kms/qkmsintegration.cpp delete mode 100644 src/plugins/platforms/kms/qkmsintegration.h delete mode 100644 src/plugins/platforms/kms/qkmsnativeinterface.cpp delete mode 100644 src/plugins/platforms/kms/qkmsnativeinterface.h delete mode 100644 src/plugins/platforms/kms/qkmsscreen.cpp delete mode 100644 src/plugins/platforms/kms/qkmsscreen.h delete mode 100644 src/plugins/platforms/kms/qkmswindow.cpp delete mode 100644 src/plugins/platforms/kms/qkmswindow.h (limited to 'src') diff --git a/src/plugins/platforms/kms/kms.json b/src/plugins/platforms/kms/kms.json deleted file mode 100644 index be662226ae..0000000000 --- a/src/plugins/platforms/kms/kms.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "Keys": [ "kms" ] -} diff --git a/src/plugins/platforms/kms/kms.pro b/src/plugins/platforms/kms/kms.pro deleted file mode 100644 index baa8778153..0000000000 --- a/src/plugins/platforms/kms/kms.pro +++ /dev/null @@ -1,37 +0,0 @@ -TARGET = qkms - -PLUGIN_TYPE = platforms -PLUGIN_CLASS_NAME = QKmsIntegrationPlugin -!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = - -load(qt_plugin) - -QT += core-private gui-private platformsupport-private -qtHaveModule(opengl):QT += opengl-private - -DEFINES += MESA_EGL_NO_X11_HEADERS __GBM__ - -CONFIG += link_pkgconfig egl qpa/genericunixfontdatabase - -PKGCONFIG += libdrm libudev egl gbm glesv2 - -SOURCES = main.cpp \ - qkmsintegration.cpp \ - qkmsscreen.cpp \ - qkmscontext.cpp \ - qkmswindow.cpp \ - qkmscursor.cpp \ - qkmsdevice.cpp \ - qkmsbackingstore.cpp \ - qkmsnativeinterface.cpp - -HEADERS = qkmsintegration.h \ - qkmsscreen.h \ - qkmscontext.h \ - qkmswindow.h \ - qkmscursor.h \ - qkmsdevice.h \ - qkmsbackingstore.h \ - qkmsnativeinterface.h - -OTHER_FILES += \ - kms.json diff --git a/src/plugins/platforms/kms/main.cpp b/src/plugins/platforms/kms/main.cpp deleted file mode 100644 index 565ac7a7d4..0000000000 --- a/src/plugins/platforms/kms/main.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include "qkmsintegration.h" - -QT_BEGIN_NAMESPACE - -class QKmsIntegrationPlugin : public QPlatformIntegrationPlugin -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "kms.json") -public: - QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE; -}; - -QPlatformIntegration *QKmsIntegrationPlugin::create(const QString& system, const QStringList& paramList) -{ - Q_UNUSED(paramList); - if (!system.compare(QLatin1String("kms"), Qt::CaseInsensitive)) - return new QKmsIntegration; - - return 0; -} - -QT_END_NAMESPACE - -#include "main.moc" diff --git a/src/plugins/platforms/kms/qkmsbackingstore.cpp b/src/plugins/platforms/kms/qkmsbackingstore.cpp deleted file mode 100644 index 6e5a3f9192..0000000000 --- a/src/plugins/platforms/kms/qkmsbackingstore.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qkmsbackingstore.h" - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -QKmsBackingStore::QKmsBackingStore(QWindow *window) - : QPlatformBackingStore(window) - , m_context(new QOpenGLContext) - , m_texture(0) - , m_program(0) - , m_initialized(false) -{ - m_context->setFormat(window->requestedFormat()); - m_context->setScreen(window->screen()); - m_context->create(); -} - -QKmsBackingStore::~QKmsBackingStore() -{ - delete m_program; - if (m_texture) - glDeleteTextures(1, &m_texture); - - delete m_context; -} - -QPaintDevice *QKmsBackingStore::paintDevice() -{ - return &m_image; -} - -void QKmsBackingStore::beginPaint(const QRegion &rgn) -{ - m_dirty |= rgn; -} - -void QKmsBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) -{ - Q_UNUSED(region) - Q_UNUSED(offset) - - m_context->makeCurrent(window); - - if (!m_initialized) { - initializeOpenGLFunctions(); - m_initialized = true; - } - - if (!m_program) { - static const char *textureVertexProgram = - "attribute highp vec2 vertexCoordEntry;\n" - "attribute highp vec2 textureCoordEntry;\n" - "varying highp vec2 textureCoord;\n" - "void main() {\n" - " textureCoord = textureCoordEntry;\n" - " gl_Position = vec4(vertexCoordEntry, 0.0, 1.0);\n" - "}\n"; - - static const char *textureFragmentProgram = - "uniform sampler2D texture;\n" - "varying highp vec2 textureCoord;\n" - "void main() {\n" - " gl_FragColor = texture2D(texture, textureCoord).bgra;\n" - "}\n"; - - m_program = new QOpenGLShaderProgram; - - m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram); - m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram); - m_program->bindAttributeLocation("vertexCoordEntry", 0); - m_program->bindAttributeLocation("textureCoordEntry", 1); - m_program->link(); - } - - m_program->bind(); - - QRectF r = window->geometry(); - QRectF sr = window->screen()->geometry(); - - GLfloat x1 = (r.left() / sr.width()) * 2 - 1; - GLfloat x2 = (r.right() / sr.width()) * 2 - 1; - GLfloat y1 = -1 * ((r.top() / sr.height()) * 2 - 1); - GLfloat y2 = -1 * ((r.bottom() / sr.height()) * 2 - 1); - - const GLfloat vertexCoordinates[] = { - x1, y1, - x2, y1, - x2, y2, - x1, y2 - }; - - const GLfloat textureCoordinates[] = { - 0, 0, - 1, 0, - 1, 1, - 0, 1 - }; - - glEnableVertexAttribArray(0); - glEnableVertexAttribArray(1); - - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinates); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinates); - - glBindTexture(GL_TEXTURE_2D, m_texture); - - if (!m_dirty.isNull()) { - QRect imageRect = m_image.rect(); - QRegion fixed; - Q_FOREACH (const QRect &rect, m_dirty.rects()) { - // intersect with image rect to be sure - QRect r = imageRect & rect; - // if the rect is wide enough it's cheaper to just - // extend it instead of doing an image copy - if (r.width() >= imageRect.width() / 2) { - r.setX(0); - r.setWidth(imageRect.width()); - } - fixed |= r; - } - - Q_FOREACH (const QRect &rect, fixed.rects()) { - // if the sub-rect is full-width we can pass the image data directly to - // OpenGL instead of copying, since there's no gap between scanlines - if (rect.width() == imageRect.width()) { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), - rect.width(), rect.height(), - GL_RGBA, GL_UNSIGNED_BYTE, - m_image.constScanLine(rect.y())); - } else { - glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), - rect.width(), rect.height(), - GL_RGBA, GL_UNSIGNED_BYTE, - m_image.copy(rect).constBits()); - } - } - - m_dirty = QRegion(); - } - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - m_program->release(); - glBindTexture(GL_TEXTURE_2D, 0); - glDisableVertexAttribArray(0); - glDisableVertexAttribArray(1); - - m_context->swapBuffers(window); - - m_context->doneCurrent(); -} - -void QKmsBackingStore::resize(const QSize &size, const QRegion &staticContents) -{ - Q_UNUSED(staticContents) - - m_image = QImage(size, QImage::Format_RGB32); - - m_context->makeCurrent(window()); - - if (!m_initialized) { - initializeOpenGLFunctions(); - m_initialized = true; - } - - if (m_texture) - glDeleteTextures(1, &m_texture); - - glGenTextures(1, &m_texture); - glBindTexture(GL_TEXTURE_2D, m_texture); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), - 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - -} - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/kms/qkmsbackingstore.h b/src/plugins/platforms/kms/qkmsbackingstore.h deleted file mode 100644 index a34b10d3d9..0000000000 --- a/src/plugins/platforms/kms/qkmsbackingstore.h +++ /dev/null @@ -1,72 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QBACKINGSTORE_KMS_H -#define QBACKINGSTORE_KMS_H - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class QOpenGLContext; -class QOpenGLShaderProgram; - -class QKmsBackingStore : public QPlatformBackingStore, public QOpenGLFunctions -{ -public: - QKmsBackingStore(QWindow *window); - ~QKmsBackingStore(); - - QPaintDevice *paintDevice() Q_DECL_OVERRIDE; - - void beginPaint(const QRegion &) Q_DECL_OVERRIDE; - - void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) Q_DECL_OVERRIDE; - void resize(const QSize &size, const QRegion &staticContents) Q_DECL_OVERRIDE; - - QImage toImage() const Q_DECL_OVERRIDE { return m_image; } - -private: - QOpenGLContext *m_context; - QImage m_image; - uint m_texture; - QOpenGLShaderProgram *m_program; - QRegion m_dirty; - bool m_initialized; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/platforms/kms/qkmscontext.cpp b/src/plugins/platforms/kms/qkmscontext.cpp deleted file mode 100644 index e00835fbac..0000000000 --- a/src/plugins/platforms/kms/qkmscontext.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qkmsscreen.h" -#include "qkmsdevice.h" -#include "qkmscontext.h" -#include "qkmswindow.h" -#include "qkmsintegration.h" - -#include -#include - -QT_BEGIN_NAMESPACE - -QKmsContext::QKmsContext(QOpenGLContext *context, QKmsDevice *device) - : m_device(device) -{ - EGLDisplay display = m_device->eglDisplay(); - EGLConfig config = q_configFromGLFormat(display, QKmsScreen::tweakFormat(context->format())); - m_format = q_glFormatFromConfig(display, config); - - //Initialize EGLContext - static EGLint contextAttribs[] = { - EGL_CONTEXT_CLIENT_VERSION, context->format().majorVersion(), - EGL_NONE - }; - - eglBindAPI(EGL_OPENGL_ES_API); - - EGLContext share = EGL_NO_CONTEXT; - if (context->shareContext()) - share = static_cast(context->shareContext()->handle())->eglContext(); - - m_eglContext = eglCreateContext(display, config, share, contextAttribs); - if (m_eglContext == EGL_NO_CONTEXT) { - qWarning("QKmsContext::QKmsContext(): eglError: %x, this: %p", - eglGetError(), this); - m_eglContext = 0; - } -} - -bool QKmsContext::isValid() const -{ - return m_eglContext != EGL_NO_CONTEXT; -} - -bool QKmsContext::makeCurrent(QPlatformSurface *surface) -{ - Q_ASSERT(surface->surface()->supportsOpenGL()); - - EGLDisplay display = m_device->eglDisplay(); - EGLSurface eglSurface; - - if (surface->surface()->surfaceClass() == QSurface::Window) { - QPlatformWindow *window = static_cast(surface); - QKmsScreen *screen = static_cast(QPlatformScreen::platformScreenForWindow(window->window())); - eglSurface = screen->eglSurface(); - screen->waitForPageFlipComplete(); - } else { - eglSurface = static_cast(surface)->surface(); - } - - bool ok = eglMakeCurrent(display, eglSurface, eglSurface, m_eglContext); - if (!ok) - qWarning("QKmsContext::makeCurrent(): eglError: %x, this: %p", - eglGetError(), this); - - return true; -} - -void QKmsContext::doneCurrent() -{ - bool ok = eglMakeCurrent(m_device->eglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, - EGL_NO_CONTEXT); - if (!ok) - qWarning("QKmsContext::doneCurrent(): eglError: %x, this: %p", - eglGetError(), this); - -} - -void QKmsContext::swapBuffers(QPlatformSurface *surface) -{ - //Cast context to a window surface and get the screen the context - //is on and call swapBuffers on that screen. - QPlatformWindow *window = static_cast(surface); - QKmsScreen *screen = static_cast (QPlatformScreen::platformScreenForWindow(window->window())); - screen->swapBuffers(); -} - -void (*QKmsContext::getProcAddress(const QByteArray &procName)) () -{ - return eglGetProcAddress(procName.data()); -} - - -EGLContext QKmsContext::eglContext() const -{ - return m_eglContext; -} - -QSurfaceFormat QKmsContext::format() const -{ - return m_format; -} - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/kms/qkmscontext.h b/src/plugins/platforms/kms/qkmscontext.h deleted file mode 100644 index 59cf9b1e34..0000000000 --- a/src/plugins/platforms/kms/qkmscontext.h +++ /dev/null @@ -1,71 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QKMSCONTEXT_H -#define QKMSCONTEXT_H - -#include - -#define EGL_EGLEXT_PROTOTYPES 1 -#include - -QT_BEGIN_NAMESPACE - -class QKmsDevice; - -class QKmsContext : public QPlatformOpenGLContext -{ -public: - QKmsContext(QOpenGLContext *context, QKmsDevice *device); - - bool makeCurrent(QPlatformSurface *surface) Q_DECL_OVERRIDE; - void doneCurrent() Q_DECL_OVERRIDE; - void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE; - void (*getProcAddress(const QByteArray &procName)) () Q_DECL_OVERRIDE; - - bool isValid() const Q_DECL_OVERRIDE; - - QSurfaceFormat format() const Q_DECL_OVERRIDE; - - EGLContext eglContext() const; - -private: - EGLContext m_eglContext; - QSurfaceFormat m_format; - - QKmsDevice *m_device; -}; - -QT_END_NAMESPACE - -#endif // QKMSCONTEXT_H diff --git a/src/plugins/platforms/kms/qkmscursor.cpp b/src/plugins/platforms/kms/qkmscursor.cpp deleted file mode 100644 index 44212cd3c8..0000000000 --- a/src/plugins/platforms/kms/qkmscursor.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -//#include -#include "qkmscursor.h" -#include "qkmsscreen.h" -#include "qkmsdevice.h" - -QT_BEGIN_NAMESPACE - -#ifndef DRM_CAP_CURSOR_WIDTH -#define DRM_CAP_CURSOR_WIDTH 0x8 -#endif - -#ifndef DRM_CAP_CURSOR_HEIGHT -#define DRM_CAP_CURSOR_HEIGHT 0x9 -#endif - -QKmsCursor::QKmsCursor(QKmsScreen *screen) - : m_screen(screen), - m_graphicsBufferManager(screen->device()->gbmDevice()), - m_cursorImage(new QPlatformCursorImage(0, 0, 0, 0, 0, 0)), - m_moved(false), - m_cursorSize(64, 64) -{ - uint64_t value = 0; - if (!drmGetCap(m_screen->device()->fd(), DRM_CAP_CURSOR_WIDTH, &value)) - m_cursorSize.setWidth(value); - if (!drmGetCap(m_screen->device()->fd(), DRM_CAP_CURSOR_HEIGHT, &value)) - m_cursorSize.setHeight(value); - - m_cursorBufferObject = gbm_bo_create(m_graphicsBufferManager, m_cursorSize.width(), m_cursorSize.height(), - GBM_FORMAT_ARGB8888, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE); -} - -QKmsCursor::~QKmsCursor() -{ - drmModeSetCursor(m_screen->device()->fd(), m_screen->crtcId(), 0, 0, 0); - gbm_bo_destroy(m_cursorBufferObject); -} - -void QKmsCursor::pointerEvent(const QMouseEvent &event) -{ - m_moved = true; - int status = drmModeMoveCursor(m_screen->device()->fd(), - m_screen->crtcId(), - event.globalX(), - event.globalY()); - if (status) { - qWarning("failed to move cursor: %d", status); - } -} - -void QKmsCursor::changeCursor(QCursor *windowCursor, QWindow *window) -{ - Q_UNUSED(window) - - if (!m_moved) - drmModeMoveCursor(m_screen->device()->fd(), m_screen->crtcId(), 0, 0); - - const Qt::CursorShape newShape = windowCursor ? windowCursor->shape() : Qt::ArrowCursor; - if (newShape != Qt::BitmapCursor) { - m_cursorImage->set(newShape); - } else { - m_cursorImage->set(windowCursor->pixmap().toImage(), - windowCursor->hotSpot().x(), - windowCursor->hotSpot().y()); - } - - if (m_cursorImage->image()->width() > m_cursorSize.width() || m_cursorImage->image()->width() > m_cursorSize.height()) - qWarning("cursor larger than %dx%d, cursor truncated", m_cursorSize.width(), m_cursorSize.height()); - - QImage cursorImage = m_cursorImage->image()->convertToFormat(QImage::Format_ARGB32) - .copy(0, 0, m_cursorSize.width(), m_cursorSize.height()); - gbm_bo_write(m_cursorBufferObject, cursorImage.constBits(), cursorImage.byteCount()); - - quint32 handle = gbm_bo_get_handle(m_cursorBufferObject).u32; - int status = drmModeSetCursor(m_screen->device()->fd(), - m_screen->crtcId(), handle, - m_cursorSize.width(), m_cursorSize.height()); - - if (status) { - qWarning("failed to set cursor: %d", status); - } -} - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/kms/qkmscursor.h b/src/plugins/platforms/kms/qkmscursor.h deleted file mode 100644 index 9aadf407c0..0000000000 --- a/src/plugins/platforms/kms/qkmscursor.h +++ /dev/null @@ -1,66 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QKMSCURSOR_H -#define QKMSCURSOR_H - -#include - -struct gbm_device; -struct gbm_bo; - -QT_BEGIN_NAMESPACE - -class QKmsScreen; - -class QKmsCursor : public QPlatformCursor -{ -public: - QKmsCursor(QKmsScreen *screen); - ~QKmsCursor(); - - void pointerEvent(const QMouseEvent &event) Q_DECL_OVERRIDE; - void changeCursor(QCursor *windowCursor, QWindow *window) Q_DECL_OVERRIDE; - -private: - QKmsScreen *m_screen; - gbm_device *m_graphicsBufferManager; - gbm_bo *m_cursorBufferObject; - QPlatformCursorImage *m_cursorImage; - bool m_moved; - QSize m_cursorSize; -}; - -QT_END_NAMESPACE - -#endif // QKMSCURSOR_H diff --git a/src/plugins/platforms/kms/qkmsdevice.cpp b/src/plugins/platforms/kms/qkmsdevice.cpp deleted file mode 100644 index 74fa59c16a..0000000000 --- a/src/plugins/platforms/kms/qkmsdevice.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -//#include -#include "qkmsscreen.h" -#include "qkmsdevice.h" - -#include "qkmsintegration.h" - -#include -#include - -QT_BEGIN_NAMESPACE - -QKmsDevice::QKmsDevice(const QString &path, QKmsIntegration *parent) : - QObject(0), m_integration(parent) -{ - m_fd = QT_OPEN(path.toLatin1().constData(), O_RDWR); - if (m_fd < 0) { - qWarning("Could not open %s.", path.toLatin1().constData()); - qFatal("No DRM display device"); - } - - m_graphicsBufferManager = gbm_create_device(m_fd); - m_eglDisplay = eglGetDisplay(m_graphicsBufferManager); - - if (m_eglDisplay == EGL_NO_DISPLAY) { - qWarning("Could not open EGL display"); - qFatal("EGL error"); - } - - EGLint major; - EGLint minor; - if (!eglInitialize(m_eglDisplay, &major, &minor)) { - qWarning("Could not initialize EGL display"); - qFatal("EGL error"); - } - - createScreens(); - -// QSocketNotifier *notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); -// connect(notifier, SIGNAL(activated(int)), this, SLOT(handlePageFlipCompleted())); -} - -QKmsDevice::~QKmsDevice() -{ -} - -void QKmsDevice::createScreens() -{ - drmModeRes *resources = drmModeGetResources(m_fd); - if (!resources) - qFatal("drmModeGetResources failed"); - - //Iterate connectors and create screens on each one active - for (int i = 0; i < resources->count_connectors; i++) { - drmModeConnector *connector = 0; - connector = drmModeGetConnector(m_fd, resources->connectors[i]); - if (connector && connector->connection == DRM_MODE_CONNECTED) { - m_integration->addScreen(new QKmsScreen(this, resources, connector)); - } - drmModeFreeConnector(connector); - } - drmModeFreeResources(resources); -} - -void QKmsDevice::handlePageFlipCompleted() -{ - drmEventContext eventContext; - - memset(&eventContext, 0, sizeof eventContext); - eventContext.version = DRM_EVENT_CONTEXT_VERSION; - eventContext.page_flip_handler = QKmsDevice::pageFlipHandler; - drmHandleEvent(m_fd, &eventContext); - -} - -void QKmsDevice::pageFlipHandler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data) -{ - Q_UNUSED(fd) - Q_UNUSED(frame) - Q_UNUSED(sec) - Q_UNUSED(usec) - - QKmsScreen *screen = static_cast(data); - screen->handlePageFlipped(); -} - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/kms/qkmsdevice.h b/src/plugins/platforms/kms/qkmsdevice.h deleted file mode 100644 index d5e33cb8c7..0000000000 --- a/src/plugins/platforms/kms/qkmsdevice.h +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QKMSDEVICE_H -#define QKMSDEVICE_H - -#include - -extern "C" { -#include -} -#include - -#include - -struct gbm_device; - -QT_BEGIN_NAMESPACE - -class QKmsIntegration; - -class QKmsDevice : public QObject -{ - Q_OBJECT -public: - explicit QKmsDevice(const QString &path, QKmsIntegration *parent); - ~QKmsDevice(); - - EGLDisplay eglDisplay() { return m_eglDisplay; } - gbm_device *gbmDevice() { return m_graphicsBufferManager; } - int fd() const { return m_fd; } - - static void pageFlipHandler(int fd, unsigned int frame, unsigned int sec, - unsigned int usec, void *data); - -public slots: - void handlePageFlipCompleted(); -private: - void createScreens(); - - QKmsIntegration *m_integration; - - EGLDisplay m_eglDisplay; - EGLContext m_eglContext; - gbm_device *m_graphicsBufferManager; - int m_fd; -}; - -QT_END_NAMESPACE - -#endif // QKMSDEVICE_H diff --git a/src/plugins/platforms/kms/qkmsintegration.cpp b/src/plugins/platforms/kms/qkmsintegration.cpp deleted file mode 100644 index f48c868ae5..0000000000 --- a/src/plugins/platforms/kms/qkmsintegration.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qkmsintegration.h" -#include "qkmsdevice.h" -#include "qkmsscreen.h" -#include "qkmswindow.h" -#include "qkmsbackingstore.h" -#include "qkmscontext.h" -#include "qkmsnativeinterface.h" - -#if !defined(QT_NO_EVDEV) -#include -#include -#include -#endif - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -QKmsIntegration::QKmsIntegration() - : QPlatformIntegration(), - m_fontDatabase(new QGenericUnixFontDatabase()), - m_nativeInterface(new QKmsNativeInterface), - m_vtHandler(0), - m_deviceDiscovery(0) -{ -} - -QKmsIntegration::~QKmsIntegration() -{ - delete m_deviceDiscovery; - foreach (QKmsDevice *device, m_devices) { - delete device; - } - foreach (QPlatformScreen *screen, m_screens) { - destroyScreen(screen); - } - delete m_fontDatabase; - delete m_vtHandler; -} - -void QKmsIntegration::initialize() -{ - qputenv("EGL_PLATFORM", "drm"); - m_vtHandler = new QFbVtHandler; - - m_deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_DRM | QDeviceDiscovery::Device_DRM_PrimaryGPU, 0); - if (m_deviceDiscovery) { - QStringList devices = m_deviceDiscovery->scanConnectedDevices(); - foreach (const QString &device, devices) - addDevice(device); - - connect(m_deviceDiscovery, SIGNAL(deviceDetected(QString)), this, SLOT(addDevice(QString))); - connect(m_deviceDiscovery, SIGNAL(deviceRemoved(QString)), this, SLOT(removeDevice(QString))); - } - -#if !defined(QT_NO_EVDEV) - new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString() /* spec */, this); - new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString() /* spec */, this); - new QEvdevTouchScreenHandlerThread(QString() /* spec */, this); -#endif -} - -void QKmsIntegration::addDevice(const QString &deviceNode) -{ - m_devices.append(new QKmsDevice(deviceNode, this)); -} - -void QKmsIntegration::removeDevice(const QString &deviceNode) -{ - // TODO: support hot-plugging some day? - Q_UNUSED(deviceNode); -} - -bool QKmsIntegration::hasCapability(QPlatformIntegration::Capability cap) const -{ - switch (cap) { - case ThreadedPixmaps: return true; - case OpenGL: return true; - case ThreadedOpenGL: return false; - case RasterGLSurface: return true; - default: return QPlatformIntegration::hasCapability(cap); - } -} - -QPlatformOpenGLContext *QKmsIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const -{ - QKmsScreen *screen = static_cast(context->screen()->handle()); - return new QKmsContext(context, screen->device()); -} - -QPlatformWindow *QKmsIntegration::createPlatformWindow(QWindow *window) const -{ - QKmsWindow *w = new QKmsWindow(window); - w->requestActivateWindow(); - return w; -} - -QPlatformBackingStore *QKmsIntegration::createPlatformBackingStore(QWindow *window) const -{ - return new QKmsBackingStore(window); -} - -// Neither a pbuffer nor a hidden QWindow is suitable. Just use an additional, small gbm surface. -QKmsOffscreenWindow::QKmsOffscreenWindow(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface) - : QPlatformOffscreenSurface(offscreenSurface) - , m_format(format) - , m_display(display) - , m_surface(EGL_NO_SURFACE) - , m_window(0) -{ - QKmsScreen *screen = static_cast(offscreenSurface->screen()->handle()); - m_window = gbm_surface_create(screen->device()->gbmDevice(), - 10, 10, - GBM_FORMAT_XRGB8888, - GBM_BO_USE_RENDERING); - if (!m_window) { - qWarning("QKmsOffscreenWindow: Failed to create native window"); - return; - } - - EGLConfig config = q_configFromGLFormat(m_display, m_format); - m_surface = eglCreateWindowSurface(m_display, config, m_window, 0); - if (m_surface != EGL_NO_SURFACE) - m_format = q_glFormatFromConfig(m_display, config); -} - -QKmsOffscreenWindow::~QKmsOffscreenWindow() -{ - if (m_surface != EGL_NO_SURFACE) - eglDestroySurface(m_display, m_surface); - if (m_window) - gbm_surface_destroy((gbm_surface *) m_window); -} - -QPlatformOffscreenSurface *QKmsIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const -{ - QKmsScreen *screen = static_cast(surface->screen()->handle()); - return new QKmsOffscreenWindow(screen->device()->eglDisplay(), QKmsScreen::tweakFormat(surface->format()), surface); -} - -QPlatformFontDatabase *QKmsIntegration::fontDatabase() const -{ - return m_fontDatabase; -} - -void QKmsIntegration::addScreen(QKmsScreen *screen) -{ - m_screens.append(screen); - screenAdded(screen); -} - -QAbstractEventDispatcher *QKmsIntegration::createEventDispatcher() const -{ - return createUnixEventDispatcher(); -} - -QPlatformNativeInterface *QKmsIntegration::nativeInterface() const -{ - return m_nativeInterface; -} - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/kms/qkmsintegration.h b/src/plugins/platforms/kms/qkmsintegration.h deleted file mode 100644 index bcf9ac7296..0000000000 --- a/src/plugins/platforms/kms/qkmsintegration.h +++ /dev/null @@ -1,108 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPLATFORMINTEGRATION_KMS_H -#define QPLATFORMINTEGRATION_KMS_H - -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class QKmsScreen; -class QKmsDevice; -class QFbVtHandler; - -class QKmsOffscreenWindow : public QPlatformOffscreenSurface -{ -public: - QKmsOffscreenWindow(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface); - ~QKmsOffscreenWindow(); - - QSurfaceFormat format() const Q_DECL_OVERRIDE { return m_format; } - bool isValid() const Q_DECL_OVERRIDE { return m_surface != EGL_NO_SURFACE; } - - EGLSurface surface() const { return m_surface; } - -private: - QSurfaceFormat m_format; - EGLDisplay m_display; - EGLSurface m_surface; - EGLNativeWindowType m_window; -}; - -class QKmsIntegration : public QObject, public QPlatformIntegration -{ - Q_OBJECT - -public: - QKmsIntegration(); - ~QKmsIntegration(); - - void initialize() Q_DECL_OVERRIDE; - bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; - - QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE; - QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE; - QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE; - QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const Q_DECL_OVERRIDE; - - QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE; - QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE; - - QPlatformNativeInterface *nativeInterface() const Q_DECL_OVERRIDE; - - void addScreen(QKmsScreen *screen); - QObject *createDevice(const char *); - -private slots: - void addDevice(const QString &deviceNode); - void removeDevice(const QString &deviceNode); - -private: - QStringList findDrmDevices(); - - QList m_screens; - QList m_devices; - QPlatformFontDatabase *m_fontDatabase; - QPlatformNativeInterface *m_nativeInterface; - QFbVtHandler *m_vtHandler; - QDeviceDiscovery *m_deviceDiscovery; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/platforms/kms/qkmsnativeinterface.cpp b/src/plugins/platforms/kms/qkmsnativeinterface.cpp deleted file mode 100644 index 1538a7f8c3..0000000000 --- a/src/plugins/platforms/kms/qkmsnativeinterface.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include "qkmsnativeinterface.h" -#include "qkmsdevice.h" - -#include "qscreen.h" -#include "qkmscontext.h" -#include - -class QKmsResourceMap : public QMap -{ -public: - QKmsResourceMap() - :QMap() - { - insert("egldisplay", QKmsNativeInterface::EglDisplay); - insert("eglcontext", QKmsNativeInterface::EglContext); - } -}; - -Q_GLOBAL_STATIC(QKmsResourceMap, qKmsResourceMap) - -void *QKmsNativeInterface::nativeResourceForIntegration(const QByteArray &resourceString) -{ - QByteArray lowerCaseResource = resourceString.toLower(); - ResourceType resource = qKmsResourceMap()->value(lowerCaseResource); - void *result = 0; - switch (resource) { - case EglDisplay: - result = eglDisplay(); - break; - default: - result = 0; - } - return result; - -} -void *QKmsNativeInterface::nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) -{ - QByteArray lowerCaseResource = resourceString.toLower(); - ResourceType resource = qKmsResourceMap()->value(lowerCaseResource); - void *result = 0; - switch (resource) { - case EglDisplay: - result = eglDisplayForWindow(window); - break; - case EglContext: - result = eglContextForWindow(window); - break; - default: - result = 0; - } - return result; -} - -QPlatformNativeInterface::NativeResourceForContextFunction QKmsNativeInterface::nativeResourceFunctionForContext(const QByteArray &resource) -{ - QByteArray lowerCaseResource = resource.toLower(); - if (lowerCaseResource == "get_egl_context") { - return eglContextForContext; - } - return 0; -} - -void *QKmsNativeInterface::eglDisplay() -{ - //QKmsIntegration *integration = static_cast(QGuiApplicationPrivate::platformIntegration()); - QKmsScreen *screen = static_cast(QGuiApplication::primaryScreen()->handle()); - if (!screen || !screen->device()) - return 0; - return screen->device()->eglDisplay(); -} - -void *QKmsNativeInterface::eglDisplayForWindow(QWindow *window) -{ - QKmsScreen *screen = qPlatformScreenForWindow(window); - if (!screen) - return 0; - QKmsDevice *device = screen->device(); - if (!device) - return 0; - return device->eglDisplay(); -} - -void *QKmsNativeInterface::eglContextForWindow(QWindow *) -{ - return 0; -} - -QKmsScreen *QKmsNativeInterface::qPlatformScreenForWindow(QWindow *window) -{ - QScreen *screen = window ? window->screen() : QGuiApplication::primaryScreen(); - return static_cast(screen->handle()); -} - -void *QKmsNativeInterface::eglContextForContext(QOpenGLContext *context) -{ - Q_ASSERT(context); - - QKmsContext *eglPlatformContext = static_cast(context->handle()); - - return eglPlatformContext->eglContext(); -} diff --git a/src/plugins/platforms/kms/qkmsnativeinterface.h b/src/plugins/platforms/kms/qkmsnativeinterface.h deleted file mode 100644 index 56879d0a3a..0000000000 --- a/src/plugins/platforms/kms/qkmsnativeinterface.h +++ /dev/null @@ -1,64 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QKMSNATIVEINTERFACE_H -#define QKMSNATIVEINTERFACE_H - -#include "qkmsscreen.h" - -#include - -class QKmsNativeInterface : public QPlatformNativeInterface -{ -public: - enum ResourceType { - EglDisplay, - EglContext - }; - - void *nativeResourceForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE; - void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) Q_DECL_OVERRIDE; - - NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource) Q_DECL_OVERRIDE; - - void *eglDisplay(); - void *eglDisplayForWindow(QWindow *window); - void *eglContextForWindow(QWindow *window); - static void *eglContextForContext(QOpenGLContext *context); - -private: - static QKmsScreen *qPlatformScreenForWindow(QWindow *window); -}; - - -#endif // QKMSNATIVEINTERFACE_H diff --git a/src/plugins/platforms/kms/qkmsscreen.cpp b/src/plugins/platforms/kms/qkmsscreen.cpp deleted file mode 100644 index 6392b99cd5..0000000000 --- a/src/plugins/platforms/kms/qkmsscreen.cpp +++ /dev/null @@ -1,275 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qkmsscreen.h" -#include "qkmscursor.h" -#include "qkmsdevice.h" -#include "qkmscontext.h" - -#include - -#include -#include - -QT_BEGIN_NAMESPACE - -Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.kms.screen") - -//Fallback mode (taken from Wayland DRM demo compositor) -static drmModeModeInfo builtin_1024x768 = { - 63500, //clock - 1024, 1072, 1176, 1328, 0, - 768, 771, 775, 798, 0, - 59920, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC, - 0, - "1024x768" -}; - -QKmsScreen::QKmsScreen(QKmsDevice *device, const drmModeRes *resources, const drmModeConnector *connector) - : m_device(device), - m_current_bo(0), - m_next_bo(0), - m_connectorId(connector->connector_id), - m_depth(32), - m_format(QImage::Format_Invalid), - m_eglWindowSurface(EGL_NO_SURFACE), - m_modeSet(false) -{ - m_cursor = new QKmsCursor(this); - initializeScreenMode(resources, connector); -} - -QKmsScreen::~QKmsScreen() -{ - delete m_cursor; - drmModeSetCrtc(m_device->fd(), m_oldCrtc->crtc_id, m_oldCrtc->buffer_id, - m_oldCrtc->x, m_oldCrtc->y, - &m_connectorId, 1, &m_oldCrtc->mode); - drmModeFreeCrtc(m_oldCrtc); - if (m_eglWindowSurface != EGL_NO_SURFACE) - eglDestroySurface(m_device->eglDisplay(), m_eglWindowSurface); - gbm_surface_destroy(m_gbmSurface); -} - -QRect QKmsScreen::geometry() const -{ - return m_geometry; -} - -int QKmsScreen::depth() const -{ - return m_depth; -} - -QImage::Format QKmsScreen::format() const -{ - return m_format; -} - -QSizeF QKmsScreen::physicalSize() const -{ - return m_physicalSize; -} - -QPlatformCursor *QKmsScreen::cursor() const -{ - return m_cursor; -} - -void QKmsScreen::initializeScreenMode(const drmModeRes *resources, const drmModeConnector *connector) -{ - //Determine optimal mode for screen - drmModeModeInfo *mode = 0; - for (int i = 0; i < connector->count_modes; ++i) { - if (connector->modes[i].type & DRM_MODE_TYPE_PREFERRED) { - mode = &connector->modes[i]; - break; - } - } - if (!mode) { - if (connector->count_modes > 0) - mode = &connector->modes[0]; - else - mode = &builtin_1024x768; - } - - drmModeEncoder *encoder = drmModeGetEncoder(m_device->fd(), connector->encoders[0]); - if (encoder == 0) - qFatal("No encoder for connector."); - - int i; - for (i = 0; i < resources->count_crtcs; i++) { - if (encoder->possible_crtcs & (1 << i)) - break; - } - if (i == resources->count_crtcs) - qFatal("No usable crtc for encoder."); - - m_oldCrtc = drmModeGetCrtc(m_device->fd(), encoder->crtc_id); - - m_crtcId = resources->crtcs[i]; - m_mode = *mode; - m_geometry = QRect(0, 0, m_mode.hdisplay, m_mode.vdisplay); - qCDebug(lcQpaScreen) << "kms initialized with geometry" << m_geometry; - m_depth = 32; - m_format = QImage::Format_RGB32; - m_physicalSize = QSizeF(connector->mmWidth, connector->mmHeight); - - m_gbmSurface = gbm_surface_create(m_device->gbmDevice(), - m_mode.hdisplay, m_mode.vdisplay, - GBM_BO_FORMAT_XRGB8888, - GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); - - qCDebug(lcQpaScreen) << "created gbm surface" << m_gbmSurface << m_mode.hdisplay << m_mode.vdisplay; - //Cleanup - drmModeFreeEncoder(encoder); -} - -QSurfaceFormat QKmsScreen::tweakFormat(const QSurfaceFormat &format) -{ - QSurfaceFormat fmt = format; - fmt.setRedBufferSize(8); - fmt.setGreenBufferSize(8); - fmt.setBlueBufferSize(8); - if (fmt.alphaBufferSize() != -1) - fmt.setAlphaBufferSize(8); - return fmt; -} - -void QKmsScreen::initializeWithFormat(const QSurfaceFormat &format) -{ - EGLDisplay display = m_device->eglDisplay(); - EGLConfig config = q_configFromGLFormat(display, tweakFormat(format)); - - m_eglWindowSurface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)m_gbmSurface, NULL); - qCDebug(lcQpaScreen) << "created window surface"; - m_surfaceFormat = q_glFormatFromConfig(display, config); -} - -void QKmsScreen::swapBuffers() -{ - eglSwapBuffers(m_device->eglDisplay(), m_eglWindowSurface); - - m_next_bo = gbm_surface_lock_front_buffer(m_gbmSurface); - if (!m_next_bo) - qFatal("kms: Failed to lock front buffer"); - - performPageFlip(); -} - -void QKmsScreen::performPageFlip() -{ - if (!m_next_bo) - return; - - uint32_t width = gbm_bo_get_width(m_next_bo); - uint32_t height = gbm_bo_get_height(m_next_bo); - uint32_t stride = gbm_bo_get_stride(m_next_bo); - uint32_t handle = gbm_bo_get_handle(m_next_bo).u32; - - uint32_t fb_id; - int ret = drmModeAddFB(m_device->fd(), width, height, 24, 32, - stride, handle, &fb_id); - if (ret) { - qFatal("kms: Failed to create fb: fd %d, w %d, h %d, stride %d, handle %d, ret %d", - m_device->fd(), width, height, stride, handle, ret); - } - - if (!m_modeSet) { - //Set the Mode of the screen. - int ret = drmModeSetCrtc(m_device->fd(), m_crtcId, fb_id, - 0, 0, &m_connectorId, 1, &m_mode); - if (ret) - qFatal("failed to set mode"); - m_modeSet = true; - - // Initialize cursor - - static int hideCursor = qEnvironmentVariableIntValue("QT_QPA_KMS_HIDECURSOR"); - if (!hideCursor) { - QCursor cursor(Qt::ArrowCursor); - m_cursor->changeCursor(&cursor, 0); - } - } - - int pageFlipStatus = drmModePageFlip(m_device->fd(), m_crtcId, - fb_id, - DRM_MODE_PAGE_FLIP_EVENT, this); - if (pageFlipStatus) - { - qWarning("Pageflip status: %d", pageFlipStatus); - gbm_surface_release_buffer(m_gbmSurface, m_next_bo); - m_next_bo = 0; - } -} - -void QKmsScreen::handlePageFlipped() -{ - if (m_current_bo) - gbm_surface_release_buffer(m_gbmSurface, m_current_bo); - - m_current_bo = m_next_bo; - m_next_bo = 0; -} - -QKmsDevice * QKmsScreen::device() const -{ - return m_device; -} - -void QKmsScreen::waitForPageFlipComplete() -{ - while (m_next_bo) { -#if 0 - //Check manually if there is something to be read on the device - //as there are senarios where the signal is not received (starvation) - fd_set fdSet; - timeval timeValue; - int returnValue; - - FD_ZERO(&fdSet); - FD_SET(m_device->fd(), &fdSet); - timeValue.tv_sec = 0; - timeValue.tv_usec = 1000; - - returnValue = select(1, &fdSet, 0, 0, &timeValue); - printf("select returns %d\n", returnValue); -#endif - - m_device->handlePageFlipCompleted(); - } -} - - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/kms/qkmsscreen.h b/src/plugins/platforms/kms/qkmsscreen.h deleted file mode 100644 index c52d0211b3..0000000000 --- a/src/plugins/platforms/kms/qkmsscreen.h +++ /dev/null @@ -1,122 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QKMSSCREEN_H -#define QKMSSCREEN_H - -#include - -#define EGL_EGLEXT_PROTOTYPES 1 -#define GL_GLEXT_PROTOTYPES 1 - -extern "C" { -#include -#include -#include -} - -#include -#include -#include -#include -#include - -#include - -QT_BEGIN_NAMESPACE - -Q_DECLARE_LOGGING_CATEGORY(lcQpaScreen) - -class QKmsCursor; -class QKmsDevice; -class QKmsContext; - -class QKmsScreen : public QPlatformScreen -{ -public: - QKmsScreen(QKmsDevice *device, const drmModeRes *resources, const drmModeConnector *connector); - ~QKmsScreen(); - - QRect geometry() const Q_DECL_OVERRIDE; - int depth() const Q_DECL_OVERRIDE; - QImage::Format format() const Q_DECL_OVERRIDE; - QSizeF physicalSize() const Q_DECL_OVERRIDE; - QPlatformCursor *cursor() const Q_DECL_OVERRIDE; - - quint32 crtcId() const { return m_crtcId; } - QKmsDevice *device() const; - - void initializeWithFormat(const QSurfaceFormat &format); - - //Called by context for each screen - void swapBuffers(); - void handlePageFlipped(); - - EGLSurface eglSurface() const { return m_eglWindowSurface; } - - void waitForPageFlipComplete(); - - static QSurfaceFormat tweakFormat(const QSurfaceFormat &format); - - QSurfaceFormat surfaceFormat() const { return m_surfaceFormat; } - -private: - void performPageFlip(); - void initializeScreenMode(const drmModeRes *resources, const drmModeConnector *connector); - - QKmsDevice *m_device; - gbm_bo *m_current_bo; - gbm_bo *m_next_bo; - quint32 m_connectorId; - - quint32 m_crtcId; - drmModeModeInfo m_mode; - QRect m_geometry; - QSizeF m_physicalSize; - int m_depth; - QImage::Format m_format; - - drmModeCrtcPtr m_oldCrtc; - - QKmsCursor *m_cursor; - - gbm_surface *m_gbmSurface; - EGLSurface m_eglWindowSurface; - - bool m_modeSet; - QSurfaceFormat m_surfaceFormat; -}; - -QT_END_NAMESPACE - -#endif // QKMSSCREEN_H diff --git a/src/plugins/platforms/kms/qkmswindow.cpp b/src/plugins/platforms/kms/qkmswindow.cpp deleted file mode 100644 index 3b01dfedca..0000000000 --- a/src/plugins/platforms/kms/qkmswindow.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qkmswindow.h" -#include "qkmsscreen.h" - -#include -#include - -QT_BEGIN_NAMESPACE - -QKmsWindow::QKmsWindow(QWindow *window) - : QPlatformWindow(window) -{ - Q_D(QPlatformWindow); - m_screen = QPlatformScreen::platformScreenForWindow(window); - static_cast(m_screen)->initializeWithFormat(window->requestedFormat()); - setGeometry(d->rect); // rect is set to window->geometry() in base ctor -} - -void QKmsWindow::setGeometry(const QRect &rect) -{ - // All windows must be fullscreen - QRect fullscreenRect = m_screen->availableGeometry(); - if (rect != fullscreenRect) - QWindowSystemInterface::handleGeometryChange(window(), fullscreenRect); - - QPlatformWindow::setGeometry(fullscreenRect); -} - -QSurfaceFormat QKmsWindow::format() const -{ - return static_cast(m_screen)->surfaceFormat(); -} - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/kms/qkmswindow.h b/src/plugins/platforms/kms/qkmswindow.h deleted file mode 100644 index aec6d55b5d..0000000000 --- a/src/plugins/platforms/kms/qkmswindow.h +++ /dev/null @@ -1,57 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QKMSWINDOW_H -#define QKMSWINDOW_H - -#include - -QT_BEGIN_NAMESPACE - -class QKmsWindow : public QPlatformWindow -{ - Q_DECLARE_PRIVATE(QPlatformWindow) - -public: - QKmsWindow(QWindow *window); - - void setGeometry(const QRect &rect) Q_DECL_OVERRIDE; - QSurfaceFormat format() const Q_DECL_OVERRIDE; - -private: - QPlatformScreen *m_screen; -}; - -QT_END_NAMESPACE - -#endif // QKMSWINDOW_H -- cgit v1.2.3 From 31fb4379c81c58fe471fc7d8e799a6a00c4b4ba0 Mon Sep 17 00:00:00 2001 From: Louai Al-Khanji Date: Mon, 24 Aug 2015 12:04:57 +0300 Subject: Fix module reference in license header Change-Id: I8efa30869e716d827e8463ef4285f8ff9357cc0e Reviewed-by: Laszlo Agocs --- src/gui/kernel/qplatformcursor.cpp | 2 +- src/gui/kernel/qplatformcursor.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qplatformcursor.cpp b/src/gui/kernel/qplatformcursor.cpp index 7239ac7ba4..cd43fc42fe 100644 --- a/src/gui/kernel/qplatformcursor.cpp +++ b/src/gui/kernel/qplatformcursor.cpp @@ -3,7 +3,7 @@ ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** -** This file is part of the QtOpenVG module of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage diff --git a/src/gui/kernel/qplatformcursor.h b/src/gui/kernel/qplatformcursor.h index 4f4f9cc6ae..8c788fd27b 100644 --- a/src/gui/kernel/qplatformcursor.h +++ b/src/gui/kernel/qplatformcursor.h @@ -3,7 +3,7 @@ ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** -** This file is part of the QtOpenVG module of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage -- cgit v1.2.3 From b46fe39d940712c5d401e731e171a7ccfadfe648 Mon Sep 17 00:00:00 2001 From: Bernd Weimer Date: Mon, 23 Mar 2015 11:53:16 +0100 Subject: Harmonize input context selection Input context selection works differently across platforms. On some platforms it is not possible to request a specific context at all (e.g. Wayland). This will be unified, depending on the environment variable "QT_IM_MODULE", you will get: - null: default (platform) context, if defined (otherwise no context) - empty: no context - set: set one, if it exists and is valid (otherwise no context) [ChangeLog][Platform Specific Changes] Haromnized input context selection. QT_IM_MODULE environment variable will be taken into account. Change-Id: Ic8f826fbc6ace25941cd19b9b086943e848fbe01 Reviewed-by: Lars Knoll Reviewed-by: Nedim Hadzic --- src/gui/kernel/qplatforminputcontextfactory.cpp | 44 +++++++--------------- src/gui/kernel/qplatforminputcontextfactory_p.h | 1 + src/plugins/platforms/cocoa/qcocoaintegration.mm | 7 ++-- .../platforms/windows/qwindowsintegration.cpp | 7 ++-- src/plugins/platforms/xcb/qxcbconnection.cpp | 3 -- src/plugins/platforms/xcb/qxcbintegration.cpp | 5 ++- 6 files changed, 26 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qplatforminputcontextfactory.cpp b/src/gui/kernel/qplatforminputcontextfactory.cpp index a7660e76ae..9d55b778ce 100644 --- a/src/gui/kernel/qplatforminputcontextfactory.cpp +++ b/src/gui/kernel/qplatforminputcontextfactory.cpp @@ -56,48 +56,32 @@ QStringList QPlatformInputContextFactory::keys() #endif } -QPlatformInputContext *QPlatformInputContextFactory::create(const QString& key) +QString QPlatformInputContextFactory::requested() { - QStringList paramList = key.split(QLatin1Char(':')); - const QString platform = paramList.takeFirst().toLower(); - -#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS) - if (QPlatformInputContext *ret = qLoadPlugin1(loader(), platform, paramList)) - return ret; -#endif - return 0; + QByteArray env = qgetenv("QT_IM_MODULE"); + return env.isNull() ? QString() : QString::fromLocal8Bit(env); } -QPlatformInputContext *QPlatformInputContextFactory::create() +QPlatformInputContext *QPlatformInputContextFactory::create(const QString& key) { - QPlatformInputContext *ic = 0; - - QString icString = QString::fromLatin1(qgetenv("QT_IM_MODULE")); - - if (icString == QLatin1String("none")) - return 0; +#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS) + QStringList paramList = key.split(QLatin1Char(':')); + const QString platform = paramList.takeFirst().toLower(); - ic = create(icString); + QPlatformInputContext *ic = qLoadPlugin1 + (loader(), platform, paramList); if (ic && ic->isValid()) return ic; delete ic; - ic = 0; - - QStringList k = keys(); - for (int i = 0; i < k.size(); ++i) { - if (k.at(i) == icString) - continue; - ic = create(k.at(i)); - if (ic && ic->isValid()) - return ic; - delete ic; - ic = 0; - } - +#endif return 0; } +QPlatformInputContext *QPlatformInputContextFactory::create() +{ + return create(requested()); +} QT_END_NAMESPACE diff --git a/src/gui/kernel/qplatforminputcontextfactory_p.h b/src/gui/kernel/qplatforminputcontextfactory_p.h index a74c4f5f80..38f4358287 100644 --- a/src/gui/kernel/qplatforminputcontextfactory_p.h +++ b/src/gui/kernel/qplatforminputcontextfactory_p.h @@ -56,6 +56,7 @@ class Q_GUI_EXPORT QPlatformInputContextFactory { public: static QStringList keys(); + static QString requested(); static QPlatformInputContext *create(const QString &key); static QPlatformInputContext *create(); }; diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 2e6bfc95db..051a1c8710 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -47,6 +47,7 @@ #include "qcocoamimetypes.h" #include "qcocoaaccessibility.h" +#include #include #include #include @@ -286,9 +287,9 @@ QCocoaIntegration::QCocoaIntegration(const QStringList ¶mList) qWarning("Creating multiple Cocoa platform integrations is not supported"); mInstance = this; - mInputContext.reset(QPlatformInputContextFactory::create()); - if (mInputContext.isNull()) - mInputContext.reset(new QCocoaInputContext()); + QString icStr = QPlatformInputContextFactory::requested(); + icStr.isNull() ? mInputContext.reset(new QCocoaInputContext) + : mInputContext.reset(QPlatformInputContextFactory::create(icStr)); initResources(); QMacAutoReleasePool pool; diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index f97c23c207..bbb1f68a52 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -264,10 +264,9 @@ QWindowsIntegration::~QWindowsIntegration() void QWindowsIntegration::initialize() { - if (QPlatformInputContext *pluginContext = QPlatformInputContextFactory::create()) - d->m_inputContext.reset(pluginContext); - else - d->m_inputContext.reset(new QWindowsInputContext); + QString icStr = QPlatformInputContextFactory::requested(); + icStr.isNull() ? d->m_inputContext.reset(new QWindowsInputContext) + : d->m_inputContext.reset(QPlatformInputContextFactory::create(icStr)); } bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) const diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 15d3575e60..e612cff9a3 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -590,9 +590,6 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra qCDebug(QT_XCB_GLINTEGRATION) << "Failed to create xcb gl-integration"; sync(); - - if (qEnvironmentVariableIsEmpty("QT_IM_MODULE")) - qputenv("QT_IM_MODULE", QByteArray("compose")); } QXcbConnection::~QXcbConnection() diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index fc06f1a7b0..9cedfa77ad 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -268,7 +268,10 @@ void QXcbIntegration::initialize() { // Perform everything that may potentially need the event dispatcher (timers, socket // notifiers) here instead of the constructor. - m_inputContext.reset(QPlatformInputContextFactory::create()); + QString icStr = QPlatformInputContextFactory::requested(); + if (icStr.isNull()) + icStr = QLatin1String("compose"); + m_inputContext.reset(QPlatformInputContextFactory::create(icStr)); } void QXcbIntegration::moveToScreen(QWindow *window, int screen) -- cgit v1.2.3 From bc867b179451a4c06c669f03f4598ea8799ad9f6 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 24 Aug 2015 11:57:31 +0200 Subject: QWindowsMimeImage: Revert image format handling back to Qt 4. Effectively revert 9150563940f61be9fb17510be49c0734244866a5 for QTBUG-11463 (offering only CF_DIB5 for images of format ARGB32) and 4018cd3529ded32f3434095a2da2568d52dfe16a for QTBUG-46848 adding support for "PNG". The changes broke pasting images into MS Office since it can only handle plain CF_DIB and gets confused if "PNG" is returned as available format. Task-number: QTBUG-47656 Task-number: QTBUG-11463 Task-number: QTBUG-46848 Change-Id: I9b641b4b912b7b16a2f58bc84fa09c28a64e91c8 Reviewed-by: aavit --- src/plugins/platforms/windows/qwindowsmime.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp index f86ab9fee3..622352e987 100644 --- a/src/plugins/platforms/windows/qwindowsmime.cpp +++ b/src/plugins/platforms/windows/qwindowsmime.cpp @@ -990,12 +990,11 @@ QVector QWindowsMimeImage::formatsForMime(const QString &mimeType, co { QVector formatetcs; if (mimeData->hasImage() && mimeType == QLatin1String("application/x-qt-image")) { - //add DIBV5 if image has alpha channel + //add DIBV5 if image has alpha channel. Do not add CF_PNG here as it will confuse MS Office (QTBUG47656). QImage image = qvariant_cast(mimeData->imageData()); if (!image.isNull() && image.hasAlphaChannel()) formatetcs += setCf(CF_DIBV5); formatetcs += setCf(CF_DIB); - formatetcs += setCf(CF_PNG); // QTBUG-86848, Paste into GIMP queries for PNG. } return formatetcs; } @@ -1024,11 +1023,7 @@ bool QWindowsMimeImage::canConvertFromMime(const FORMATETC &formatetc, const QMi const QImage image = qvariant_cast(mimeData->imageData()); if (image.isNull()) return false; - // QTBUG-11463, deny CF_DIB support for images with alpha to prevent loss of - // transparency in conversion. - return cf == CF_DIBV5 - || (cf == CF_DIB && !image.hasAlphaChannel()) - || cf == int(CF_PNG); + return cf == CF_DIBV5 || (cf == CF_DIB) || cf == int(CF_PNG); } bool QWindowsMimeImage::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const -- cgit v1.2.3 From ffbc2d3dc06017959167feecd60b66891c3b2c7b Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Wed, 19 Aug 2015 14:56:08 +0200 Subject: Doc: Mention Windows limitations in QFileInfo permission methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The limitation is already mentioned in the class documentation, but IMO is severe enough to be highlighted in the documentation of the respective methods, too. Change-Id: I16c68eb41ab9d3a7698d7ef06f747cfd98a8aaff Reviewed-by: Oswald Buddenhagen Reviewed-by: Topi Reiniö --- src/corelib/io/qfileinfo.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp index 8a86ec5858..51b39b1114 100644 --- a/src/corelib/io/qfileinfo.cpp +++ b/src/corelib/io/qfileinfo.cpp @@ -263,6 +263,7 @@ QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request) groupId(). You can examine a file's permissions and ownership in a single statement using the permission() function. + \target NTFS permissions \note On NTFS file systems, ownership and permissions checking is disabled by default for performance reasons. To enable it, include the following line: @@ -893,6 +894,9 @@ QDir QFileInfo::absoluteDir() const /*! Returns \c true if the user can read the file; otherwise returns \c false. + \note If the \l{NTFS permissions} check has not been enabled, the result + on Windows will merely reflect whether the file exists. + \sa isWritable(), isExecutable(), permission() */ bool QFileInfo::isReadable() const @@ -911,6 +915,9 @@ bool QFileInfo::isReadable() const /*! Returns \c true if the user can write to the file; otherwise returns \c false. + \note If the \l{NTFS permissions} check has not been enabled, the result on + Windows will merely reflect whether the file is marked as Read Only. + \sa isReadable(), isExecutable(), permission() */ bool QFileInfo::isWritable() const @@ -1137,7 +1144,8 @@ QString QFileInfo::readLink() const returned. This function can be time consuming under Unix (in the order of - milliseconds). + milliseconds). On Windows, it will return an empty string unless + the \l{NTFS permissions} check has been enabled. \sa ownerId(), group(), groupId() */ @@ -1217,6 +1225,9 @@ uint QFileInfo::groupId() const On systems where files do not have permissions this function always returns \c true. + \note The result might be inaccurate on Windows if the + \l{NTFS permissions} check has not been enabled. + Example: \snippet code/src_corelib_io_qfileinfo.cpp 10 @@ -1240,6 +1251,9 @@ bool QFileInfo::permission(QFile::Permissions permissions) const /*! Returns the complete OR-ed together combination of QFile::Permissions for the file. + + \note The result might be inaccurate on Windows if the + \l{NTFS permissions} check has not been enabled. */ QFile::Permissions QFileInfo::permissions() const { -- cgit v1.2.3 From df276787d5bb191da62db632efaeb4256fa5da27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Martins?= Date: Fri, 26 Jun 2015 20:40:50 +0100 Subject: QRasterPaintEngine: Don't detach QImage Caught being detached a few thousand times per second. Change-Id: I6dd5fd69d7d4f32048cdb7e4ac707f24df6c15f8 (cherry picked from commit 2a81516835c680c29f3de9241a8c28027624ce4f) Reviewed-by: Konstantin Ritt Reviewed-by: Allan Sandfeld Jensen --- src/gui/painting/qpaintengine_raster.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index aabf4a9427..a5957ca86e 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -2756,12 +2756,12 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, QFixed spp = fontEngine->subPixelPositionForX(positions[i].x); QPoint offset; - QImage *alphaMap = fontEngine->lockedAlphaMapForGlyph(glyphs[i], spp, neededFormat, s->matrix, - &offset); + const QImage *alphaMap = fontEngine->lockedAlphaMapForGlyph(glyphs[i], spp, neededFormat, s->matrix, + &offset); if (alphaMap == 0 || alphaMap->isNull()) continue; - alphaPenBlt(alphaMap->bits(), alphaMap->bytesPerLine(), alphaMap->depth(), + alphaPenBlt(alphaMap->constBits(), alphaMap->bytesPerLine(), alphaMap->depth(), qFloor(positions[i].x) + offset.x(), qRound(positions[i].y) + offset.y(), alphaMap->width(), alphaMap->height()); -- cgit v1.2.3 From 2518c4c9079efdaa10f33c3c049f62f0c0c44373 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Fri, 7 Aug 2015 11:01:09 +0200 Subject: iOS: calculate bounds in desktop view using transformed window bounds for both width and height MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Depending on the orientation, UIKit might shrink either the width or the height of the view to fit the status bar. Since we anyway want the view to fill the whole window, we simply ignore this, and use the bounds of the whole window directly. Task-number: QTBUG-47506 Change-Id: I73294e5792f8d98fb0c0b0a42198207baca08e3c Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiosviewcontroller.mm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm index 6667ec3dd8..a7068b9246 100644 --- a/src/plugins/platforms/ios/qiosviewcontroller.mm +++ b/src/plugins/platforms/ios/qiosviewcontroller.mm @@ -190,8 +190,9 @@ - (void)setBounds:(CGRect)newBounds { + Q_UNUSED(newBounds); CGRect transformedWindowBounds = [self convertRect:self.window.bounds fromView:self.window]; - [super setBounds:CGRectMake(0, 0, CGRectGetWidth(newBounds), CGRectGetHeight(transformedWindowBounds))]; + [super setBounds:CGRectMake(0, 0, CGRectGetWidth(transformedWindowBounds), CGRectGetHeight(transformedWindowBounds))]; } - (void)setCenter:(CGPoint)newCenter -- cgit v1.2.3 From b14550fa45395d6b57d958bb4a4e42212ba0da0f Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 20 Aug 2015 14:51:53 +0200 Subject: Windows/Input context: Update enabling of IME in in update(), too. Amend change b55f88caba339a49bf0ebabfa324dde523c2b866 by splitting out the enabling into a separate function and call that when QWindowsInputContext::update() is triggered to reflect updates of the microfocus in QGraphicsView or item view widgets. Task-number: QTBUG-47679 Task-number: QTBUG-47705 Task-number: QTBUG-40691 Change-Id: I84a6647944f1aaedcd72d7060cc90e29a177f577 Reviewed-by: Liang Qi Reviewed-by: Andy Shaw --- src/plugins/platforms/windows/qwindowsinputcontext.cpp | 17 ++++++++++++++--- src/plugins/platforms/windows/qwindowsinputcontext.h | 1 + 2 files changed, 15 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index c943438570..68e38dc4a6 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -200,18 +200,27 @@ void QWindowsInputContext::reset() doneContext(); } -void QWindowsInputContext::setFocusObject(QObject *object) +void QWindowsInputContext::setFocusObject(QObject *) { // ### fixme: On Windows 8.1, it has been observed that the Input context // remains active when this happens resulting in a lock-up. Consecutive // key events still have VK_PROCESSKEY set and are thus ignored. if (m_compositionContext.isComposing) reset(); + updateEnabled(); +} +void QWindowsInputContext::updateEnabled() +{ + if (!QGuiApplication::focusObject()) + return; const QWindow *window = QGuiApplication::focusWindow(); - if (object && window && window->handle()) { + if (window && window->handle()) { QWindowsWindow *platformWindow = QWindowsWindow::baseWindowOf(window); - if (inputMethodAccepted()) { + const bool accepted = inputMethodAccepted(); + if (QWindowsContext::verbose > 1) + qCDebug(lcQpaInputMethods) << __FUNCTION__ << window << "accepted=" << accepted; + if (accepted) { // Re-enable IME by associating default context saved on first disabling. if (platformWindow->testFlag(QWindowsWindow::InputMethodDisabled)) { ImmAssociateContext(platformWindow->handle(), QWindowsInputContext::m_defaultContext); @@ -235,6 +244,8 @@ void QWindowsInputContext::setFocusObject(QObject *object) void QWindowsInputContext::update(Qt::InputMethodQueries queries) { + if (queries & Qt::ImEnabled) + updateEnabled(); QPlatformInputContext::update(queries); } diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.h b/src/plugins/platforms/windows/qwindowsinputcontext.h index 83a39989f6..110986c20c 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.h +++ b/src/plugins/platforms/windows/qwindowsinputcontext.h @@ -87,6 +87,7 @@ private: void doneContext(); void startContextComposition(); void endContextComposition(); + void updateEnabled(); const DWORD m_WM_MSIME_MOUSE; static HIMC m_defaultContext; -- cgit v1.2.3 From 4c3fa449acfc7ec43f3b2c53318c2838ceba5a86 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 17 Aug 2015 13:18:28 +0200 Subject: Fix potential crash in QWindowsWindow::setDropSiteEnabled(). Release drop target after CoLockObjectExternal() to prevent a potential access violation. Change-Id: I2c3bde9f8008b1d567544596f56ebfd61fe6ad86 Task-number: QTBUG-47737 Reviewed-by: Joerg Bornemann --- src/plugins/platforms/windows/qwindowswindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 853cf036a7..288f73cb8f 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1034,8 +1034,8 @@ void QWindowsWindow::setDropSiteEnabled(bool dropEnabled) RegisterDragDrop(m_data.hwnd, m_dropTarget); CoLockObjectExternal(m_dropTarget, true, true); } else { - m_dropTarget->Release(); CoLockObjectExternal(m_dropTarget, false, true); + m_dropTarget->Release(); RevokeDragDrop(m_data.hwnd); m_dropTarget = 0; } -- cgit v1.2.3 From dbb1e1936ca9ddc66d2032448da63edec651a77a Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Mon, 24 Aug 2015 10:53:00 +0200 Subject: Bump PCRE to r1594 Get a couple of fixes for important bugs (1667, 1672). The WinCE build patch has also been merged upstream, so remove it from our tree. Change-Id: I933c2d824612a70d7bc52648df5f5c481ae066d7 Reviewed-by: Lars Knoll Reviewed-by: Richard J. Moore --- .../patches/0001-Re-fix-X86-Wince-builds.patch | 35 --- src/3rdparty/pcre/pcre.h | 6 +- src/3rdparty/pcre/pcre_compile.c | 271 ++++++++++++------ src/3rdparty/pcre/pcre_exec.c | 3 +- src/3rdparty/pcre/pcre_internal.h | 17 +- src/3rdparty/pcre/pcre_jit_compile.c | 58 +++- src/3rdparty/pcre/pcre_study.c | 19 +- src/3rdparty/pcre/sljit/sljitConfig.h | 9 + src/3rdparty/pcre/sljit/sljitConfigInternal.h | 13 +- src/3rdparty/pcre/sljit/sljitLir.c | 10 +- src/3rdparty/pcre/sljit/sljitLir.h | 40 ++- src/3rdparty/pcre/sljit/sljitNativeARM_32.c | 27 +- src/3rdparty/pcre/sljit/sljitNativeARM_64.c | 48 +++- src/3rdparty/pcre/sljit/sljitNativeARM_T2_32.c | 58 +++- src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c | 15 +- src/3rdparty/pcre/sljit/sljitNativePPC_common.c | 23 +- src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c | 19 +- src/3rdparty/pcre/sljit/sljitNativeTILEGX_64.c | 311 ++++++++++----------- src/3rdparty/pcre/sljit/sljitNativeX86_common.c | 59 ++-- 19 files changed, 643 insertions(+), 398 deletions(-) delete mode 100644 src/3rdparty/pcre/patches/0001-Re-fix-X86-Wince-builds.patch (limited to 'src') diff --git a/src/3rdparty/pcre/patches/0001-Re-fix-X86-Wince-builds.patch b/src/3rdparty/pcre/patches/0001-Re-fix-X86-Wince-builds.patch deleted file mode 100644 index 8cb3c8c608..0000000000 --- a/src/3rdparty/pcre/patches/0001-Re-fix-X86-Wince-builds.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 121e4d1ad09bdbfeb8a871d4f2c3ffe1acb8e2d6 Mon Sep 17 00:00:00 2001 -From: Giuseppe D'Angelo -Date: Tue, 30 Jun 2015 09:41:39 +0200 -Subject: [PATCH] Re-fix X86 Wince builds. - -eebb8de21ce4845866f15e444a4c78fc2cbb7f3f fixed the PCRE -build, but was accidentally overwritten by a subsequent -import of the PCRE tarball. - -Now put the same patch also into patches/ so that we don't -forget it needs to be manually applied. - -Change-Id: I93c2ee9c2e2dd1c48d391ce7e16d33208fb2cbbb ---- - src/3rdparty/pcre/sljit/sljitNativeX86_common.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/src/3rdparty/pcre/sljit/sljitNativeX86_common.c b/src/3rdparty/pcre/sljit/sljitNativeX86_common.c -index 22a163f..21b276f 100644 ---- a/src/3rdparty/pcre/sljit/sljitNativeX86_common.c -+++ b/src/3rdparty/pcre/sljit/sljitNativeX86_common.c -@@ -273,7 +273,9 @@ static sljit_si cpu_has_sse2 = -1; - #endif - static sljit_si cpu_has_cmov = -1; - --#if defined(_MSC_VER) && _MSC_VER >= 1400 -+#ifdef _WIN32_WCE -+#include -+#elif defined(_MSC_VER) && _MSC_VER >= 1400 - #include - #endif - --- -1.9.1 - diff --git a/src/3rdparty/pcre/pcre.h b/src/3rdparty/pcre/pcre.h index 58ed46a2a3..c2557cf4b1 100644 --- a/src/3rdparty/pcre/pcre.h +++ b/src/3rdparty/pcre/pcre.h @@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE. /* The current PCRE version information. */ #define PCRE_MAJOR 8 -#define PCRE_MINOR 37 -#define PCRE_PRERELEASE -#define PCRE_DATE 2015-04-28 +#define PCRE_MINOR 38 +#define PCRE_PRERELEASE -RC1 +#define PCRE_DATE 2015-05-03 /* When an application links to a PCRE DLL in Windows, the symbols that are imported have to be identified as such. When building PCRE, the appropriate diff --git a/src/3rdparty/pcre/pcre_compile.c b/src/3rdparty/pcre/pcre_compile.c index 0efad2645d..866aa8c693 100644 --- a/src/3rdparty/pcre/pcre_compile.c +++ b/src/3rdparty/pcre/pcre_compile.c @@ -174,7 +174,7 @@ static const short int escapes[] = { -ESC_Z, CHAR_LEFT_SQUARE_BRACKET, CHAR_BACKSLASH, CHAR_RIGHT_SQUARE_BRACKET, CHAR_CIRCUMFLEX_ACCENT, CHAR_UNDERSCORE, - CHAR_GRAVE_ACCENT, 7, + CHAR_GRAVE_ACCENT, ESC_a, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0, @@ -202,9 +202,9 @@ static const short int escapes[] = { /* 68 */ 0, 0, '|', ',', '%', '_', '>', '?', /* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 78 */ 0, '`', ':', '#', '@', '\'', '=', '"', -/* 80 */ 0, 7, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0, +/* 80 */ 0, ESC_a, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0, /* 88 */-ESC_h, 0, 0, '{', 0, 0, 0, 0, -/* 90 */ 0, 0, -ESC_k, 'l', 0, ESC_n, 0, -ESC_p, +/* 90 */ 0, 0, -ESC_k, 0, 0, ESC_n, 0, -ESC_p, /* 98 */ 0, ESC_r, 0, '}', 0, 0, 0, 0, /* A0 */ 0, '~', -ESC_s, ESC_tee, 0,-ESC_v, -ESC_w, 0, /* A8 */ 0,-ESC_z, 0, 0, 0, '[', 0, 0, @@ -219,6 +219,12 @@ static const short int escapes[] = { /* F0 */ 0, 0, 0, 0, 0, 0, 0, 0, /* F8 */ 0, 0, 0, 0, 0, 0, 0, 0 }; + +/* We also need a table of characters that may follow \c in an EBCDIC +environment for characters 0-31. */ + +static unsigned char ebcdic_escape_c[] = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"; + #endif @@ -458,7 +464,7 @@ static const char error_texts[] = "range out of order in character class\0" "nothing to repeat\0" /* 10 */ - "operand of unlimited repeat could match the empty string\0" /** DEAD **/ + "internal error: invalid forward reference offset\0" "internal error: unexpected repeat\0" "unrecognized character after (? or (?-\0" "POSIX named classes are supported only within a class\0" @@ -527,7 +533,11 @@ static const char error_texts[] = "different names for subpatterns of the same number are not allowed\0" "(*MARK) must have an argument\0" "this version of PCRE is not compiled with Unicode property support\0" +#ifndef EBCDIC "\\c must be followed by an ASCII character\0" +#else + "\\c must be followed by a letter or one of [\\]^_?\0" +#endif "\\k is not followed by a braced, angle-bracketed, or quoted name\0" /* 70 */ "internal error: unknown opcode in find_fixedlength()\0" @@ -1425,7 +1435,16 @@ else c ^= 0x40; #else /* EBCDIC coding */ if (c >= CHAR_a && c <= CHAR_z) c += 64; - c ^= 0xC0; + if (c == CHAR_QUESTION_MARK) + c = ('\\' == 188 && '`' == 74)? 0x5f : 0xff; + else + { + for (i = 0; i < 32; i++) + { + if (c == ebcdic_escape_c[i]) break; + } + if (i < 32) c = i; else *errorcodeptr = ERR68; + } #endif break; @@ -1799,7 +1818,7 @@ for (;;) case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: do cc += GET(cc, 1); while (*cc == OP_ALT); - cc += PRIV(OP_lengths)[*cc]; + cc += 1 + LINK_SIZE; break; /* Skip over things that don't match chars */ @@ -2487,7 +2506,7 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE); if (c == OP_BRA || c == OP_BRAPOS || c == OP_CBRA || c == OP_CBRAPOS || c == OP_ONCE || c == OP_ONCE_NC || - c == OP_COND) + c == OP_COND || c == OP_SCOND) { BOOL empty_branch; if (GET(code, 1) == 0) return TRUE; /* Hit unclosed bracket */ @@ -3886,11 +3905,11 @@ didn't consider this to be a POSIX class. Likewise for [:1234:]. The problem in trying to be exactly like Perl is in the handling of escapes. We have to be sure that [abc[:x\]pqr] is *not* treated as containing a POSIX class, but [abc[:x\]pqr:]] is (so that an error can be generated). The code -below handles the special case of \], but does not try to do any other escape -processing. This makes it different from Perl for cases such as [:l\ower:] -where Perl recognizes it as the POSIX class "lower" but PCRE does not recognize -"l\ower". This is a lesser evil than not diagnosing bad classes when Perl does, -I think. +below handles the special cases \\ and \], but does not try to do any other +escape processing. This makes it different from Perl for cases such as +[:l\ower:] where Perl recognizes it as the POSIX class "lower" but PCRE does +not recognize "l\ower". This is a lesser evil than not diagnosing bad classes +when Perl does, I think. A user pointed out that PCRE was rejecting [:a[:digit:]] whereas Perl was not. It seems that the appearance of a nested POSIX class supersedes an apparent @@ -3917,21 +3936,16 @@ pcre_uchar terminator; /* Don't combine these lines; the Solaris cc */ terminator = *(++ptr); /* compiler warns about "non-constant" initializer. */ for (++ptr; *ptr != CHAR_NULL; ptr++) { - if (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET) + if (*ptr == CHAR_BACKSLASH && + (ptr[1] == CHAR_RIGHT_SQUARE_BRACKET || + ptr[1] == CHAR_BACKSLASH)) ptr++; - else if (*ptr == CHAR_RIGHT_SQUARE_BRACKET) return FALSE; - else + else if ((*ptr == CHAR_LEFT_SQUARE_BRACKET && ptr[1] == terminator) || + *ptr == CHAR_RIGHT_SQUARE_BRACKET) return FALSE; + else if (*ptr == terminator && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET) { - if (*ptr == terminator && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET) - { - *endptr = ptr; - return TRUE; - } - if (*ptr == CHAR_LEFT_SQUARE_BRACKET && - (ptr[1] == CHAR_COLON || ptr[1] == CHAR_DOT || - ptr[1] == CHAR_EQUALS_SIGN) && - check_posix_syntax(ptr, endptr)) - return FALSE; + *endptr = ptr; + return TRUE; } } return FALSE; @@ -3985,11 +3999,12 @@ have their offsets adjusted. That one of the jobs of this function. Before it is called, the partially compiled regex must be temporarily terminated with OP_END. -This function has been extended with the possibility of forward references for -recursions and subroutine calls. It must also check the list of such references -for the group we are dealing with. If it finds that one of the recursions in -the current group is on this list, it adjusts the offset in the list, not the -value in the reference (which is a group number). +This function has been extended to cope with forward references for recursions +and subroutine calls. It must check the list of such references for the +group we are dealing with. If it finds that one of the recursions in the +current group is on this list, it does not adjust the value in the reference +(which is a group number). After the group has been scanned, all the offsets in +the forward reference list for the group are adjusted. Arguments: group points to the start of the group @@ -4005,29 +4020,21 @@ static void adjust_recurse(pcre_uchar *group, int adjust, BOOL utf, compile_data *cd, size_t save_hwm_offset) { +int offset; +pcre_uchar *hc; pcre_uchar *ptr = group; while ((ptr = (pcre_uchar *)find_recurse(ptr, utf)) != NULL) { - int offset; - pcre_uchar *hc; - - /* See if this recursion is on the forward reference list. If so, adjust the - reference. */ - for (hc = (pcre_uchar *)cd->start_workspace + save_hwm_offset; hc < cd->hwm; hc += LINK_SIZE) { offset = (int)GET(hc, 0); - if (cd->start_code + offset == ptr + 1) - { - PUT(hc, 0, offset + adjust); - break; - } + if (cd->start_code + offset == ptr + 1) break; } - /* Otherwise, adjust the recursion offset if it's after the start of this - group. */ + /* If we have not found this recursion on the forward reference list, adjust + the recursion's offset if it's after the start of this group. */ if (hc >= cd->hwm) { @@ -4037,6 +4044,15 @@ while ((ptr = (pcre_uchar *)find_recurse(ptr, utf)) != NULL) ptr += 1 + LINK_SIZE; } + +/* Now adjust all forward reference offsets for the group. */ + +for (hc = (pcre_uchar *)cd->start_workspace + save_hwm_offset; hc < cd->hwm; + hc += LINK_SIZE) + { + offset = (int)GET(hc, 0); + PUT(hc, 0, offset + adjust); + } } @@ -4465,7 +4481,7 @@ const pcre_uchar *tempptr; const pcre_uchar *nestptr = NULL; pcre_uchar *previous = NULL; pcre_uchar *previous_callout = NULL; -size_t save_hwm_offset = 0; +size_t item_hwm_offset = 0; pcre_uint8 classbits[32]; /* We can fish out the UTF-8 setting once and for all into a BOOL, but we @@ -4767,6 +4783,7 @@ for (;; ptr++) zeroreqchar = reqchar; zeroreqcharflags = reqcharflags; previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; *code++ = ((options & PCRE_DOTALL) != 0)? OP_ALLANY: OP_ANY; break; @@ -4818,6 +4835,7 @@ for (;; ptr++) /* Handle a real character class. */ previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; /* PCRE supports POSIX class stuff inside a class. Perl gives an error if they are encountered at the top level, so we'll do that too. */ @@ -5195,9 +5213,9 @@ for (;; ptr++) cd, PRIV(vspace_list)); continue; -#ifdef SUPPORT_UCP case ESC_p: case ESC_P: +#ifdef SUPPORT_UCP { BOOL negated; unsigned int ptype = 0, pdata = 0; @@ -5211,6 +5229,9 @@ for (;; ptr++) class_has_8bitchar--; /* Undo! */ continue; } +#else + *errorcodeptr = ERR45; + goto FAILED; #endif /* Unrecognized escapes are faulted if PCRE is running in its strict mode. By default, for compatibility with Perl, they are @@ -5930,7 +5951,7 @@ for (;; ptr++) { register int i; int len = (int)(code - previous); - size_t base_hwm_offset = save_hwm_offset; + size_t base_hwm_offset = item_hwm_offset; pcre_uchar *bralink = NULL; pcre_uchar *brazeroptr = NULL; @@ -5985,7 +6006,7 @@ for (;; ptr++) if (repeat_max <= 1) /* Covers 0, 1, and unlimited */ { *code = OP_END; - adjust_recurse(previous, 1, utf, cd, save_hwm_offset); + adjust_recurse(previous, 1, utf, cd, item_hwm_offset); memmove(previous + 1, previous, IN_UCHARS(len)); code++; if (repeat_max == 0) @@ -6009,7 +6030,7 @@ for (;; ptr++) { int offset; *code = OP_END; - adjust_recurse(previous, 2 + LINK_SIZE, utf, cd, save_hwm_offset); + adjust_recurse(previous, 2 + LINK_SIZE, utf, cd, item_hwm_offset); memmove(previous + 2 + LINK_SIZE, previous, IN_UCHARS(len)); code += 2 + LINK_SIZE; *previous++ = OP_BRAZERO + repeat_type; @@ -6254,6 +6275,12 @@ for (;; ptr++) while (*scode == OP_ALT); } + /* A conditional group with only one branch has an implicit empty + alternative branch. */ + + if (*bracode == OP_COND && bracode[GET(bracode,1)] != OP_ALT) + *bracode = OP_SCOND; + /* Handle possessive quantifiers. */ if (possessive_quantifier) @@ -6267,11 +6294,11 @@ for (;; ptr++) { int nlen = (int)(code - bracode); *code = OP_END; - adjust_recurse(bracode, 1 + LINK_SIZE, utf, cd, save_hwm_offset); + adjust_recurse(bracode, 1 + LINK_SIZE, utf, cd, item_hwm_offset); memmove(bracode + 1 + LINK_SIZE, bracode, IN_UCHARS(nlen)); code += 1 + LINK_SIZE; nlen += 1 + LINK_SIZE; - *bracode = OP_BRAPOS; + *bracode = (*bracode == OP_COND)? OP_BRAPOS : OP_SBRAPOS; *code++ = OP_KETRPOS; PUTINC(code, 0, nlen); PUT(bracode, 1, nlen); @@ -6401,7 +6428,7 @@ for (;; ptr++) else { *code = OP_END; - adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm_offset); + adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, item_hwm_offset); memmove(tempcode + 1 + LINK_SIZE, tempcode, IN_UCHARS(len)); code += 1 + LINK_SIZE; len += 1 + LINK_SIZE; @@ -6450,7 +6477,7 @@ for (;; ptr++) default: *code = OP_END; - adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm_offset); + adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, item_hwm_offset); memmove(tempcode + 1 + LINK_SIZE, tempcode, IN_UCHARS(len)); code += 1 + LINK_SIZE; len += 1 + LINK_SIZE; @@ -6623,7 +6650,7 @@ for (;; ptr++) newoptions = options; skipbytes = 0; bravalue = OP_CBRA; - save_hwm_offset = cd->hwm - cd->start_workspace; + item_hwm_offset = cd->hwm - cd->start_workspace; reset_bracount = FALSE; /* Deal with the extended parentheses; all are introduced by '?', and the @@ -6641,6 +6668,7 @@ for (;; ptr++) /* ------------------------------------------------------------ */ case CHAR_VERTICAL_LINE: /* Reset capture count for each branch */ reset_bracount = TRUE; + cd->dupgroups = TRUE; /* Record (?| encountered */ /* Fall through */ /* ------------------------------------------------------------ */ @@ -6741,6 +6769,12 @@ for (;; ptr++) { while (IS_DIGIT(*ptr)) { + if (recno > INT_MAX / 10 - 1) /* Integer overflow */ + { + while (IS_DIGIT(*ptr)) ptr++; + *errorcodeptr = ERR61; + goto FAILED; + } recno = recno * 10 + (int)(*ptr - CHAR_0); ptr++; } @@ -6769,7 +6803,7 @@ for (;; ptr++) ptr++; } namelen = (int)(ptr - name); - if (lengthptr != NULL) *lengthptr += IMM2_SIZE; + if (lengthptr != NULL) skipbytes += IMM2_SIZE; } /* Check the terminator */ @@ -6875,6 +6909,11 @@ for (;; ptr++) *errorcodeptr = ERR15; goto FAILED; } + if (recno > INT_MAX / 10 - 1) /* Integer overflow */ + { + *errorcodeptr = ERR61; + goto FAILED; + } recno = recno * 10 + name[i] - CHAR_0; } if (recno == 0) recno = RREF_ANY; @@ -7151,7 +7190,8 @@ for (;; ptr++) if (lengthptr != NULL) { named_group *ng; - + recno = 0; + if (namelen == 0) { *errorcodeptr = ERR62; @@ -7168,20 +7208,6 @@ for (;; ptr++) goto FAILED; } - /* The name table does not exist in the first pass; instead we must - scan the list of names encountered so far in order to get the - number. If the name is not found, set the value to 0 for a forward - reference. */ - - ng = cd->named_groups; - for (i = 0; i < cd->names_found; i++, ng++) - { - if (namelen == ng->length && - STRNCMP_UC_UC(name, ng->name, namelen) == 0) - break; - } - recno = (i < cd->names_found)? ng->number : 0; - /* Count named back references. */ if (!is_recurse) cd->namedrefcount++; @@ -7191,6 +7217,56 @@ for (;; ptr++) 16-bit data item. */ *lengthptr += IMM2_SIZE; + + /* If this is a forward reference and we are within a (?|...) group, + the reference may end up as the number of a group which we are + currently inside, that is, it could be a recursive reference. In the + real compile this will be picked up and the reference wrapped with + OP_ONCE to make it atomic, so we must space in case this occurs. */ + + /* In fact, this can happen for a non-forward reference because + another group with the same number might be created later. This + issue is fixed "properly" in PCRE2. As PCRE1 is now in maintenance + only mode, we finesse the bug by allowing more memory always. */ + + *lengthptr += 2 + 2*LINK_SIZE; + + /* It is even worse than that. The current reference may be to an + existing named group with a different number (so apparently not + recursive) but which later on is also attached to a group with the + current number. This can only happen if $(| has been previous + encountered. In that case, we allow yet more memory, just in case. + (Again, this is fixed "properly" in PCRE2. */ + + if (cd->dupgroups) *lengthptr += 4 + 4*LINK_SIZE; + + /* Otherwise, check for recursion here. The name table does not exist + in the first pass; instead we must scan the list of names encountered + so far in order to get the number. If the name is not found, leave + the value of recno as 0 for a forward reference. */ + + else + { + ng = cd->named_groups; + for (i = 0; i < cd->names_found; i++, ng++) + { + if (namelen == ng->length && + STRNCMP_UC_UC(name, ng->name, namelen) == 0) + { + open_capitem *oc; + recno = ng->number; + if (is_recurse) break; + for (oc = cd->open_caps; oc != NULL; oc = oc->next) + { + if (oc->number == recno) + { + oc->flag = TRUE; + break; + } + } + } + } + } } /* In the real compile, search the name table. We check the name @@ -7237,8 +7313,6 @@ for (;; ptr++) for (i++; i < cd->names_found; i++) { if (STRCMP_UC_UC(slot + IMM2_SIZE, cslot + IMM2_SIZE) != 0) break; - - count++; cslot += cd->name_entry_size; } @@ -7247,6 +7321,7 @@ for (;; ptr++) { if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE; previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; *code++ = ((options & PCRE_CASELESS) != 0)? OP_DNREFI : OP_DNREF; PUT2INC(code, 0, index); PUT2INC(code, 0, count); @@ -7284,9 +7359,14 @@ for (;; ptr++) /* ------------------------------------------------------------ */ - case CHAR_R: /* Recursion */ - ptr++; /* Same as (?0) */ - /* Fall through */ + case CHAR_R: /* Recursion, same as (?0) */ + recno = 0; + if (*(++ptr) != CHAR_RIGHT_PARENTHESIS) + { + *errorcodeptr = ERR29; + goto FAILED; + } + goto HANDLE_RECURSION; /* ------------------------------------------------------------ */ @@ -7323,7 +7403,15 @@ for (;; ptr++) recno = 0; while(IS_DIGIT(*ptr)) + { + if (recno > INT_MAX / 10 - 1) /* Integer overflow */ + { + while (IS_DIGIT(*ptr)) ptr++; + *errorcodeptr = ERR61; + goto FAILED; + } recno = recno * 10 + *ptr++ - CHAR_0; + } if (*ptr != (pcre_uchar)terminator) { @@ -7360,6 +7448,7 @@ for (;; ptr++) HANDLE_RECURSION: previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; called = cd->start_code; /* When we are actually compiling, find the bracket that is being @@ -7561,7 +7650,11 @@ for (;; ptr++) previous = NULL; cd->iscondassert = FALSE; } - else previous = code; + else + { + previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; + } *code = bravalue; tempcode = code; @@ -7809,7 +7902,7 @@ for (;; ptr++) const pcre_uchar *p; pcre_uint32 cf; - save_hwm_offset = cd->hwm - cd->start_workspace; /* Normally this is set when '(' is read */ + item_hwm_offset = cd->hwm - cd->start_workspace; /* Normally this is set when '(' is read */ terminator = (*(++ptr) == CHAR_LESS_THAN_SIGN)? CHAR_GREATER_THAN_SIGN : CHAR_APOSTROPHE; @@ -7838,7 +7931,7 @@ for (;; ptr++) if (*p != (pcre_uchar)terminator) { *errorcodeptr = ERR57; - break; + goto FAILED; } ptr++; goto HANDLE_NUMERICAL_RECURSION; @@ -7853,7 +7946,7 @@ for (;; ptr++) ptr[1] != CHAR_APOSTROPHE && ptr[1] != CHAR_LEFT_CURLY_BRACKET)) { *errorcodeptr = ERR69; - break; + goto FAILED; } is_recurse = FALSE; terminator = (*(++ptr) == CHAR_LESS_THAN_SIGN)? @@ -7877,6 +7970,7 @@ for (;; ptr++) HANDLE_REFERENCE: if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE; previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; *code++ = ((options & PCRE_CASELESS) != 0)? OP_REFI : OP_REF; PUT2INC(code, 0, recno); cd->backref_map |= (recno < 32)? (1 << recno) : 1; @@ -7906,6 +8000,7 @@ for (;; ptr++) if (!get_ucp(&ptr, &negated, &ptype, &pdata, errorcodeptr)) goto FAILED; previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; *code++ = ((escape == ESC_p) != negated)? OP_PROP : OP_NOTPROP; *code++ = ptype; *code++ = pdata; @@ -7946,6 +8041,7 @@ for (;; ptr++) { previous = (escape > ESC_b && escape < ESC_Z)? code : NULL; + item_hwm_offset = cd->hwm - cd->start_workspace; *code++ = (!utf && escape == ESC_C)? OP_ALLANY : escape; } } @@ -7989,6 +8085,7 @@ for (;; ptr++) ONE_CHAR: previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; /* For caseless UTF-8 mode when UCP support is available, check whether this character has more than one other case. If so, generate a special @@ -9164,6 +9261,7 @@ cd->names_found = 0; cd->name_entry_size = 0; cd->name_table = NULL; cd->dupnames = FALSE; +cd->dupgroups = FALSE; cd->namedrefcount = 0; cd->start_code = cworkspace; cd->hwm = cworkspace; @@ -9198,7 +9296,7 @@ if (errorcode != 0) goto PCRE_EARLY_ERROR_RETURN; DPRINTF(("end pre-compile: length=%d workspace=%d\n", length, (int)(cd->hwm - cworkspace))); - + if (length > MAX_PATTERN_SIZE) { errorcode = ERR20; @@ -9336,6 +9434,16 @@ if (cd->hwm > cd->start_workspace) int offset, recno; cd->hwm -= LINK_SIZE; offset = GET(cd->hwm, 0); + + /* Check that the hwm handling hasn't gone wrong. This whole area is + rewritten in PCRE2 because there are some obscure cases. */ + + if (offset == 0 || codestart[offset-1] != OP_RECURSE) + { + errorcode = ERR10; + break; + } + recno = GET(codestart, offset); if (recno != prev_recno) { @@ -9366,7 +9474,7 @@ used in this code because at least one compiler gives a warning about loss of "const" attribute if the cast (pcre_uchar *)codestart is used directly in the function call. */ -if ((options & PCRE_NO_AUTO_POSSESS) == 0) +if (errorcode == 0 && (options & PCRE_NO_AUTO_POSSESS) == 0) { pcre_uchar *temp = (pcre_uchar *)codestart; auto_possessify(temp, utf, cd); @@ -9380,7 +9488,7 @@ OP_RECURSE that are not fixed length get a diagnosic with a useful offset. The exceptional ones forgo this. We scan the pattern to check that they are fixed length, and set their lengths. */ -if (cd->check_lookbehind) +if (errorcode == 0 && cd->check_lookbehind) { pcre_uchar *cc = (pcre_uchar *)codestart; @@ -9593,4 +9701,3 @@ return (pcre32 *)re; } /* End of pcre_compile.c */ - diff --git a/src/3rdparty/pcre/pcre_exec.c b/src/3rdparty/pcre/pcre_exec.c index c021fe1a4c..24b23ca286 100644 --- a/src/3rdparty/pcre/pcre_exec.c +++ b/src/3rdparty/pcre/pcre_exec.c @@ -6685,7 +6685,8 @@ if (md->offset_vector != NULL) register int *iend = iptr - re->top_bracket; if (iend < md->offset_vector + 2) iend = md->offset_vector + 2; while (--iptr >= iend) *iptr = -1; - md->offset_vector[0] = md->offset_vector[1] = -1; + if (offsetcount > 0) md->offset_vector[0] = -1; + if (offsetcount > 1) md->offset_vector[1] = -1; } /* Set up the first character to match, if available. The first_char value is diff --git a/src/3rdparty/pcre/pcre_internal.h b/src/3rdparty/pcre/pcre_internal.h index dd0ac7fc91..544d9c0709 100644 --- a/src/3rdparty/pcre/pcre_internal.h +++ b/src/3rdparty/pcre/pcre_internal.h @@ -984,7 +984,7 @@ other. NOTE: The values also appear in pcre_jit_compile.c. */ #ifndef EBCDIC #define HSPACE_LIST \ - CHAR_HT, CHAR_SPACE, 0xa0, \ + CHAR_HT, CHAR_SPACE, CHAR_NBSP, \ 0x1680, 0x180e, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, \ 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202f, 0x205f, 0x3000, \ NOTACHAR @@ -1010,7 +1010,7 @@ other. NOTE: The values also appear in pcre_jit_compile.c. */ #define HSPACE_BYTE_CASES \ case CHAR_HT: \ case CHAR_SPACE: \ - case 0xa0 /* NBSP */ + case CHAR_NBSP #define HSPACE_CASES \ HSPACE_BYTE_CASES: \ @@ -1037,11 +1037,12 @@ other. NOTE: The values also appear in pcre_jit_compile.c. */ /* ------ EBCDIC environments ------ */ #else -#define HSPACE_LIST CHAR_HT, CHAR_SPACE +#define HSPACE_LIST CHAR_HT, CHAR_SPACE, CHAR_NBSP, NOTACHAR #define HSPACE_BYTE_CASES \ case CHAR_HT: \ - case CHAR_SPACE + case CHAR_SPACE: \ + case CHAR_NBSP #define HSPACE_CASES HSPACE_BYTE_CASES @@ -1215,6 +1216,7 @@ same code point. */ #define CHAR_ESC '\047' #define CHAR_DEL '\007' +#define CHAR_NBSP '\x41' #define STR_ESC "\047" #define STR_DEL "\007" @@ -1229,6 +1231,7 @@ a positive value. */ #define CHAR_NEL ((unsigned char)'\x85') #define CHAR_ESC '\033' #define CHAR_DEL '\177' +#define CHAR_NBSP ((unsigned char)'\xa0') #define STR_LF "\n" #define STR_NL STR_LF @@ -1606,6 +1609,7 @@ only. */ #define CHAR_VERTICAL_LINE '\174' #define CHAR_RIGHT_CURLY_BRACKET '\175' #define CHAR_TILDE '\176' +#define CHAR_NBSP ((unsigned char)'\xa0') #define STR_HT "\011" #define STR_VT "\013" @@ -1762,6 +1766,10 @@ only. */ /* Escape items that are just an encoding of a particular data value. */ +#ifndef ESC_a +#define ESC_a CHAR_BEL +#endif + #ifndef ESC_e #define ESC_e CHAR_ESC #endif @@ -2446,6 +2454,7 @@ typedef struct compile_data { BOOL had_pruneorskip; /* (*PRUNE) or (*SKIP) encountered */ BOOL check_lookbehind; /* Lookbehinds need later checking */ BOOL dupnames; /* Duplicate names exist */ + BOOL dupgroups; /* Duplicate groups exist: (?| found */ BOOL iscondassert; /* Next assert is a condition */ int nltype; /* Newline type */ int nllen; /* Newline string length */ diff --git a/src/3rdparty/pcre/pcre_jit_compile.c b/src/3rdparty/pcre/pcre_jit_compile.c index debdf6ef45..868d1d91bf 100644 --- a/src/3rdparty/pcre/pcre_jit_compile.c +++ b/src/3rdparty/pcre/pcre_jit_compile.c @@ -1064,6 +1064,7 @@ pcre_uchar *alternative; pcre_uchar *end = NULL; int private_data_ptr = *private_data_start; int space, size, bracketlen; +BOOL repeat_check = TRUE; while (cc < ccend) { @@ -1071,9 +1072,10 @@ while (cc < ccend) size = 0; bracketlen = 0; if (private_data_ptr > SLJIT_MAX_LOCAL_SIZE) - return; + break; - if (*cc == OP_ONCE || *cc == OP_ONCE_NC || *cc == OP_BRA || *cc == OP_CBRA || *cc == OP_COND) + if (repeat_check && (*cc == OP_ONCE || *cc == OP_ONCE_NC || *cc == OP_BRA || *cc == OP_CBRA || *cc == OP_COND)) + { if (detect_repeat(common, cc)) { /* These brackets are converted to repeats, so no global @@ -1081,6 +1083,8 @@ while (cc < ccend) if (cc >= end) end = bracketend(cc); } + } + repeat_check = TRUE; switch(*cc) { @@ -1136,6 +1140,13 @@ while (cc < ccend) bracketlen = 1 + LINK_SIZE + IMM2_SIZE; break; + case OP_BRAZERO: + case OP_BRAMINZERO: + case OP_BRAPOSZERO: + repeat_check = FALSE; + size = 1; + break; + CASE_ITERATOR_PRIVATE_DATA_1 space = 1; size = -2; @@ -1162,12 +1173,17 @@ while (cc < ccend) size = 1; break; - CASE_ITERATOR_TYPE_PRIVATE_DATA_2B + case OP_TYPEUPTO: if (cc[1 + IMM2_SIZE] != OP_ANYNL && cc[1 + IMM2_SIZE] != OP_EXTUNI) space = 2; size = 1 + IMM2_SIZE; break; + case OP_TYPEMINUPTO: + space = 2; + size = 1 + IMM2_SIZE; + break; + case OP_CLASS: case OP_NCLASS: size += 1 + 32 / sizeof(pcre_uchar); @@ -1316,6 +1332,13 @@ while (cc < ccend) cc += 1 + LINK_SIZE + IMM2_SIZE; break; + case OP_THEN: + stack_restore = TRUE; + if (common->control_head_ptr != 0) + *needs_control_head = TRUE; + cc ++; + break; + default: stack_restore = TRUE; /* Fall through. */ @@ -2220,6 +2243,7 @@ while (current != NULL) SLJIT_ASSERT_STOP(); break; } + SLJIT_ASSERT(current > (sljit_sw*)current[-1]); current = (sljit_sw*)current[-1]; } return -1; @@ -3209,7 +3233,7 @@ bytes[len] = byte; bytes[0] = len; } -static int scan_prefix(compiler_common *common, pcre_uchar *cc, pcre_uint32 *chars, pcre_uint8 *bytes, int max_chars) +static int scan_prefix(compiler_common *common, pcre_uchar *cc, pcre_uint32 *chars, pcre_uint8 *bytes, int max_chars, pcre_uint32 *rec_count) { /* Recursive function, which scans prefix literals. */ BOOL last, any, caseless; @@ -3227,9 +3251,14 @@ pcre_uchar othercase[1]; repeat = 1; while (TRUE) { + if (*rec_count == 0) + return 0; + (*rec_count)--; + last = TRUE; any = FALSE; caseless = FALSE; + switch (*cc) { case OP_CHARI: @@ -3291,7 +3320,7 @@ while (TRUE) #ifdef SUPPORT_UTF if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc); #endif - max_chars = scan_prefix(common, cc + len, chars, bytes, max_chars); + max_chars = scan_prefix(common, cc + len, chars, bytes, max_chars, rec_count); if (max_chars == 0) return consumed; last = FALSE; @@ -3314,7 +3343,7 @@ while (TRUE) alternative = cc + GET(cc, 1); while (*alternative == OP_ALT) { - max_chars = scan_prefix(common, alternative + 1 + LINK_SIZE, chars, bytes, max_chars); + max_chars = scan_prefix(common, alternative + 1 + LINK_SIZE, chars, bytes, max_chars, rec_count); if (max_chars == 0) return consumed; alternative += GET(alternative, 1); @@ -3556,6 +3585,7 @@ int i, max, from; int range_right = -1, range_len = 3 - 1; sljit_ub *update_table = NULL; BOOL in_range; +pcre_uint32 rec_count; for (i = 0; i < MAX_N_CHARS; i++) { @@ -3564,7 +3594,8 @@ for (i = 0; i < MAX_N_CHARS; i++) bytes[i * MAX_N_BYTES] = 0; } -max = scan_prefix(common, common->start, chars, bytes, MAX_N_CHARS); +rec_count = 10000; +max = scan_prefix(common, common->start, chars, bytes, MAX_N_CHARS, &rec_count); if (max <= 1) return FALSE; @@ -7665,6 +7696,10 @@ while (*cc != OP_KETRPOS) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); } + /* Even if the match is empty, we need to reset the control head. */ + if (needs_control_head) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack)); + if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS) add_jump(compiler, &emptymatch, CMP(SLJIT_EQUAL, TMP1, 0, STR_PTR, 0)); @@ -7692,6 +7727,10 @@ while (*cc != OP_KETRPOS) OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_sw), STR_PTR, 0); } + /* Even if the match is empty, we need to reset the control head. */ + if (needs_control_head) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack)); + if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS) add_jump(compiler, &emptymatch, CMP(SLJIT_EQUAL, TMP1, 0, STR_PTR, 0)); @@ -7704,9 +7743,6 @@ while (*cc != OP_KETRPOS) } } - if (needs_control_head) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack)); - JUMPTO(SLJIT_JUMP, loop); flush_stubs(common); @@ -9648,6 +9684,7 @@ set_jumps(common->currententry->calls, common->currententry->entry); sljit_emit_fast_enter(compiler, TMP2, 0); allocate_stack(common, private_data_size + framesize + alternativesize); +count_match(common); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(private_data_size + framesize + alternativesize - 1), TMP2, 0); copy_private_data(common, ccbegin, ccend, TRUE, private_data_size + framesize + alternativesize, framesize + alternativesize, needs_control_head); if (needs_control_head) @@ -9992,6 +10029,7 @@ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack)); OP1(SLJIT_MOV_UI, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, limit_match)); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, base)); OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, limit)); +OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LIMIT_MATCH, TMP1, 0); if (mode == JIT_PARTIAL_SOFT_COMPILE) diff --git a/src/3rdparty/pcre/pcre_study.c b/src/3rdparty/pcre/pcre_study.c index 998fe2325e..932e9a7c4c 100644 --- a/src/3rdparty/pcre/pcre_study.c +++ b/src/3rdparty/pcre/pcre_study.c @@ -71,6 +71,7 @@ Arguments: startcode pointer to start of the whole pattern's code options the compiling options recurses chain of recurse_check to catch mutual recursion + countptr pointer to call count (to catch over complexity) Returns: the minimum length -1 if \C in UTF-8 mode or (*ACCEPT) was encountered @@ -80,7 +81,8 @@ Returns: the minimum length static int find_minlength(const REAL_PCRE *re, const pcre_uchar *code, - const pcre_uchar *startcode, int options, recurse_check *recurses) + const pcre_uchar *startcode, int options, recurse_check *recurses, + int *countptr) { int length = -1; /* PCRE_UTF16 has the same value as PCRE_UTF8. */ @@ -90,6 +92,8 @@ recurse_check this_recurse; register int branchlength = 0; register pcre_uchar *cc = (pcre_uchar *)code + 1 + LINK_SIZE; +if ((*countptr)++ > 1000) return -1; /* too complex */ + if (*code == OP_CBRA || *code == OP_SCBRA || *code == OP_CBRAPOS || *code == OP_SCBRAPOS) cc += IMM2_SIZE; @@ -131,7 +135,7 @@ for (;;) case OP_SBRAPOS: case OP_ONCE: case OP_ONCE_NC: - d = find_minlength(re, cc, startcode, options, recurses); + d = find_minlength(re, cc, startcode, options, recurses, countptr); if (d < 0) return d; branchlength += d; do cc += GET(cc, 1); while (*cc == OP_ALT); @@ -415,7 +419,8 @@ for (;;) int dd; this_recurse.prev = recurses; this_recurse.group = cs; - dd = find_minlength(re, cs, startcode, options, &this_recurse); + dd = find_minlength(re, cs, startcode, options, &this_recurse, + countptr); if (dd < d) d = dd; } } @@ -451,7 +456,8 @@ for (;;) { this_recurse.prev = recurses; this_recurse.group = cs; - d = find_minlength(re, cs, startcode, options, &this_recurse); + d = find_minlength(re, cs, startcode, options, &this_recurse, + countptr); } } } @@ -514,7 +520,7 @@ for (;;) this_recurse.prev = recurses; this_recurse.group = cs; branchlength += find_minlength(re, cs, startcode, options, - &this_recurse); + &this_recurse, countptr); } } cc += 1 + LINK_SIZE; @@ -1453,6 +1459,7 @@ pcre32_study(const pcre32 *external_re, int options, const char **errorptr) #endif { int min; +int count = 0; BOOL bits_set = FALSE; pcre_uint8 start_bits[32]; PUBL(extra) *extra = NULL; @@ -1539,7 +1546,7 @@ if ((re->options & PCRE_ANCHORED) == 0 && /* Find the minimum length of subject string. */ -switch(min = find_minlength(re, code, code, re->options, NULL)) +switch(min = find_minlength(re, code, code, re->options, NULL, &count)) { case -2: *errorptr = "internal error: missing capturing bracket"; return NULL; case -3: *errorptr = "internal error: opcode not recognized"; return NULL; diff --git a/src/3rdparty/pcre/sljit/sljitConfig.h b/src/3rdparty/pcre/sljit/sljitConfig.h index 10364c3b60..1c8a521aa8 100644 --- a/src/3rdparty/pcre/sljit/sljitConfig.h +++ b/src/3rdparty/pcre/sljit/sljitConfig.h @@ -96,6 +96,15 @@ #define SLJIT_EXECUTABLE_ALLOCATOR 1 #endif +/* Force cdecl calling convention even if a better calling + convention (e.g. fastcall) is supported by the C compiler. + If this option is enabled, C functions without + SLJIT_CALL can also be called from JIT code. */ +#ifndef SLJIT_USE_CDECL_CALLING_CONVENTION +/* Disabled by default */ +#define SLJIT_USE_CDECL_CALLING_CONVENTION 0 +#endif + /* Return with error when an invalid argument is passed. */ #ifndef SLJIT_ARGUMENT_CHECKS /* Disabled by default */ diff --git a/src/3rdparty/pcre/sljit/sljitConfigInternal.h b/src/3rdparty/pcre/sljit/sljitConfigInternal.h index 3284012f19..16e3547c93 100644 --- a/src/3rdparty/pcre/sljit/sljitConfigInternal.h +++ b/src/3rdparty/pcre/sljit/sljitConfigInternal.h @@ -468,7 +468,12 @@ typedef double sljit_d; #ifndef SLJIT_CALL -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) +#if (defined SLJIT_USE_CDECL_CALLING_CONVENTION && SLJIT_USE_CDECL_CALLING_CONVENTION) + +/* Force cdecl. */ +#define SLJIT_CALL + +#elif (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) #if defined(__GNUC__) && !defined(__APPLE__) @@ -608,6 +613,12 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void); #define SLJIT_LOCALS_OFFSET_BASE ((23 + 1) * sizeof(sljit_sw)) #endif +#elif (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) + +#define SLJIT_NUMBER_OF_REGISTERS 10 +#define SLJIT_NUMBER_OF_SAVED_REGISTERS 5 +#define SLJIT_LOCALS_OFFSET_BASE 0 + #elif (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) #define SLJIT_NUMBER_OF_REGISTERS 0 diff --git a/src/3rdparty/pcre/sljit/sljitLir.c b/src/3rdparty/pcre/sljit/sljitLir.c index 5039a7e04e..0f1b1c9cce 100644 --- a/src/3rdparty/pcre/sljit/sljitLir.c +++ b/src/3rdparty/pcre/sljit/sljitLir.c @@ -845,8 +845,8 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *comp } static SLJIT_CONST char* op0_names[] = { - (char*)"breakpoint", (char*)"nop", - (char*)"lumul", (char*)"lsmul", (char*)"ludiv", (char*)"lsdiv", + (char*)"breakpoint", (char*)"nop", (char*)"lumul", (char*)"lsmul", + (char*)"udivmod", (char*)"sdivmod", (char*)"udivi", (char*)"sdivi" }; static SLJIT_CONST char* op1_names[] = { @@ -1036,7 +1036,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op0(struct sljit_compiler { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT((op >= SLJIT_BREAKPOINT && op <= SLJIT_LSMUL) - || ((op & ~SLJIT_INT_OP) >= SLJIT_LUDIV && (op & ~SLJIT_INT_OP) <= SLJIT_LSDIV)); + || ((op & ~SLJIT_INT_OP) >= SLJIT_UDIVMOD && (op & ~SLJIT_INT_OP) <= SLJIT_SDIVI)); CHECK_ARGUMENT(op < SLJIT_LUMUL || compiler->scratches >= 2); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) @@ -1447,6 +1447,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_com static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw offset) { + SLJIT_UNUSED_ARG(offset); + #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) FUNCTION_CHECK_DST(dst, dstw); #endif @@ -1462,6 +1464,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_co static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value) { + SLJIT_UNUSED_ARG(init_value); + #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) FUNCTION_CHECK_DST(dst, dstw); #endif diff --git a/src/3rdparty/pcre/sljit/sljitLir.h b/src/3rdparty/pcre/sljit/sljitLir.h index 24c0f60399..f0969dac2e 100644 --- a/src/3rdparty/pcre/sljit/sljitLir.h +++ b/src/3rdparty/pcre/sljit/sljitLir.h @@ -687,7 +687,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler * #define SLJIT_OP0_BASE 0 /* Flags: - (never set any flags) - Note: breakpoint instruction is not supported by all architectures (namely ppc) + Note: breakpoint instruction is not supported by all architectures (e.g. ppc) It falls back to SLJIT_NOP in those cases. */ #define SLJIT_BREAKPOINT (SLJIT_OP0_BASE + 0) /* Flags: - (never set any flags) @@ -696,24 +696,42 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler * #define SLJIT_NOP (SLJIT_OP0_BASE + 1) /* Flags: - (may destroy flags) Unsigned multiplication of SLJIT_R0 and SLJIT_R1. - Result goes to SLJIT_R1:SLJIT_R0 (high:low) word */ + Result is placed into SLJIT_R1:SLJIT_R0 (high:low) word */ #define SLJIT_LUMUL (SLJIT_OP0_BASE + 2) /* Flags: - (may destroy flags) Signed multiplication of SLJIT_R0 and SLJIT_R1. - Result goes to SLJIT_R1:SLJIT_R0 (high:low) word */ + Result is placed into SLJIT_R1:SLJIT_R0 (high:low) word */ #define SLJIT_LSMUL (SLJIT_OP0_BASE + 3) /* Flags: I - (may destroy flags) Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1. - The result is placed in SLJIT_R0 and the remainder goes to SLJIT_R1. - Note: if SLJIT_R1 contains 0, the behaviour is undefined. */ -#define SLJIT_LUDIV (SLJIT_OP0_BASE + 4) -#define SLJIT_ILUDIV (SLJIT_LUDIV | SLJIT_INT_OP) + The result is placed into SLJIT_R0 and the remainder into SLJIT_R1. + Note: if SLJIT_R1 is 0, the behaviour is undefined. */ +#define SLJIT_UDIVMOD (SLJIT_OP0_BASE + 4) +#define SLJIT_IUDIVMOD (SLJIT_UDIVMOD | SLJIT_INT_OP) /* Flags: I - (may destroy flags) Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1. - The result is placed in SLJIT_R0 and the remainder goes to SLJIT_R1. - Note: if SLJIT_R1 contains 0, the behaviour is undefined. */ -#define SLJIT_LSDIV (SLJIT_OP0_BASE + 5) -#define SLJIT_ILSDIV (SLJIT_LSDIV | SLJIT_INT_OP) + The result is placed into SLJIT_R0 and the remainder into SLJIT_R1. + Note: if SLJIT_R1 is 0, the behaviour is undefined. + Note: if SLJIT_R1 is -1 and SLJIT_R0 is integer min (0x800..00), + the behaviour is undefined. */ +#define SLJIT_SDIVMOD (SLJIT_OP0_BASE + 5) +#define SLJIT_ISDIVMOD (SLJIT_SDIVMOD | SLJIT_INT_OP) +/* Flags: I - (may destroy flags) + Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1. + The result is placed into SLJIT_R0. SLJIT_R1 preserves its value. + Note: if SLJIT_R1 is 0, the behaviour is undefined. + Note: SLJIT_SDIV is single precision divide. */ +#define SLJIT_UDIVI (SLJIT_OP0_BASE + 6) +#define SLJIT_IUDIVI (SLJIT_UDIVI | SLJIT_INT_OP) +/* Flags: I - (may destroy flags) + Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1. + The result is placed into SLJIT_R0. SLJIT_R1 preserves its value. + Note: if SLJIT_R1 is 0, the behaviour is undefined. + Note: if SLJIT_R1 is -1 and SLJIT_R0 is integer min (0x800..00), + the behaviour is undefined. + Note: SLJIT_SDIV is single precision divide. */ +#define SLJIT_SDIVI (SLJIT_OP0_BASE + 7) +#define SLJIT_ISDIVI (SLJIT_SDIVI | SLJIT_INT_OP) SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op); diff --git a/src/3rdparty/pcre/sljit/sljitNativeARM_32.c b/src/3rdparty/pcre/sljit/sljitNativeARM_32.c index aca1d31fdf..5cd4c71a29 100644 --- a/src/3rdparty/pcre/sljit/sljitNativeARM_32.c +++ b/src/3rdparty/pcre/sljit/sljitNativeARM_32.c @@ -1833,18 +1833,33 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler | (reg_map[SLJIT_R0] << 8) | reg_map[TMP_REG1]); #endif - case SLJIT_LUDIV: - case SLJIT_LSDIV: - if (compiler->scratches >= 3) + case SLJIT_UDIVMOD: + case SLJIT_SDIVMOD: + case SLJIT_UDIVI: + case SLJIT_SDIVI: + SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments); + SLJIT_COMPILE_ASSERT(reg_map[2] == 1 && reg_map[3] == 2, bad_register_mapping); + + if ((op >= SLJIT_UDIVI) && (compiler->scratches >= 3)) { FAIL_IF(push_inst(compiler, 0xe52d2008 /* str r2, [sp, #-8]! */)); + FAIL_IF(push_inst(compiler, 0xe58d1004 /* str r1, [sp, #4] */)); + } + else if ((op >= SLJIT_UDIVI) || (compiler->scratches >= 3)) + FAIL_IF(push_inst(compiler, 0xe52d0008 | (op >= SLJIT_UDIVI ? 0x1000 : 0x2000) /* str r1/r2, [sp, #-8]! */)); + #if defined(__GNUC__) FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM, - (op == SLJIT_LUDIV ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod)))); + ((op | 0x2) == SLJIT_UDIVI ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod)))); #else #error "Software divmod functions are needed" #endif - if (compiler->scratches >= 3) - return push_inst(compiler, 0xe49d2008 /* ldr r2, [sp], #8 */); + + if ((op >= SLJIT_UDIVI) && (compiler->scratches >= 3)) { + FAIL_IF(push_inst(compiler, 0xe59d1004 /* ldr r1, [sp, #4] */)); + FAIL_IF(push_inst(compiler, 0xe49d2008 /* ldr r2, [sp], #8 */)); + } + else if ((op >= SLJIT_UDIVI) || (compiler->scratches >= 3)) + return push_inst(compiler, 0xe49d0008 | (op >= SLJIT_UDIVI ? 0x1000 : 0x2000) /* ldr r1/r2, [sp], #8 */); return SLJIT_SUCCESS; } diff --git a/src/3rdparty/pcre/sljit/sljitNativeARM_64.c b/src/3rdparty/pcre/sljit/sljitNativeARM_64.c index b66455f756..044a675eee 100644 --- a/src/3rdparty/pcre/sljit/sljitNativeARM_64.c +++ b/src/3rdparty/pcre/sljit/sljitNativeARM_64.c @@ -1087,14 +1087,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil saved_regs_size += sizeof(sljit_sw); } local_size -= saved_regs_size + SLJIT_LOCALS_OFFSET; - FAIL_IF(push_inst(compiler, SUBI | RD(TMP_SP) | RN(TMP_SP) | (saved_regs_size << 10))); + if (saved_regs_size > 0) + FAIL_IF(push_inst(compiler, SUBI | RD(TMP_SP) | RN(TMP_SP) | (saved_regs_size << 10))); } tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG; prev = -1; for (i = SLJIT_S0; i >= tmp; i--) { if (prev == -1) { - prev = i; + if (!(offs & (1 << 15))) { + prev = i; + continue; + } + FAIL_IF(push_inst(compiler, STRI | RT(i) | RN(TMP_SP) | (offs >> 5))); + offs += 1 << 15; continue; } FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(TMP_SP) | offs)); @@ -1104,7 +1110,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { if (prev == -1) { - prev = i; + if (!(offs & (1 << 15))) { + prev = i; + continue; + } + FAIL_IF(push_inst(compiler, STRI | RT(i) | RN(TMP_SP) | (offs >> 5))); + offs += 1 << 15; continue; } FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(TMP_SP) | offs)); @@ -1112,8 +1123,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil prev = -1; } - if (prev != -1) - FAIL_IF(push_inst(compiler, STRI | RT(prev) | RN(TMP_SP) | (offs >> 5))); + SLJIT_ASSERT(prev == -1); if (compiler->local_size > (63 * sizeof(sljit_sw))) { /* The local_size is already adjusted by the saved registers. */ @@ -1188,7 +1198,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi prev = -1; for (i = SLJIT_S0; i >= tmp; i--) { if (prev == -1) { - prev = i; + if (!(offs & (1 << 15))) { + prev = i; + continue; + } + FAIL_IF(push_inst(compiler, LDRI | RT(i) | RN(TMP_SP) | (offs >> 5))); + offs += 1 << 15; continue; } FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(TMP_SP) | offs)); @@ -1198,7 +1213,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { if (prev == -1) { - prev = i; + if (!(offs & (1 << 15))) { + prev = i; + continue; + } + FAIL_IF(push_inst(compiler, LDRI | RT(i) | RN(TMP_SP) | (offs >> 5))); + offs += 1 << 15; continue; } FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(TMP_SP) | offs)); @@ -1206,13 +1226,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi prev = -1; } - if (prev != -1) - FAIL_IF(push_inst(compiler, LDRI | RT(prev) | RN(TMP_SP) | (offs >> 5))); + SLJIT_ASSERT(prev == -1); if (compiler->local_size <= (63 * sizeof(sljit_sw))) { FAIL_IF(push_inst(compiler, LDP_PST | 29 | RT2(TMP_LR) | RN(TMP_SP) | (((local_size >> 3) & 0x7f) << 15))); - } else { + } else if (saved_regs_size > 0) { FAIL_IF(push_inst(compiler, ADDI | RD(TMP_SP) | RN(TMP_SP) | (saved_regs_size << 10))); } @@ -1242,12 +1261,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler FAIL_IF(push_inst(compiler, ORR | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_R0))); FAIL_IF(push_inst(compiler, MADD | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1) | RT2(TMP_ZERO))); return push_inst(compiler, (op == SLJIT_LUMUL ? UMULH : SMULH) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1)); - case SLJIT_LUDIV: - case SLJIT_LSDIV: + case SLJIT_UDIVMOD: + case SLJIT_SDIVMOD: FAIL_IF(push_inst(compiler, (ORR ^ inv_bits) | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_R0))); - FAIL_IF(push_inst(compiler, ((op == SLJIT_LUDIV ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1))); + FAIL_IF(push_inst(compiler, ((op == SLJIT_UDIVMOD ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1))); FAIL_IF(push_inst(compiler, (MADD ^ inv_bits) | RD(SLJIT_R1) | RN(SLJIT_R0) | RM(SLJIT_R1) | RT2(TMP_ZERO))); return push_inst(compiler, (SUB ^ inv_bits) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1)); + case SLJIT_UDIVI: + case SLJIT_SDIVI: + return push_inst(compiler, ((op == SLJIT_UDIVI ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1)); } return SLJIT_SUCCESS; diff --git a/src/3rdparty/pcre/sljit/sljitNativeARM_T2_32.c b/src/3rdparty/pcre/sljit/sljitNativeARM_T2_32.c index 6e38cec899..f9803f5d44 100644 --- a/src/3rdparty/pcre/sljit/sljitNativeARM_T2_32.c +++ b/src/3rdparty/pcre/sljit/sljitNativeARM_T2_32.c @@ -1239,6 +1239,9 @@ extern int __aeabi_idivmod(int numerator, int denominator); SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op) { + sljit_sw saved_reg_list[3]; + sljit_sw saved_reg_count; + CHECK_ERROR(); CHECK(check_sljit_emit_op0(compiler, op)); @@ -1255,24 +1258,53 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler | (reg_map[SLJIT_R0] << 12) | (reg_map[SLJIT_R0] << 16) | reg_map[SLJIT_R1]); - case SLJIT_LUDIV: - case SLJIT_LSDIV: - if (compiler->scratches >= 4) { - FAIL_IF(push_inst32(compiler, 0xf84d2d04 /* str r2, [sp, #-4]! */)); - FAIL_IF(push_inst32(compiler, 0xf84dcd04 /* str ip, [sp, #-4]! */)); - } else if (compiler->scratches >= 3) - FAIL_IF(push_inst32(compiler, 0xf84d2d08 /* str r2, [sp, #-8]! */)); + case SLJIT_UDIVMOD: + case SLJIT_SDIVMOD: + case SLJIT_UDIVI: + case SLJIT_SDIVI: + SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments); + SLJIT_COMPILE_ASSERT(reg_map[2] == 1 && reg_map[3] == 2 && reg_map[4] == 12, bad_register_mapping); + + saved_reg_count = 0; + if (compiler->scratches >= 4) + saved_reg_list[saved_reg_count++] = 12; + if (compiler->scratches >= 3) + saved_reg_list[saved_reg_count++] = 2; + if (op >= SLJIT_UDIVI) + saved_reg_list[saved_reg_count++] = 1; + + if (saved_reg_count > 0) { + FAIL_IF(push_inst32(compiler, 0xf84d0d00 | (saved_reg_count >= 3 ? 16 : 8) + | (saved_reg_list[0] << 12) /* str rX, [sp, #-8/-16]! */)); + if (saved_reg_count >= 2) { + SLJIT_ASSERT(saved_reg_list[1] < 8); + FAIL_IF(push_inst16(compiler, 0x9001 | (saved_reg_list[1] << 8) /* str rX, [sp, #4] */)); + } + if (saved_reg_count >= 3) { + SLJIT_ASSERT(saved_reg_list[2] < 8); + FAIL_IF(push_inst16(compiler, 0x9002 | (saved_reg_list[2] << 8) /* str rX, [sp, #8] */)); + } + } + #if defined(__GNUC__) FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM, - (op == SLJIT_LUDIV ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod)))); + ((op | 0x2) == SLJIT_UDIVI ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod)))); #else #error "Software divmod functions are needed" #endif - if (compiler->scratches >= 4) { - FAIL_IF(push_inst32(compiler, 0xf85dcb04 /* ldr ip, [sp], #4 */)); - return push_inst32(compiler, 0xf85d2b04 /* ldr r2, [sp], #4 */); - } else if (compiler->scratches >= 3) - return push_inst32(compiler, 0xf85d2b08 /* ldr r2, [sp], #8 */); + + if (saved_reg_count > 0) { + if (saved_reg_count >= 3) { + SLJIT_ASSERT(saved_reg_list[2] < 8); + FAIL_IF(push_inst16(compiler, 0x9802 | (saved_reg_list[2] << 8) /* ldr rX, [sp, #8] */)); + } + if (saved_reg_count >= 2) { + SLJIT_ASSERT(saved_reg_list[1] < 8); + FAIL_IF(push_inst16(compiler, 0x9801 | (saved_reg_list[1] << 8) /* ldr rX, [sp, #4] */)); + } + return push_inst32(compiler, 0xf85d0b00 | (saved_reg_count >= 3 ? 16 : 8) + | (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */); + } return SLJIT_SUCCESS; } diff --git a/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c b/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c index 3e2c9f0232..cf3535f81a 100644 --- a/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c +++ b/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c @@ -1053,8 +1053,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler #endif FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0))); return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1)); - case SLJIT_LUDIV: - case SLJIT_LSDIV: + case SLJIT_UDIVMOD: + case SLJIT_SDIVMOD: + case SLJIT_UDIVI: + case SLJIT_SDIVI: + SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments); #if !(defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); @@ -1062,15 +1065,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) if (int_op) - FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); else - FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); #else - FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); #endif FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0))); - return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1)); + return (op >= SLJIT_UDIVI) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1)); } return SLJIT_SUCCESS; diff --git a/src/3rdparty/pcre/sljit/sljitNativePPC_common.c b/src/3rdparty/pcre/sljit/sljitNativePPC_common.c index 08d5356f5a..b6a043f4e4 100644 --- a/src/3rdparty/pcre/sljit/sljitNativePPC_common.c +++ b/src/3rdparty/pcre/sljit/sljitNativePPC_common.c @@ -1267,22 +1267,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1))); return push_inst(compiler, (op == SLJIT_LUMUL ? MULHWU : MULHW) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1)); #endif - case SLJIT_LUDIV: - case SLJIT_LSDIV: + case SLJIT_UDIVMOD: + case SLJIT_SDIVMOD: FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0))); #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) - if (int_op) { - FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVWU : DIVW) | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1))); - FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1))); - } else { - FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVDU : DIVD) | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1))); - FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1))); - } - return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1)); + FAIL_IF(push_inst(compiler, (int_op ? (op == SLJIT_UDIVMOD ? DIVWU : DIVW) : (op == SLJIT_UDIVMOD ? DIVDU : DIVD)) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1))); + FAIL_IF(push_inst(compiler, (int_op ? MULLW : MULLD) | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1))); #else - FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVWU : DIVW) | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1))); + FAIL_IF(push_inst(compiler, (op == SLJIT_UDIVMOD ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1))); FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1))); +#endif return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1)); + case SLJIT_UDIVI: + case SLJIT_SDIVI: +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + return push_inst(compiler, (int_op ? (op == SLJIT_UDIVI ? DIVWU : DIVW) : (op == SLJIT_UDIVI ? DIVDU : DIVD)) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)); +#else + return push_inst(compiler, (op == SLJIT_UDIVI ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)); #endif } diff --git a/src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c b/src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c index 0b1927a824..327c4267be 100644 --- a/src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c +++ b/src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c @@ -777,20 +777,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler #else #error "Implementation required" #endif - case SLJIT_LUDIV: - case SLJIT_LSDIV: + case SLJIT_UDIVMOD: + case SLJIT_SDIVMOD: + case SLJIT_UDIVI: + case SLJIT_SDIVI: + SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments); #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) - if (op == SLJIT_LUDIV) + if ((op | 0x2) == SLJIT_UDIVI) FAIL_IF(push_inst(compiler, WRY | S1(0), MOVABLE_INS)); else { FAIL_IF(push_inst(compiler, SRA | D(TMP_REG1) | S1(SLJIT_R0) | IMM(31), DR(TMP_REG1))); FAIL_IF(push_inst(compiler, WRY | S1(TMP_REG1), MOVABLE_INS)); } - FAIL_IF(push_inst(compiler, OR | D(TMP_REG2) | S1(0) | S2(SLJIT_R0), DR(TMP_REG2))); - FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? UDIV : SDIV) | D(SLJIT_R0) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R0))); + if (op <= SLJIT_SDIVMOD) + FAIL_IF(push_inst(compiler, OR | D(TMP_REG2) | S1(0) | S2(SLJIT_R0), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? UDIV : SDIV) | D(SLJIT_R0) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R0))); + if (op >= SLJIT_UDIVI) + return SLJIT_SUCCESS; FAIL_IF(push_inst(compiler, SMUL | D(SLJIT_R1) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R1))); - FAIL_IF(push_inst(compiler, SUB | D(SLJIT_R1) | S1(TMP_REG2) | S2(SLJIT_R1), DR(SLJIT_R1))); - return SLJIT_SUCCESS; + return push_inst(compiler, SUB | D(SLJIT_R1) | S1(TMP_REG2) | S2(SLJIT_R1), DR(SLJIT_R1)); #else #error "Implementation required" #endif diff --git a/src/3rdparty/pcre/sljit/sljitNativeTILEGX_64.c b/src/3rdparty/pcre/sljit/sljitNativeTILEGX_64.c index 1d6aa5a110..4d40392fa8 100644 --- a/src/3rdparty/pcre/sljit/sljitNativeTILEGX_64.c +++ b/src/3rdparty/pcre/sljit/sljitNativeTILEGX_64.c @@ -35,21 +35,21 @@ #define SIMM_16BIT_MIN (-0x8000) #define SIMM_17BIT_MAX (0xffff) #define SIMM_17BIT_MIN (-0x10000) -#define SIMM_32BIT_MIN (-0x80000000) #define SIMM_32BIT_MAX (0x7fffffff) -#define SIMM_48BIT_MIN (0x800000000000L) +#define SIMM_32BIT_MIN (-0x7fffffff - 1) #define SIMM_48BIT_MAX (0x7fffffff0000L) +#define SIMM_48BIT_MIN (-0x800000000000L) #define IMM16(imm) ((imm) & 0xffff) #define UIMM_16BIT_MAX (0xffff) -#define TMP_REG1 (SLJIT_NO_REGISTERS + 1) -#define TMP_REG2 (SLJIT_NO_REGISTERS + 2) -#define TMP_REG3 (SLJIT_NO_REGISTERS + 3) -#define ADDR_TMP (SLJIT_NO_REGISTERS + 4) +#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) +#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3) +#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4) +#define ADDR_TMP (SLJIT_NUMBER_OF_REGISTERS + 5) #define PIC_ADDR_REG TMP_REG2 -static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = { +static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = { 63, 0, 1, 2, 3, 4, 30, 31, 32, 33, 34, 54, 5, 16, 6, 7 }; @@ -58,11 +58,6 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = { #define TMP_REG2_mapped 16 #define TMP_REG3_mapped 6 #define ADDR_TMP_mapped 7 -#define SLJIT_SAVED_REG1_mapped 30 -#define SLJIT_SAVED_REG2_mapped 31 -#define SLJIT_SAVED_REG3_mapped 32 -#define SLJIT_SAVED_EREG1_mapped 33 -#define SLJIT_SAVED_EREG2_mapped 34 /* Flags are keept in volatile registers. */ #define EQUAL_FLAG 8 @@ -399,6 +394,9 @@ static sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins) #define SUB(dst, srca, srcb) \ push_3_buffer(compiler, TILEGX_OPC_SUB, dst, srca, srcb, __LINE__) +#define MUL(dst, srca, srcb) \ + push_3_buffer(compiler, TILEGX_OPC_MULX, dst, srca, srcb, __LINE__) + #define NOR(dst, srca, srcb) \ push_3_buffer(compiler, TILEGX_OPC_NOR, dst, srca, srcb, __LINE__) @@ -547,8 +545,8 @@ const struct Format* compute_format() const struct Format* match = NULL; const struct Format *b = NULL; - unsigned int i = 0; - for (i; i < sizeof formats / sizeof formats[0]; i++) { + unsigned int i; + for (i = 0; i < sizeof formats / sizeof formats[0]; i++) { b = &formats[i]; if ((b->pipe_mask & compatible_pipes) == b->pipe_mask) { match = b; @@ -625,7 +623,6 @@ tilegx_bundle_bits get_bundle_bit(struct jit_instr *inst) static sljit_si update_buffer(struct sljit_compiler *compiler) { - int count; int i; int orig_index = inst_buf_index; struct jit_instr inst0 = inst_buf[0]; @@ -738,8 +735,10 @@ static sljit_si update_buffer(struct sljit_compiler *compiler) static sljit_si flush_buffer(struct sljit_compiler *compiler) { - while (inst_buf_index != 0) - update_buffer(compiler); + while (inst_buf_index != 0) { + FAIL_IF(update_buffer(compiler)); + } + return SLJIT_SUCCESS; } static sljit_si push_4_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int op2, int op3, int line) @@ -787,6 +786,7 @@ static sljit_si push_3_buffer(struct sljit_compiler *compiler, tilegx_mnemonic o case TILEGX_OPC_ADD: case TILEGX_OPC_AND: case TILEGX_OPC_SUB: + case TILEGX_OPC_MULX: case TILEGX_OPC_OR: case TILEGX_OPC_XOR: case TILEGX_OPC_NOR: @@ -905,7 +905,6 @@ static SLJIT_INLINE sljit_ins * detect_jump_type(struct sljit_jump *jump, sljit_ sljit_sw diff; sljit_uw target_addr; sljit_ins *inst; - sljit_ins saved_inst; if (jump->flags & SLJIT_REWRITABLE_JUMP) return code_ptr; @@ -1009,7 +1008,7 @@ SLJIT_API_FUNC_ATTRIBUTE void * sljit_generate_code(struct sljit_compiler *compi struct sljit_const *const_; CHECK_ERROR_PTR(); - check_sljit_generate_code(compiler); + CHECK_PTR(check_sljit_generate_code(compiler)); reverse_buf(compiler); code = (sljit_ins *)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins)); @@ -1178,13 +1177,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil sljit_si fscratches, sljit_si fsaveds, sljit_si local_size) { sljit_ins base; - sljit_ins bundle = 0; - + sljit_si i, tmp; + CHECK_ERROR(); - check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); + CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size)); set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); - local_size += (saveds + 1) * sizeof(sljit_sw); + local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); local_size = (local_size + 7) & ~7; compiler->local_size = local_size; @@ -1200,56 +1199,52 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil local_size = 0; } + /* Save the return address. */ FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 8)); FAIL_IF(ST_ADD(ADDR_TMP_mapped, RA, -8)); - if (saveds >= 1) - FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_REG1_mapped, -8)); - - if (saveds >= 2) - FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_REG2_mapped, -8)); - - if (saveds >= 3) - FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_REG3_mapped, -8)); - - if (saveds >= 4) - FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_EREG1_mapped, -8)); - - if (saveds >= 5) - FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_EREG2_mapped, -8)); - - if (args >= 1) - FAIL_IF(ADD(SLJIT_SAVED_REG1_mapped, 0, ZERO)); + /* Save the S registers. */ + tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG; + for (i = SLJIT_S0; i >= tmp; i--) { + FAIL_IF(ST_ADD(ADDR_TMP_mapped, reg_map[i], -8)); + } - if (args >= 2) - FAIL_IF(ADD(SLJIT_SAVED_REG2_mapped, 1, ZERO)); + /* Save the R registers that need to be reserved. */ + for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { + FAIL_IF(ST_ADD(ADDR_TMP_mapped, reg_map[i], -8)); + } - if (args >= 3) - FAIL_IF(ADD(SLJIT_SAVED_REG3_mapped, 2, ZERO)); + /* Move the arguments to S registers. */ + for (i = 0; i < args; i++) { + FAIL_IF(ADD(reg_map[SLJIT_S0 - i], i, ZERO)); + } return SLJIT_SUCCESS; } -SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, +SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compiler, sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si fscratches, sljit_si fsaveds, sljit_si local_size) { - CHECK_ERROR_VOID(); - check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); + CHECK_ERROR(); + CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size)); set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); - local_size += (saveds + 1) * sizeof(sljit_sw); + local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); compiler->local_size = (local_size + 7) & ~7; + + return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw) { sljit_si local_size; sljit_ins base; - int addr_initialized = 0; + sljit_si i, tmp; + sljit_si saveds; CHECK_ERROR(); - check_sljit_emit_return(compiler, op, src, srcw); + CHECK(check_sljit_emit_return(compiler, op, src, srcw)); FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); @@ -1263,50 +1258,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi local_size = 0; } + /* Restore the return address. */ FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 8)); - FAIL_IF(LD(RA, ADDR_TMP_mapped)); - - if (compiler->saveds >= 5) { - FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 48)); - addr_initialized = 1; + FAIL_IF(LD_ADD(RA, ADDR_TMP_mapped, -8)); - FAIL_IF(LD_ADD(SLJIT_SAVED_EREG2_mapped, ADDR_TMP_mapped, 8)); + /* Restore the S registers. */ + saveds = compiler->saveds; + tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG; + for (i = SLJIT_S0; i >= tmp; i--) { + FAIL_IF(LD_ADD(reg_map[i], ADDR_TMP_mapped, -8)); } - if (compiler->saveds >= 4) { - if (addr_initialized == 0) { - FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 40)); - addr_initialized = 1; - } - - FAIL_IF(LD_ADD(SLJIT_SAVED_EREG1_mapped, ADDR_TMP_mapped, 8)); - } - - if (compiler->saveds >= 3) { - if (addr_initialized == 0) { - FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 32)); - addr_initialized = 1; - } - - FAIL_IF(LD_ADD(SLJIT_SAVED_REG3_mapped, ADDR_TMP_mapped, 8)); - } - - if (compiler->saveds >= 2) { - if (addr_initialized == 0) { - FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 24)); - addr_initialized = 1; - } - - FAIL_IF(LD_ADD(SLJIT_SAVED_REG2_mapped, ADDR_TMP_mapped, 8)); - } - - if (compiler->saveds >= 1) { - if (addr_initialized == 0) { - FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 16)); - /* addr_initialized = 1; no need to initialize as it's the last one. */ - } - - FAIL_IF(LD_ADD(SLJIT_SAVED_REG1_mapped, ADDR_TMP_mapped, 8)); + /* Restore the R registers that need to be reserved. */ + for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { + FAIL_IF(LD_ADD(reg_map[i], ADDR_TMP_mapped, -8)); } if (compiler->local_size <= SIMM_16BIT_MAX) @@ -1585,7 +1550,7 @@ static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw) { CHECK_ERROR(); - check_sljit_emit_fast_enter(compiler, dst, dstw); + CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); /* For UNUSED dst. Uncommon, but possible. */ @@ -1602,7 +1567,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw) { CHECK_ERROR(); - check_sljit_emit_fast_return(compiler, src, srcw); + CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); if (FAST_IS_REG(src)) @@ -1636,9 +1601,11 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj if (op == SLJIT_MOV_SI) return BFEXTS(reg_map[dst], reg_map[src2], 0, 31); - return BFEXTU(reg_map[dst], reg_map[src2], 0, 31); - } else if (dst != src2) - SLJIT_ASSERT_STOP(); + return BFEXTU(reg_map[dst], reg_map[src2], 0, 31); + } else if (dst != src2) { + SLJIT_ASSERT(src2 == 0); + return ADD(reg_map[dst], reg_map[src2], ZERO); + } return SLJIT_SUCCESS; @@ -1650,8 +1617,10 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj return BFEXTS(reg_map[dst], reg_map[src2], 0, 7); return BFEXTU(reg_map[dst], reg_map[src2], 0, 7); - } else if (dst != src2) - SLJIT_ASSERT_STOP(); + } else if (dst != src2) { + SLJIT_ASSERT(src2 == 0); + return ADD(reg_map[dst], reg_map[src2], ZERO); + } return SLJIT_SUCCESS; @@ -1663,8 +1632,10 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj return BFEXTS(reg_map[dst], reg_map[src2], 0, 15); return BFEXTU(reg_map[dst], reg_map[src2], 0, 15); - } else if (dst != src2) - SLJIT_ASSERT_STOP(); + } else if (dst != src2) { + SLJIT_ASSERT(src2 == 0); + return ADD(reg_map[dst], reg_map[src2], ZERO); + } return SLJIT_SUCCESS; @@ -1811,7 +1782,6 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj else { /* Rare ocasion. */ FAIL_IF(ADD(TMP_EREG2, reg_map[src1], ZERO)); - overflow_ra = TMP_EREG2; } } @@ -1903,6 +1873,17 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj return SLJIT_SUCCESS; + case SLJIT_MUL: + if (flags & SRC2_IMM) { + FAIL_IF(load_immediate(compiler, TMP_REG2_mapped, src2)); + src2 = TMP_REG2; + flags &= ~SRC2_IMM; + } + + FAIL_IF(MUL(reg_map[dst], reg_map[src1], reg_map[src2])); + + return SLJIT_SUCCESS; + #define EMIT_LOGICAL(op_imm, op_norm) \ if (flags & SRC2_IMM) { \ FAIL_IF(load_immediate(compiler, ADDR_TMP_mapped, src2)); \ @@ -1950,8 +1931,8 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj } else { \ if (op & SLJIT_SET_E) \ FAIL_IF(push_3_buffer( \ - compiler, op_imm, reg_map[dst], reg_map[src1], \ - src2 & 0x3F, __LINE__)); \ + compiler, op_norm, EQUAL_FLAG, reg_map[src1], \ + reg_map[src2], __LINE__)); \ if (CHECK_FLAGS(SLJIT_SET_E)) \ FAIL_IF(push_3_buffer( \ compiler, op_norm, reg_map[dst], reg_map[src1], \ @@ -2105,66 +2086,61 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com { sljit_si sugg_dst_ar, dst_ar; sljit_si flags = GET_ALL_FLAGS(op); + sljit_si mem_type = (op & SLJIT_INT_OP) ? (INT_DATA | SIGNED_DATA) : WORD_DATA; CHECK_ERROR(); - check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type); + CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type)); ADJUST_LOCAL_OFFSET(dst, dstw); if (dst == SLJIT_UNUSED) return SLJIT_SUCCESS; op = GET_OPCODE(op); + if (op == SLJIT_MOV_SI || op == SLJIT_MOV_UI) + mem_type = INT_DATA | SIGNED_DATA; sugg_dst_ar = reg_map[(op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2]; compiler->cache_arg = 0; compiler->cache_argw = 0; if (op >= SLJIT_ADD && (src & SLJIT_MEM)) { ADJUST_LOCAL_OFFSET(src, srcw); - FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1_mapped, src, srcw, dst, dstw)); + FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, TMP_REG1_mapped, src, srcw, dst, dstw)); src = TMP_REG1; srcw = 0; } - switch (type) { - case SLJIT_C_EQUAL: - case SLJIT_C_NOT_EQUAL: + switch (type & 0xff) { + case SLJIT_EQUAL: + case SLJIT_NOT_EQUAL: FAIL_IF(CMPLTUI(sugg_dst_ar, EQUAL_FLAG, 1)); dst_ar = sugg_dst_ar; break; - case SLJIT_C_LESS: - case SLJIT_C_GREATER_EQUAL: - case SLJIT_C_FLOAT_LESS: - case SLJIT_C_FLOAT_GREATER_EQUAL: + case SLJIT_LESS: + case SLJIT_GREATER_EQUAL: dst_ar = ULESS_FLAG; break; - case SLJIT_C_GREATER: - case SLJIT_C_LESS_EQUAL: - case SLJIT_C_FLOAT_GREATER: - case SLJIT_C_FLOAT_LESS_EQUAL: + case SLJIT_GREATER: + case SLJIT_LESS_EQUAL: dst_ar = UGREATER_FLAG; break; - case SLJIT_C_SIG_LESS: - case SLJIT_C_SIG_GREATER_EQUAL: + case SLJIT_SIG_LESS: + case SLJIT_SIG_GREATER_EQUAL: dst_ar = LESS_FLAG; break; - case SLJIT_C_SIG_GREATER: - case SLJIT_C_SIG_LESS_EQUAL: + case SLJIT_SIG_GREATER: + case SLJIT_SIG_LESS_EQUAL: dst_ar = GREATER_FLAG; break; - case SLJIT_C_OVERFLOW: - case SLJIT_C_NOT_OVERFLOW: + case SLJIT_OVERFLOW: + case SLJIT_NOT_OVERFLOW: dst_ar = OVERFLOW_FLAG; break; - case SLJIT_C_MUL_OVERFLOW: - case SLJIT_C_MUL_NOT_OVERFLOW: + case SLJIT_MUL_OVERFLOW: + case SLJIT_MUL_NOT_OVERFLOW: FAIL_IF(CMPLTUI(sugg_dst_ar, OVERFLOW_FLAG, 1)); dst_ar = sugg_dst_ar; type ^= 0x1; /* Flip type bit for the XORI below. */ break; - case SLJIT_C_FLOAT_EQUAL: - case SLJIT_C_FLOAT_NOT_EQUAL: - dst_ar = EQUAL_FLAG; - break; default: SLJIT_ASSERT_STOP(); @@ -2180,11 +2156,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com if (op >= SLJIT_ADD) { if (TMP_REG2_mapped != dst_ar) FAIL_IF(ADD(TMP_REG2_mapped, dst_ar, ZERO)); - return emit_op(compiler, op | flags, CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0); + return emit_op(compiler, op | flags, mem_type | CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0); } if (dst & SLJIT_MEM) - return emit_op_mem(compiler, WORD_DATA, dst_ar, dst, dstw); + return emit_op_mem(compiler, mem_type, dst_ar, dst, dstw); if (sugg_dst_ar != dst_ar) return ADD(sugg_dst_ar, dst_ar, ZERO); @@ -2194,7 +2170,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op) { CHECK_ERROR(); - check_sljit_emit_op0(compiler, op); + CHECK(check_sljit_emit_op0(compiler, op)); op = GET_OPCODE(op); switch (op) { @@ -2204,10 +2180,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler case SLJIT_BREAKPOINT: return PI(BPT); - case SLJIT_UMUL: - case SLJIT_SMUL: - case SLJIT_UDIV: - case SLJIT_SDIV: + case SLJIT_LUMUL: + case SLJIT_LSMUL: + case SLJIT_UDIVI: + case SLJIT_SDIVI: SLJIT_ASSERT_STOP(); } @@ -2217,7 +2193,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, sljit_si src, sljit_sw srcw) { CHECK_ERROR(); - check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw); + CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src, srcw); @@ -2273,7 +2249,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler return emit_op(compiler, SLJIT_SUB | GET_ALL_FLAGS(op), IMM_OP, dst, dstw, SLJIT_IMM, 0, src, srcw); case SLJIT_CLZ: - return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw); + return emit_op(compiler, op, (op & SLJIT_INT_OP) ? INT_DATA : WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw); } return SLJIT_SUCCESS; @@ -2282,7 +2258,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, sljit_si src1, sljit_sw src1w, sljit_si src2, sljit_sw src2w) { CHECK_ERROR(); - check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w); + CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); @@ -2325,7 +2301,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label * sljit_emit_label(struct sljit_comp flush_buffer(compiler); CHECK_ERROR_PTR(); - check_sljit_emit_label(compiler); + CHECK_PTR(check_sljit_emit_label(compiler)); if (compiler->last_label && compiler->last_label->size == compiler->size) return compiler->last_label; @@ -2344,7 +2320,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil flush_buffer(compiler); CHECK_ERROR(); - check_sljit_emit_ijump(compiler, type, src, srcw); + CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); if (FAST_IS_REG(src)) { @@ -2404,8 +2380,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil return SLJIT_SUCCESS; - } else if (src & SLJIT_MEM) + } else if (src & SLJIT_MEM) { FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw)); + flush_buffer(compiler); + } FAIL_IF(JR_SOLO(reg_map[src_r])); @@ -2432,7 +2410,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compil flush_buffer(compiler); CHECK_ERROR_PTR(); - check_sljit_emit_jump(compiler, type); + CHECK_PTR(check_sljit_emit_jump(compiler, type)); jump = (struct sljit_jump *)ensure_abuf(compiler, sizeof(struct sljit_jump)); PTR_FAIL_IF(!jump); @@ -2440,48 +2418,42 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compil type &= 0xff; switch (type) { - case SLJIT_C_EQUAL: - case SLJIT_C_FLOAT_NOT_EQUAL: + case SLJIT_EQUAL: BR_NZ(EQUAL_FLAG); break; - case SLJIT_C_NOT_EQUAL: - case SLJIT_C_FLOAT_EQUAL: + case SLJIT_NOT_EQUAL: BR_Z(EQUAL_FLAG); break; - case SLJIT_C_LESS: - case SLJIT_C_FLOAT_LESS: + case SLJIT_LESS: BR_Z(ULESS_FLAG); break; - case SLJIT_C_GREATER_EQUAL: - case SLJIT_C_FLOAT_GREATER_EQUAL: + case SLJIT_GREATER_EQUAL: BR_NZ(ULESS_FLAG); break; - case SLJIT_C_GREATER: - case SLJIT_C_FLOAT_GREATER: + case SLJIT_GREATER: BR_Z(UGREATER_FLAG); break; - case SLJIT_C_LESS_EQUAL: - case SLJIT_C_FLOAT_LESS_EQUAL: + case SLJIT_LESS_EQUAL: BR_NZ(UGREATER_FLAG); break; - case SLJIT_C_SIG_LESS: + case SLJIT_SIG_LESS: BR_Z(LESS_FLAG); break; - case SLJIT_C_SIG_GREATER_EQUAL: + case SLJIT_SIG_GREATER_EQUAL: BR_NZ(LESS_FLAG); break; - case SLJIT_C_SIG_GREATER: + case SLJIT_SIG_GREATER: BR_Z(GREATER_FLAG); break; - case SLJIT_C_SIG_LESS_EQUAL: + case SLJIT_SIG_LESS_EQUAL: BR_NZ(GREATER_FLAG); break; - case SLJIT_C_OVERFLOW: - case SLJIT_C_MUL_OVERFLOW: + case SLJIT_OVERFLOW: + case SLJIT_MUL_OVERFLOW: BR_Z(OVERFLOW_FLAG); break; - case SLJIT_C_NOT_OVERFLOW: - case SLJIT_C_MUL_NOT_OVERFLOW: + case SLJIT_NOT_OVERFLOW: + case SLJIT_MUL_NOT_OVERFLOW: BR_NZ(OVERFLOW_FLAG); break; default: @@ -2536,7 +2508,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const * sljit_emit_const(struct sljit_comp flush_buffer(compiler); CHECK_ERROR_PTR(); - check_sljit_emit_const(compiler, dst, dstw, init_value); + CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); ADJUST_LOCAL_OFFSET(dst, dstw); const_ = (struct sljit_const *)ensure_abuf(compiler, sizeof(struct sljit_const)); @@ -2572,3 +2544,18 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta inst[3] = (inst[3] & ~(0xFFFFL << 43)) | ((new_constant & 0xFFFFL) << 43); SLJIT_CACHE_FLUSH(inst, inst + 4); } + +SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg) +{ + CHECK_REG_INDEX(check_sljit_get_register_index(reg)); + return reg_map[reg]; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler, + void *instruction, sljit_si size) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_op_custom(compiler, instruction, size)); + return SLJIT_ERR_UNSUPPORTED; +} + diff --git a/src/3rdparty/pcre/sljit/sljitNativeX86_common.c b/src/3rdparty/pcre/sljit/sljitNativeX86_common.c index 21b276fb8d..e148c34cd1 100644 --- a/src/3rdparty/pcre/sljit/sljitNativeX86_common.c +++ b/src/3rdparty/pcre/sljit/sljitNativeX86_common.c @@ -744,8 +744,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler break; case SLJIT_LUMUL: case SLJIT_LSMUL: - case SLJIT_LUDIV: - case SLJIT_LSDIV: + case SLJIT_UDIVMOD: + case SLJIT_SDIVMOD: + case SLJIT_UDIVI: + case SLJIT_SDIVI: compiler->flags_saved = 0; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) #ifdef _WIN64 @@ -763,9 +765,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler #endif compiler->mode32 = op & SLJIT_INT_OP; #endif + SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments); op = GET_OPCODE(op); - if (op == SLJIT_LUDIV) { + if ((op | 0x2) == SLJIT_UDIVI) { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64) EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R1, 0); inst = emit_x86_instruction(compiler, 1, SLJIT_R1, 0, SLJIT_R1, 0); @@ -776,7 +779,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler *inst = XOR_r_rm; } - if (op == SLJIT_LSDIV) { + if ((op | 0x2) == SLJIT_SDIVI) { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64) EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R1, 0); #endif @@ -807,10 +810,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler FAIL_IF(!inst); INC_SIZE(2); *inst++ = GROUP_F7; - *inst = MOD_REG | ((op >= SLJIT_LUDIV) ? reg_map[TMP_REG1] : reg_map[SLJIT_R1]); + *inst = MOD_REG | ((op >= SLJIT_UDIVMOD) ? reg_map[TMP_REG1] : reg_map[SLJIT_R1]); #else #ifdef _WIN64 - size = (!compiler->mode32 || op >= SLJIT_LUDIV) ? 3 : 2; + size = (!compiler->mode32 || op >= SLJIT_UDIVMOD) ? 3 : 2; #else size = (!compiler->mode32) ? 3 : 2; #endif @@ -819,11 +822,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler INC_SIZE(size); #ifdef _WIN64 if (!compiler->mode32) - *inst++ = REX_W | ((op >= SLJIT_LUDIV) ? REX_B : 0); - else if (op >= SLJIT_LUDIV) + *inst++ = REX_W | ((op >= SLJIT_UDIVMOD) ? REX_B : 0); + else if (op >= SLJIT_UDIVMOD) *inst++ = REX_B; *inst++ = GROUP_F7; - *inst = MOD_REG | ((op >= SLJIT_LUDIV) ? reg_lmap[TMP_REG1] : reg_lmap[SLJIT_R1]); + *inst = MOD_REG | ((op >= SLJIT_UDIVMOD) ? reg_lmap[TMP_REG1] : reg_lmap[SLJIT_R1]); #else if (!compiler->mode32) *inst++ = REX_W; @@ -838,15 +841,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler case SLJIT_LSMUL: *inst |= IMUL; break; - case SLJIT_LUDIV: + case SLJIT_UDIVMOD: + case SLJIT_UDIVI: *inst |= DIV; break; - case SLJIT_LSDIV: + case SLJIT_SDIVMOD: + case SLJIT_SDIVI: *inst |= IDIV; break; } #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !defined(_WIN64) - EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0); + if (op <= SLJIT_SDIVMOD) + EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0); +#else + if (op >= SLJIT_UDIVI) + EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0); #endif break; } @@ -1907,60 +1916,62 @@ static sljit_si emit_test_binary(struct sljit_compiler *compiler, return SLJIT_SUCCESS; } - if (FAST_IS_REG(src1)) { + if (!(src1 & SLJIT_IMM)) { if (src2 & SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (IS_HALFWORD(src2w) || compiler->mode32) { - inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, 0); + inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, src1w); FAIL_IF(!inst); *inst = GROUP_F7; } else { FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w)); - inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src1, 0); + inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src1, src1w); FAIL_IF(!inst); *inst = TEST_rm_r; } #else - inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, 0); + inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, src1w); FAIL_IF(!inst); *inst = GROUP_F7; #endif + return SLJIT_SUCCESS; } - else { + else if (FAST_IS_REG(src1)) { inst = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w); FAIL_IF(!inst); *inst = TEST_rm_r; + return SLJIT_SUCCESS; } - return SLJIT_SUCCESS; } - if (FAST_IS_REG(src2)) { + if (!(src2 & SLJIT_IMM)) { if (src1 & SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (IS_HALFWORD(src1w) || compiler->mode32) { - inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src1w, src2, 0); + inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src1w, src2, src2w); FAIL_IF(!inst); *inst = GROUP_F7; } else { FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src1w)); - inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src2, 0); + inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src2, src2w); FAIL_IF(!inst); *inst = TEST_rm_r; } #else - inst = emit_x86_instruction(compiler, 1, src1, src1w, src2, 0); + inst = emit_x86_instruction(compiler, 1, src1, src1w, src2, src2w); FAIL_IF(!inst); *inst = GROUP_F7; #endif + return SLJIT_SUCCESS; } - else { + else if (FAST_IS_REG(src2)) { inst = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w); FAIL_IF(!inst); *inst = TEST_rm_r; + return SLJIT_SUCCESS; } - return SLJIT_SUCCESS; } EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); -- cgit v1.2.3 From 53ecaade10319ecc1d8115521ae6d8eba1ee55c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Thu, 13 Aug 2015 21:42:10 +0200 Subject: Cocoa: Fix backing store performance regression. Commit 916dfcb8 introduced a regression where QNSView would hold a copy if the backing store QImage, which would cause a detach and deep copy if/when the image was painted on while the copy was held. Revert back to the previous share-by-pointer scheme. Make sure the following bugs stays fixed: QTBUG-38377 QTBUG-42206 QTBUG-44313 Change-Id: Ib8049051d51947113f23b66ee61dc34c22388914 Task-number: QTBUG-46959 Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qcocoabackingstore.mm | 2 ++ src/plugins/platforms/cocoa/qnsview.h | 4 +-- src/plugins/platforms/cocoa/qnsview.mm | 31 +++++++++++++---------- 3 files changed, 22 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index 6a4f7ed8ee..ca92103826 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -44,6 +44,8 @@ QCocoaBackingStore::QCocoaBackingStore(QWindow *window) QCocoaBackingStore::~QCocoaBackingStore() { + if (QCocoaWindow *cocoaWindow = static_cast(window()->handle())) + [cocoaWindow->m_qtView clearBackingStore:this]; } QPaintDevice *QCocoaBackingStore::paintDevice() diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index 05ab8ae2c7..14a61554a3 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -51,8 +51,7 @@ QT_END_NAMESPACE Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper)); @interface QT_MANGLE_NAMESPACE(QNSView) : NSView { - QImage m_backingStore; - qreal m_pixelRatio; + QCocoaBackingStore* m_backingStore; QPoint m_backingStoreOffset; CGImageRef m_maskImage; uchar *m_maskData; @@ -86,6 +85,7 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper)); - (void)setQCocoaGLContext:(QCocoaGLContext *)context; #endif - (void)flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset; +- (void)clearBackingStore:(QCocoaBackingStore *)backingStore; - (void)setMaskRegion:(const QRegion *)region; - (void)invalidateWindowShadowIfNeeded; - (void)drawRect:(NSRect)dirtyRect; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index d802a36676..f27335d752 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -135,7 +135,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; { self = [super initWithFrame : NSMakeRect(0,0, 300,300)]; if (self) { - m_pixelRatio = 1.; + m_backingStore = 0; m_maskImage = 0; m_shouldInvalidateWindowShadow = false; m_window = 0; @@ -371,7 +371,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; if (!m_platformWindow->m_inSetGeometry) QWindowSystemInterface::flushWindowSystemEvents(); else - m_backingStore = QImage(); + m_backingStore = 0; } } @@ -476,12 +476,16 @@ QT_WARNING_POP - (void) flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset { - m_backingStore = backingStore->toImage(); - m_pixelRatio = backingStore->getBackingStoreDevicePixelRatio(); - m_backingStoreOffset = offset * m_pixelRatio; - foreach (QRect rect, region.rects()) { + m_backingStore = backingStore; + m_backingStoreOffset = offset * m_backingStore->getBackingStoreDevicePixelRatio(); + foreach (QRect rect, region.rects()) [self setNeedsDisplayInRect:NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height())]; - } +} + +- (void)clearBackingStore:(QCocoaBackingStore *)backingStore +{ + if (backingStore == m_backingStore) + m_backingStore = 0; } - (BOOL) hasMask @@ -544,7 +548,7 @@ QT_WARNING_POP if (m_platformWindow->m_drawContentBorderGradient) NSDrawWindowBackground(dirtyRect); - if (m_backingStore.isNull()) + if (!m_backingStore) return; // Calculate source and target rects. The target rect is the dirtyRect: @@ -552,10 +556,11 @@ QT_WARNING_POP // The backing store source rect will be larger on retina displays. // Scale dirtyRect by the device pixel ratio: - CGRect dirtyBackingRect = CGRectMake(dirtyRect.origin.x * m_pixelRatio, - dirtyRect.origin.y * m_pixelRatio, - dirtyRect.size.width * m_pixelRatio, - dirtyRect.size.height * m_pixelRatio); + const qreal devicePixelRatio = m_backingStore->getBackingStoreDevicePixelRatio(); + CGRect dirtyBackingRect = CGRectMake(dirtyRect.origin.x * devicePixelRatio, + dirtyRect.origin.y * devicePixelRatio, + dirtyRect.size.width * devicePixelRatio, + dirtyRect.size.height * devicePixelRatio); NSGraphicsContext *nsGraphicsContext = [NSGraphicsContext currentContext]; CGContextRef cgContext = (CGContextRef) [nsGraphicsContext graphicsPort]; @@ -581,7 +586,7 @@ QT_WARNING_POP dirtyBackingRect.size.width, dirtyBackingRect.size.height ); - CGImageRef bsCGImage = qt_mac_toCGImage(m_backingStore); + CGImageRef bsCGImage = qt_mac_toCGImage(m_backingStore->toImage()); CGImageRef cleanImg = CGImageCreateWithImageInRect(bsCGImage, backingStoreRect); // Optimization: Copy frame buffer content instead of blending for -- cgit v1.2.3 From 418824dc691fd7fe2fede6b9566f0c4db098e772 Mon Sep 17 00:00:00 2001 From: Takao Fujiwara Date: Tue, 25 Aug 2015 14:54:31 +0900 Subject: ibus: Return correct scan code to windows ibus keycode is qt scancode - 8 and needs to be returned to app windows as the right value. Use QWindowSystemInterface::handleExtendedKeyEvent() instead of QCoreApplication::sendEvent() in qtbase 5.6 to follow QXcbKeyboard::handleKeyEvent(). Also qApp->focusObject() returns QMdiChild which is a QWidget and that is not a QWindow. Task-number: QTBUG-47833 Change-Id: Ie634a86d7790d8093cfca2dc8666f726844ae654 Reviewed-by: Lars Knoll Reviewed-by: Friedemann Kleint --- .../ibus/qibusplatforminputcontext.cpp | 44 +++++++++++++++------- .../ibus/qibusplatforminputcontext.h | 9 +++-- 2 files changed, 35 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp index 4a276dc834..27fca7c6ed 100644 --- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp +++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp @@ -301,12 +301,12 @@ bool QIBusPlatformInputContext::filterEvent(const QEvent *event) quint32 sym = keyEvent->nativeVirtualKey(); quint32 code = keyEvent->nativeScanCode(); quint32 state = keyEvent->nativeModifiers(); + quint32 ibusState = state; if (keyEvent->type() != QEvent::KeyPress) - state |= IBUS_RELEASE_MASK; + ibusState |= IBUS_RELEASE_MASK; - code -= 8; // ### - QDBusPendingReply reply = d->context->ProcessKeyEvent(sym, code, state); + QDBusPendingReply reply = d->context->ProcessKeyEvent(sym, code - 8, ibusState); if (m_eventFilterUseSynchronousMode || reply.isFinished()) { bool retval = reply.value(); @@ -315,17 +315,36 @@ bool QIBusPlatformInputContext::filterEvent(const QEvent *event) } Qt::KeyboardModifiers modifiers = keyEvent->modifiers(); + const int qtcode = keyEvent->key(); + + // From QKeyEvent::modifiers() + switch (qtcode) { + case Qt::Key_Shift: + modifiers ^= Qt::ShiftModifier; + break; + case Qt::Key_Control: + modifiers ^= Qt::ControlModifier; + break; + case Qt::Key_Alt: + modifiers ^= Qt::AltModifier; + break; + case Qt::Key_Meta: + modifiers ^= Qt::MetaModifier; + break; + case Qt::Key_AltGr: + modifiers ^= Qt::GroupSwitchModifier; + break; + } QVariantList args; args << QVariant::fromValue(keyEvent->timestamp()); args << QVariant::fromValue(static_cast(keyEvent->type())); - args << QVariant::fromValue(keyEvent->key()); + args << QVariant::fromValue(qtcode); args << QVariant::fromValue(code) << QVariant::fromValue(sym) << QVariant::fromValue(state); args << QVariant::fromValue(keyEvent->text()); args << QVariant::fromValue(keyEvent->isAutoRepeat()); - args << QVariant::fromValue(keyEvent->count()); - QIBusFilterEventWatcher *watcher = new QIBusFilterEventWatcher(reply, this, qApp->focusObject(), modifiers, args); + QIBusFilterEventWatcher *watcher = new QIBusFilterEventWatcher(reply, this, QGuiApplication::focusWindow(), modifiers, args); QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, &QIBusPlatformInputContext::filterEventFinished); return true; @@ -343,9 +362,9 @@ void QIBusPlatformInputContext::filterEventFinished(QDBusPendingCallWatcher *cal // Use watcher's window instead of the current focused window // since there is a time lag until filterEventFinished() returns. - QObject *input = watcher->input(); + QWindow *window = watcher->window(); - if (!input) { + if (!window) { call->deleteLater(); return; } @@ -360,13 +379,11 @@ void QIBusPlatformInputContext::filterEventFinished(QDBusPendingCallWatcher *cal const quint32 state = args.at(5).toUInt(); const QString string = args.at(6).toString(); const bool isAutoRepeat = args.at(7).toBool(); - const int count = args.at(8).toInt(); // copied from QXcbKeyboard::handleKeyEvent() bool retval = reply.value(); qCDebug(qtQpaInputMethods) << "filterEventFinished return" << code << sym << state << retval; if (!retval) { - QWindow *window = dynamic_cast(input); if (type == QEvent::KeyPress && qtcode == Qt::Key_Menu && window != NULL) { const QPoint globalPos = window->screen()->handle()->cursor()->pos(); @@ -374,10 +391,9 @@ void QIBusPlatformInputContext::filterEventFinished(QDBusPendingCallWatcher *cal QWindowSystemInterface::handleContextMenuEvent(window, false, pos, globalPos, modifiers); } - QKeyEvent event(type, qtcode, modifiers, code, sym, - state, string, isAutoRepeat, count); - event.setTimestamp(time); - QCoreApplication::sendEvent(input, &event); + QWindowSystemInterface::handleExtendedKeyEvent(window, time, type, qtcode, modifiers, + code, sym, state, string, isAutoRepeat); + } call->deleteLater(); } diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h index 91f15ea159..127db7df8b 100644 --- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h +++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h @@ -38,6 +38,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -51,23 +52,23 @@ class QIBusFilterEventWatcher: public QDBusPendingCallWatcher public: explicit QIBusFilterEventWatcher(const QDBusPendingCall &call, QObject *parent = 0, - QObject *input = 0, + QWindow *window = 0, const Qt::KeyboardModifiers modifiers = 0, const QVariantList arguments = QVariantList()) : QDBusPendingCallWatcher(call, parent) - , m_input(input) + , m_window(window) , m_modifiers(modifiers) , m_arguments(arguments) {} ~QIBusFilterEventWatcher() {} - inline QObject *input() const { return m_input; } + inline QWindow *window() const { return m_window; } inline const Qt::KeyboardModifiers modifiers() const { return m_modifiers; } inline const QVariantList arguments() const { return m_arguments; } private: - QPointer m_input; + QPointer m_window; const Qt::KeyboardModifiers m_modifiers; const QVariantList m_arguments; }; -- cgit v1.2.3 From 5a500100581f17f057f1958f956b2ddaf7048ecf Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 14 Aug 2015 16:09:21 +0200 Subject: Be more tolerant with multiple differerent metatype registrations There is a qFatal in qmetatype.cpp that checks that the flags are the same. There is a binary compatibility break because if any cause build with Qt 5.5 is loaded, this qFatal will quit the application, due to the change in commit 54a09a41885e65fea4ca20d0e3d90d8f4e9e80c5: Type flags for type 'QtMetaTypePrivate::QPairVariantInterfaceImpl' [1034] don't match. Previously registered TypeFlags(0x103), now registering TypeFlags(0x107). This is an ODR break, which means that your application depends on a C++ undefined behavior. This is a false positive since it is an internal type, the MovableType in QMetaType is only being used for performance reason, it is perfectly fine to change it. This commit changes the qFatal to complain only about flags that could only be caused by a binary incompatible change. Change-Id: I87b9bf8cf54b6c7f4b1277d411ce5107642435ab Reviewed-by: Thiago Macieira --- src/corelib/kernel/qmetatype.cpp | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index 3906cdc036..01e2542dfa 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -1081,25 +1081,16 @@ int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName, normalizedTypeName.constData(), idx, previousSize, size); } - // Do not compare types higher than 0x100: - // Ignore WasDeclaredAsMetaType inconsitency, to many users were hitting the problem - // Ignore IsGadget as it was added in Qt 5.5 - // Ignore all the future flags as well - if ((previousFlags ^ flags) & 0xff) { - const int maskForTypeInfo = NeedsConstruction | NeedsDestruction | MovableType; + // these flags cannot change in a binary compatible way: + const int binaryCompatibilityFlag = PointerToQObject | IsEnumeration | SharedPointerToQObject + | WeakPointerToQObject | TrackingPointerToQObject; + if ((previousFlags ^ flags) & binaryCompatibilityFlag) { + const char *msg = "QMetaType::registerType: Binary compatibility break. " "\nType flags for type '%s' [%i] don't match. Previously " - "registered TypeFlags(0x%x), now registering TypeFlags(0x%x). " - "This is an ODR break, which means that your application depends on a C++ undefined behavior." - "\nHint: %s"; - QT_PREPEND_NAMESPACE(QByteArray) hint; - if ((previousFlags & maskForTypeInfo) != (flags & maskForTypeInfo)) { - hint += "\nIt seems that the type was registered at least twice in a different translation units, " - "but Q_DECLARE_TYPEINFO is not visible from all the translations unit or different flags were used." - "Remember that Q_DECLARE_TYPEINFO should be declared before QMetaType registration, " - "preferably it should be placed just after the type declaration and before Q_DECLARE_METATYPE"; - } - qFatal(msg, normalizedTypeName.constData(), idx, previousFlags, int(flags), hint.constData()); + "registered TypeFlags(0x%x), now registering TypeFlags(0x%x). "; + + qFatal(msg, normalizedTypeName.constData(), idx, previousFlags, int(flags)); } return idx; -- cgit v1.2.3 From a5f46bc64798a4f5a63c7507c9e74a21247a6f49 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Mon, 24 Aug 2015 13:43:13 +0200 Subject: Doc: Fix QDoc warnings for QOpenGLFunctions and QOpenGLExtraFunctions - Use \a commands when listing the arguments for OpenGL methods - Document functions taking a single argument of type 'void' verbatim. Otherwise, QDoc refuses to generate their docs - Add constructor docs for QOpenGLExtraFunctions (copied from QOpenGLFunctions). Change-Id: I64a436365572a80319ba0a8eaba2f5d9b751e84d Reviewed-by: Venugopal Shivashankar Reviewed-by: Laszlo Agocs --- src/gui/opengl/qopenglfunctions.cpp | 165 ++++++++++++++++++++---------------- 1 file changed, 90 insertions(+), 75 deletions(-) (limited to 'src') diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp index 668eaa9a89..d614ad8401 100644 --- a/src/gui/opengl/qopenglfunctions.cpp +++ b/src/gui/opengl/qopenglfunctions.cpp @@ -3701,7 +3701,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) - Convenience function that calls glCopyBufferSubData(\a readTarget, writeTarget, \a readOffset, \a writeOffset, \a size). + Convenience function that calls glCopyBufferSubData(\a readTarget, \a writeTarget, \a readOffset, \a writeOffset, \a size). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -3855,7 +3855,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) */ /*! - \fn void QOpenGLExtraFunctions::glEndTransformFeedback() + \fn void QOpenGLExtraFunctions::glEndTransformFeedback(void) Convenience function that calls glEndTransformFeedback(). @@ -4362,7 +4362,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) */ /*! - \fn void QOpenGLExtraFunctions::glPauseTransformFeedback() + \fn void QOpenGLExtraFunctions::glPauseTransformFeedback(void) Convenience function that calls glPauseTransformFeedback(). @@ -4427,7 +4427,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) */ /*! - \fn void QOpenGLExtraFunctions::glResumeTransformFeedback() + \fn void QOpenGLExtraFunctions::glResumeTransformFeedback(void) Convenience function that calls glResumeTransformFeedback(). @@ -4455,7 +4455,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat * param) - Convenience function that calls glSamplerParameterfv(\a sampler, pname, \a param). + Convenience function that calls glSamplerParameterfv(\a sampler, \a pname, \a param). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -4624,7 +4624,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glUniform3uiv(GLint location, GLsizei count, const GLuint * value) - Convenience function that calls glUniform3uiv(\a location, count, \a value). + Convenience function that calls glUniform3uiv(\a location, \a count, \a value). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -4858,7 +4858,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glActiveShaderProgram(GLuint pipeline, GLuint program) - Convenience function that calls glActiveShaderProgram(pipeline, program). + Convenience function that calls glActiveShaderProgram(\a pipeline, \a program). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -4869,9 +4869,9 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) */ /*! - \fn void QOpenGLFunctions::glBindImageTexture(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format) + \fn void QOpenGLExtraFunctions::glBindImageTexture(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format) - Convenience function that calls glBindImageTexture(unit, texture, level, layered, layer, access, format). + Convenience function that calls glBindImageTexture(\a unit, \a texture, \a level, \a layered, \a layer, \a access, \a format). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -4884,7 +4884,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glBindProgramPipeline(GLuint pipeline) - Convenience function that calls glBindProgramPipeline(pipeline). + Convenience function that calls glBindProgramPipeline(\a pipeline). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -4897,7 +4897,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glBindVertexBuffer(GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride) - Convenience function that calls glBindVertexBuffer(bindingindex, buffer, offset, stride). + Convenience function that calls glBindVertexBuffer(\a bindingindex, \a buffer, \a offset, \a stride). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -4910,7 +4910,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn GLuint QOpenGLExtraFunctions::glCreateShaderProgramv(GLenum type, GLsizei count, const GLchar *const* strings) - Convenience function that calls glCreateShaderProgramv(type, count, strings). + Convenience function that calls glCreateShaderProgramv(\a type, \a count, \a strings). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -4923,7 +4923,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glDeleteProgramPipelines(GLsizei n, const GLuint * pipelines) - Convenience function that calls glDeleteProgramPipelines(n, pipelines). + Convenience function that calls glDeleteProgramPipelines(\a n, \a pipelines). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -4936,7 +4936,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glDispatchCompute(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z) - Convenience function that calls glDispatchCompute(num_groups_x, num_groups_y, num_groups_z). + Convenience function that calls glDispatchCompute(\a num_groups_x, \a num_groups_y, \a num_groups_z). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -4949,7 +4949,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glDispatchComputeIndirect(GLintptr indirect) - Convenience function that calls glDispatchComputeIndirect(indirect). + Convenience function that calls glDispatchComputeIndirect(\a indirect). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -4962,7 +4962,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glDrawArraysIndirect(GLenum mode, const void * indirect) - Convenience function that calls glDrawArraysIndirect(mode, indirect). + Convenience function that calls glDrawArraysIndirect(\a mode, \a indirect). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -4975,7 +4975,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glDrawElementsIndirect(GLenum mode, GLenum type, const void * indirect) - Convenience function that calls glDrawElementsIndirect(mode, type, indirect). + Convenience function that calls glDrawElementsIndirect(\a mode, \a type, \a indirect). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -4988,7 +4988,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glFramebufferParameteri(GLenum target, GLenum pname, GLint param) - Convenience function that calls glFramebufferParameteri(target, pname, param). + Convenience function that calls glFramebufferParameteri(\a target, \a pname, \a param). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5001,7 +5001,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glGenProgramPipelines(GLsizei n, GLuint* pipelines) - Convenience function that calls glGenProgramPipelines(n, pipelines). + Convenience function that calls glGenProgramPipelines(\a n, \a pipelines). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5014,7 +5014,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glGetBooleani_v(GLenum target, GLuint index, GLboolean* data) - Convenience function that calls glGetBooleani_v(target, index, data). + Convenience function that calls glGetBooleani_v(\a target, \a index, \a data). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5027,7 +5027,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glGetFramebufferParameteriv(GLenum target, GLenum pname, GLint* params) - Convenience function that calls glGetFramebufferParameteriv(target, pname, params). + Convenience function that calls glGetFramebufferParameteriv(\a target, \a pname, \a params). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5040,7 +5040,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glGetMultisamplefv(GLenum pname, GLuint index, GLfloat* val) - Convenience function that calls glGetMultisamplefv(pname, index, val). + Convenience function that calls glGetMultisamplefv(\a pname, \a index, \a val). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5053,7 +5053,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glGetProgramInterfaceiv(GLuint program, GLenum programInterface, GLenum pname, GLint* params) - Convenience function that calls glGetProgramInterfaceiv(program, programInterface, pname, params). + Convenience function that calls glGetProgramInterfaceiv(\a program, \a programInterface, \a pname, \a params). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5066,7 +5066,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glGetProgramPipelineInfoLog(GLuint pipeline, GLsizei bufSize, GLsizei* length, GLchar* infoLog) - Convenience function that calls glGetProgramPipelineInfoLog(pipeline, bufSize, length, infoLog). + Convenience function that calls glGetProgramPipelineInfoLog(\a pipeline, \a bufSize, \a length, \a infoLog). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5079,7 +5079,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glGetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint* params) - Convenience function that calls glGetProgramPipelineiv(pipeline, pname, params). + Convenience function that calls glGetProgramPipelineiv(\a pipeline, \a pname, \a params). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5092,7 +5092,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn GLuint QOpenGLExtraFunctions::glGetProgramResourceIndex(GLuint program, GLenum programInterface, const GLchar * name) - Convenience function that calls glGetProgramResourceIndex(program, programInterface, name). + Convenience function that calls glGetProgramResourceIndex(\a program, \a programInterface, \a name). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5105,7 +5105,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn GLint QOpenGLExtraFunctions::glGetProgramResourceLocation(GLuint program, GLenum programInterface, const GLchar * name) - Convenience function that calls glGetProgramResourceLocation(program, programInterface, name). + Convenience function that calls glGetProgramResourceLocation(\a program, \a programInterface, \a name). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5118,7 +5118,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glGetProgramResourceName(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length, GLchar* name) - Convenience function that calls glGetProgramResourceName(program, programInterface, index, bufSize, length, name). + Convenience function that calls glGetProgramResourceName(\a program, \a programInterface, \a index, \a bufSize, \a length, \a name). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5131,7 +5131,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glGetProgramResourceiv(GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei bufSize, GLsizei* length, GLint* params) - Convenience function that calls glGetProgramResourceiv(program, programInterface, index, propCount, props, bufSize, length, params). + Convenience function that calls glGetProgramResourceiv(\a program, \a programInterface, \a index, \a propCount, \a props, \a bufSize, \a length, \a params). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5144,7 +5144,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glGetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat* params) - Convenience function that calls glGetTexLevelParameterfv(target, level, pname, params). + Convenience function that calls glGetTexLevelParameterfv(\a target, \a level, \a pname, \a params). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5157,7 +5157,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint* params) - Convenience function that calls glGetTexLevelParameteriv(target, level, pname, params). + Convenience function that calls glGetTexLevelParameteriv(\a target, \a level, \a pname, \a params). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5170,7 +5170,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn GLboolean QOpenGLExtraFunctions::glIsProgramPipeline(GLuint pipeline) - Convenience function that calls glIsProgramPipeline(pipeline). + Convenience function that calls glIsProgramPipeline(\a pipeline). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5183,7 +5183,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glMemoryBarrier(GLbitfield barriers) - Convenience function that calls glMemoryBarrier(barriers). + Convenience function that calls glMemoryBarrier(\a barriers). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5196,7 +5196,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glMemoryBarrierByRegion(GLbitfield barriers) - Convenience function that calls glMemoryBarrierByRegion(barriers). + Convenience function that calls glMemoryBarrierByRegion(\a barriers). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5209,7 +5209,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniform1f(GLuint program, GLint location, GLfloat v0) - Convenience function that calls glProgramUniform1f(program, location, v0). + Convenience function that calls glProgramUniform1f(\a program, \a location, \a v0). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5222,7 +5222,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniform1fv(GLuint program, GLint location, GLsizei count, const GLfloat * value) - Convenience function that calls glProgramUniform1fv(program, location, count, value). + Convenience function that calls glProgramUniform1fv(\a program, \a location, \a count, \a value). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5235,7 +5235,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniform1i(GLuint program, GLint location, GLint v0) - Convenience function that calls glProgramUniform1i(program, location, v0). + Convenience function that calls glProgramUniform1i(\a program, \a location, \a v0). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5248,7 +5248,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniform1iv(GLuint program, GLint location, GLsizei count, const GLint * value) - Convenience function that calls glProgramUniform1iv(program, location, count, value). + Convenience function that calls glProgramUniform1iv(\a program, \a location, \a count, \a value). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5261,7 +5261,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniform1ui(GLuint program, GLint location, GLuint v0) - Convenience function that calls glProgramUniform1ui(program, location, v0). + Convenience function that calls glProgramUniform1ui(\a program, \a location, \a v0). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5274,7 +5274,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniform1uiv(GLuint program, GLint location, GLsizei count, const GLuint * value) - Convenience function that calls glProgramUniform1uiv(program, location, count, value). + Convenience function that calls glProgramUniform1uiv(\a program, \a location, \a count, \a value). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5287,7 +5287,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniform2f(GLuint program, GLint location, GLfloat v0, GLfloat v1) - Convenience function that calls glProgramUniform2f(program, location, v0, v1). + Convenience function that calls glProgramUniform2f(\a program, \a location, \a v0, \a v1). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5300,7 +5300,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniform2fv(GLuint program, GLint location, GLsizei count, const GLfloat * value) - Convenience function that calls glProgramUniform2fv(program, location, count, value). + Convenience function that calls glProgramUniform2fv(\a program, \a location, \a count, \a value). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5313,7 +5313,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniform2i(GLuint program, GLint location, GLint v0, GLint v1) - Convenience function that calls glProgramUniform2i(program, location, v0, v1). + Convenience function that calls glProgramUniform2i(\a program, \a location, \a v0, \a v1). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5326,7 +5326,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniform2iv(GLuint program, GLint location, GLsizei count, const GLint * value) - Convenience function that calls glProgramUniform2iv(program, location, count, value). + Convenience function that calls glProgramUniform2iv(\a program, \a location, \a count, \a value). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5339,7 +5339,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniform2ui(GLuint program, GLint location, GLuint v0, GLuint v1) - Convenience function that calls glProgramUniform2ui(program, location, v0, v1). + Convenience function that calls glProgramUniform2ui(\a program, \a location, \a v0, \a v1). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5352,7 +5352,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniform2uiv(GLuint program, GLint location, GLsizei count, const GLuint * value) - Convenience function that calls glProgramUniform2uiv(program, location, count, value). + Convenience function that calls glProgramUniform2uiv(\a program, \a location, \a count, \a value). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5365,7 +5365,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniform3f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2) - Convenience function that calls glProgramUniform3f(program, location, v0, v1, v2). + Convenience function that calls glProgramUniform3f(\a program, \a location, \a v0, \a v1, \a v2). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5378,7 +5378,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniform3fv(GLuint program, GLint location, GLsizei count, const GLfloat * value) - Convenience function that calls glProgramUniform3fv(program, location, count, value). + Convenience function that calls glProgramUniform3fv(\a program, \a location, \a count, \a value). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5391,7 +5391,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniform3i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2) - Convenience function that calls glProgramUniform3i(program, location, v0, v1, v2). + Convenience function that calls glProgramUniform3i(\a program, \a location, \a v0, \a v1, \a v2). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5404,7 +5404,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniform3iv(GLuint program, GLint location, GLsizei count, const GLint * value) - Convenience function that calls glProgramUniform3iv(program, location, count, value). + Convenience function that calls glProgramUniform3iv(\a program, \a location, \a count, \a value). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5417,7 +5417,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniform3ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2) - Convenience function that calls glProgramUniform3ui(program, location, v0, v1, v2). + Convenience function that calls glProgramUniform3ui(\a program, \a location, \a v0, \a v1, \a v2). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5430,7 +5430,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniform3uiv(GLuint program, GLint location, GLsizei count, const GLuint * value) - Convenience function that calls glProgramUniform3uiv(program, location, count, value). + Convenience function that calls glProgramUniform3uiv(\a program, \a location, \a count, \a value). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5443,7 +5443,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniform4f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) - Convenience function that calls glProgramUniform4f(program, location, v0, v1, v2, v3). + Convenience function that calls glProgramUniform4f(\a program, \a location, \a v0, \a v1, \a v2, \a v3). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5456,7 +5456,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniform4fv(GLuint program, GLint location, GLsizei count, const GLfloat * value) - Convenience function that calls glProgramUniform4fv(program, location, count, value). + Convenience function that calls glProgramUniform4fv(\a program, \a location, \a count, \a value). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5469,7 +5469,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniform4i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3) - Convenience function that calls glProgramUniform4i(program, location, v0, v1, v2, v3). + Convenience function that calls glProgramUniform4i(\a program, \a location, \a v0, \a v1, \a v2, \a v3). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5482,7 +5482,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniform4iv(GLuint program, GLint location, GLsizei count, const GLint * value) - Convenience function that calls glProgramUniform4iv(program, location, count, value). + Convenience function that calls glProgramUniform4iv(\a program, \a location, \a count, \a value). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5495,7 +5495,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniform4ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) - Convenience function that calls glProgramUniform4ui(program, location, v0, v1, v2, v3). + Convenience function that calls glProgramUniform4ui(\a program, \a location, \a v0, \a v1, \a v2, \a v3). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5508,7 +5508,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniform4uiv(GLuint program, GLint location, GLsizei count, const GLuint * value) - Convenience function that calls glProgramUniform4uiv(program, location, count, value). + Convenience function that calls glProgramUniform4uiv(\a program, \a location, \a count, \a value). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5521,7 +5521,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniformMatrix2fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) - Convenience function that calls glProgramUniformMatrix2fv(program, location, count, transpose, value). + Convenience function that calls glProgramUniformMatrix2fv(\a program, \a location, \a count, \a transpose, \a value). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5534,7 +5534,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniformMatrix2x3fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) - Convenience function that calls glProgramUniformMatrix2x3fv(program, location, count, transpose, value). + Convenience function that calls glProgramUniformMatrix2x3fv(\a program, \a location, \a count, \a transpose, \a value). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5547,7 +5547,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniformMatrix2x4fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) - Convenience function that calls glProgramUniformMatrix2x4fv(program, location, count, transpose, value). + Convenience function that calls glProgramUniformMatrix2x4fv(\a program, \a location, \a count, \a transpose, \a value). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5560,7 +5560,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniformMatrix3fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) - Convenience function that calls glProgramUniformMatrix3fv(program, location, count, transpose, value). + Convenience function that calls glProgramUniformMatrix3fv(\a program, \a location, \a count, \a transpose, \a value). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5573,7 +5573,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniformMatrix3x2fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) - Convenience function that calls glProgramUniformMatrix3x2fv(program, location, count, transpose, value). + Convenience function that calls glProgramUniformMatrix3x2fv(\a program, \a location, \a count, \a transpose, \a value). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5586,7 +5586,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniformMatrix3x4fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) - Convenience function that calls glProgramUniformMatrix3x4fv(program, location, count, transpose, value). + Convenience function that calls glProgramUniformMatrix3x4fv(\a program, \a location, \a count, \a transpose, \a value). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5599,7 +5599,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniformMatrix4fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) - Convenience function that calls glProgramUniformMatrix4fv(program, location, count, transpose, value). + Convenience function that calls glProgramUniformMatrix4fv(\a program, \a location, \a count, \a transpose, \a value). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5612,7 +5612,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniformMatrix4x2fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) - Convenience function that calls glProgramUniformMatrix4x2fv(program, location, count, transpose, value). + Convenience function that calls glProgramUniformMatrix4x2fv(\a program, \a location, \a count, \a transpose, \a value). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5625,7 +5625,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glProgramUniformMatrix4x3fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) - Convenience function that calls glProgramUniformMatrix4x3fv(program, location, count, transpose, value). + Convenience function that calls glProgramUniformMatrix4x3fv(\a program, \a location, \a count, \a transpose, \a value). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5638,7 +5638,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glSampleMaski(GLuint maskNumber, GLbitfield mask) - Convenience function that calls glSampleMaski(maskNumber, mask). + Convenience function that calls glSampleMaski(\a maskNumber, \a mask). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5651,7 +5651,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glTexStorage2DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) - Convenience function that calls glTexStorage2DMultisample(target, samples, internalformat, width, height, fixedsamplelocations). + Convenience function that calls glTexStorage2DMultisample(\a target, \a samples, \a internalformat, \a width, \a height, \a fixedsamplelocations). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5664,7 +5664,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glUseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program) - Convenience function that calls glUseProgramStages(pipeline, stages, program). + Convenience function that calls glUseProgramStages(\a pipeline, \a stages, \a program). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5677,7 +5677,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glValidateProgramPipeline(GLuint pipeline) - Convenience function that calls glValidateProgramPipeline(pipeline). + Convenience function that calls glValidateProgramPipeline(\a pipeline). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5690,7 +5690,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glVertexAttribBinding(GLuint attribindex, GLuint bindingindex) - Convenience function that calls glVertexAttribBinding(attribindex, bindingindex). + Convenience function that calls glVertexAttribBinding(\a attribindex, \a bindingindex). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5703,7 +5703,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glVertexAttribFormat(GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) - Convenience function that calls glVertexAttribFormat(attribindex, size, type, normalized, relativeoffset). + Convenience function that calls glVertexAttribFormat(\a attribindex, \a size, \a type, \a normalized, \a relativeoffset). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5716,7 +5716,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glVertexAttribIFormat(GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) - Convenience function that calls glVertexAttribIFormat(attribindex, size, type, relativeoffset). + Convenience function that calls glVertexAttribIFormat(\a attribindex, \a size, \a type, \a relativeoffset). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -5729,7 +5729,7 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) /*! \fn void QOpenGLExtraFunctions::glVertexBindingDivisor(GLuint bindingindex, GLuint divisor) - Convenience function that calls glVertexBindingDivisor(bindingindex, divisor). + Convenience function that calls glVertexBindingDivisor(\a bindingindex, \a divisor). This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running with plain OpenGL, the function is only usable when the given profile and version contains the @@ -7398,10 +7398,25 @@ static void QOPENGLF_APIENTRY qopenglfResolveVertexBindingDivisor(GLuint binding RESOLVE_FUNC_VOID(0, VertexBindingDivisor)(bindingindex, divisor); } +/*! + Constructs a default function resolver. The resolver cannot be used until + \l {QOpenGLFunctions::}{initializeOpenGLFunctions()} is called to specify + the context. +*/ QOpenGLExtraFunctions::QOpenGLExtraFunctions() { } +/*! + Constructs a function resolver for context. If \a context is null, then + the resolver will be created for the current QOpenGLContext. + + The context or another context in the group must be current. + + An object constructed in this way can only be used with context and other + contexts that share with it. Use \l {QOpenGLFunctions::} + {initializeOpenGLFunctions()} to change the object's context association. +*/ QOpenGLExtraFunctions::QOpenGLExtraFunctions(QOpenGLContext *context) : QOpenGLFunctions(context) { -- cgit v1.2.3 From 191b7237bfd5c2e74c0a25a17390dbb67073cf38 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Tue, 25 Aug 2015 12:34:12 +0200 Subject: qdoc: Use lowercase names for modules read from index files The module names are used as keys in the map that defines the forest of module trees. A physical module name (lowercase) is used as the primary tree name, but modules read from index were using a name written to the index file (project name, typically CamelCase) as-is. This caused issues for resolving link commands that have a module name in the square bracket parameters. To ensure that such links work, convert module names read from index to lowercase, too. Change-Id: I698e01fd1df888e4a78c06a76ad72b5eb1a70892 Reviewed-by: Martin Smith --- src/tools/qdoc/qdocdatabase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/tools/qdoc/qdocdatabase.cpp b/src/tools/qdoc/qdocdatabase.cpp index 97f1929fb4..5ca8e36ef9 100644 --- a/src/tools/qdoc/qdocdatabase.cpp +++ b/src/tools/qdoc/qdocdatabase.cpp @@ -276,7 +276,7 @@ const QVector& QDocForest::indexSearchOrder() NamespaceNode* QDocForest::newIndexTree(const QString& module) { primaryTree_ = new Tree(module, qdb_); - forest_.insert(module, primaryTree_); + forest_.insert(module.toLower(), primaryTree_); return primaryTree_->root(); } -- cgit v1.2.3 From c3a0f22b6024f09af63125d14e6c8e248095fa0f Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Tue, 25 Aug 2015 12:59:25 +0200 Subject: qdoc: allow 'void' function parameter without a parameter name There are a few functions using a C-style function declaration: void foo(void); meaning that foo() takes no parameters. This change allows this for QDoc, making it successfully match documented \fn blocks with the correct declaration, and not print out warnings. Change-Id: I8191c55094371431b0e9c2ad22d19cadcb7facfb Reviewed-by: Martin Smith --- src/tools/qdoc/generator.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/tools/qdoc/generator.cpp b/src/tools/qdoc/generator.cpp index 7dfbbb1cb8..dc731f0121 100644 --- a/src/tools/qdoc/generator.cpp +++ b/src/tools/qdoc/generator.cpp @@ -807,6 +807,7 @@ void Generator::generateBody(const Node *node, CodeMarker *marker) QVector::ConstIterator p = func->parameters().constBegin(); while (p != func->parameters().constEnd()) { if ((*p).name().isEmpty() && (*p).dataType() != QLatin1String("...") + && (*p).dataType() != QLatin1String("void") && func->name() != QLatin1String("operator++") && func->name() != QLatin1String("operator--")) { node->doc().location().warning(tr("Missing parameter name")); -- cgit v1.2.3 From 06b457c693f207e392d3021d77a0ab18cd78da92 Mon Sep 17 00:00:00 2001 From: Stanislav Baiduzhyi Date: Fri, 21 Aug 2015 14:14:38 +0200 Subject: Adding plasma5 support for QKdeTheme Plasma 5 uses the same config files structure, but follows XDG spec instead of storing them in custom locations. Added '5' to supported KDE session version, and passing it to other methods because 'kdeglobals' is located directly under XDG config dirs and not deeper inside. [ChangeLog][QtPlatformSupport][QKdeTheme] adding plasma5 support Change-Id: I5f1d8d8f8d02449328db3ffc391ad23506cd67c7 Reviewed-by: Friedemann Kleint Reviewed-by: David Faure --- .../themes/genericunix/qgenericunixthemes.cpp | 64 ++++++++++++---------- 1 file changed, 36 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp index 2e17c3f63c..cd38498217 100644 --- a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp +++ b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -209,14 +210,16 @@ public: , wheelScrollLines(3) { } - static QString kdeGlobals(const QString &kdeDir) + static QString kdeGlobals(const QString &kdeDir, int kdeVersion) { + if (kdeVersion > 4) + return kdeDir + QStringLiteral("/kdeglobals"); return kdeDir + QStringLiteral("/share/config/kdeglobals"); } void refresh(); - static QVariant readKdeSetting(const QString &key, const QStringList &kdeDirs, QHash &kdeSettings); - static void readKdeSystemPalette(const QStringList &kdeDirs, QHash &kdeSettings, QPalette *pal); + static QVariant readKdeSetting(const QString &key, const QStringList &kdeDirs, int kdeVersion, QHash &kdeSettings); + static void readKdeSystemPalette(const QStringList &kdeDirs, int kdeVersion, QHash &kdeSettings, QPalette *pal); static QFont *kdeFont(const QVariant &fontValue); static QStringList kdeIconThemeSearchPaths(const QStringList &kdeDirs); @@ -246,30 +249,30 @@ void QKdeThemePrivate::refresh() QHash kdeSettings; QPalette systemPalette = QPalette(); - readKdeSystemPalette(kdeDirs, kdeSettings, &systemPalette); + readKdeSystemPalette(kdeDirs, kdeVersion, kdeSettings, &systemPalette); resources.palettes[QPlatformTheme::SystemPalette] = new QPalette(systemPalette); //## TODO tooltip color - const QVariant styleValue = readKdeSetting(QStringLiteral("widgetStyle"), kdeDirs, kdeSettings); + const QVariant styleValue = readKdeSetting(QStringLiteral("widgetStyle"), kdeDirs, kdeVersion, kdeSettings); if (styleValue.isValid()) { const QString style = styleValue.toString(); if (style != styleNames.front()) styleNames.push_front(style); } - const QVariant singleClickValue = readKdeSetting(QStringLiteral("KDE/SingleClick"), kdeDirs, kdeSettings); + const QVariant singleClickValue = readKdeSetting(QStringLiteral("KDE/SingleClick"), kdeDirs, kdeVersion, kdeSettings); if (singleClickValue.isValid()) singleClick = singleClickValue.toBool(); - const QVariant themeValue = readKdeSetting(QStringLiteral("Icons/Theme"), kdeDirs, kdeSettings); + const QVariant themeValue = readKdeSetting(QStringLiteral("Icons/Theme"), kdeDirs, kdeVersion, kdeSettings); if (themeValue.isValid()) iconThemeName = themeValue.toString(); - const QVariant toolBarIconSizeValue = readKdeSetting(QStringLiteral("ToolbarIcons/Size"), kdeDirs, kdeSettings); + const QVariant toolBarIconSizeValue = readKdeSetting(QStringLiteral("ToolbarIcons/Size"), kdeDirs, kdeVersion, kdeSettings); if (toolBarIconSizeValue.isValid()) toolBarIconSize = toolBarIconSizeValue.toInt(); - const QVariant toolbarStyleValue = readKdeSetting(QStringLiteral("Toolbar style/ToolButtonStyle"), kdeDirs, kdeSettings); + const QVariant toolbarStyleValue = readKdeSetting(QStringLiteral("Toolbar style/ToolButtonStyle"), kdeDirs, kdeVersion, kdeSettings); if (toolbarStyleValue.isValid()) { const QString toolBarStyle = toolbarStyleValue.toString(); if (toolBarStyle == QLatin1String("TextBesideIcon")) @@ -280,17 +283,17 @@ void QKdeThemePrivate::refresh() toolButtonStyle = Qt::ToolButtonTextUnderIcon; } - const QVariant wheelScrollLinesValue = readKdeSetting(QStringLiteral("KDE/WheelScrollLines"), kdeDirs, kdeSettings); + const QVariant wheelScrollLinesValue = readKdeSetting(QStringLiteral("KDE/WheelScrollLines"), kdeDirs, kdeVersion, kdeSettings); if (wheelScrollLinesValue.isValid()) wheelScrollLines = wheelScrollLinesValue.toInt(); // Read system font, ignore 'smallestReadableFont' - if (QFont *systemFont = kdeFont(readKdeSetting(QStringLiteral("font"), kdeDirs, kdeSettings))) + if (QFont *systemFont = kdeFont(readKdeSetting(QStringLiteral("font"), kdeDirs, kdeVersion, kdeSettings))) resources.fonts[QPlatformTheme::SystemFont] = systemFont; else resources.fonts[QPlatformTheme::SystemFont] = new QFont(QLatin1String(defaultSystemFontNameC), defaultSystemFontSize); - if (QFont *fixedFont = kdeFont(readKdeSetting(QStringLiteral("fixed"), kdeDirs, kdeSettings))) { + if (QFont *fixedFont = kdeFont(readKdeSetting(QStringLiteral("fixed"), kdeDirs, kdeVersion, kdeSettings))) { resources.fonts[QPlatformTheme::FixedFont] = fixedFont; } else { fixedFont = new QFont(QLatin1String(defaultSystemFontNameC), defaultSystemFontSize); @@ -301,12 +304,12 @@ void QKdeThemePrivate::refresh() qDeleteAll(kdeSettings); } -QVariant QKdeThemePrivate::readKdeSetting(const QString &key, const QStringList &kdeDirs, QHash &kdeSettings) +QVariant QKdeThemePrivate::readKdeSetting(const QString &key, const QStringList &kdeDirs, int kdeVersion, QHash &kdeSettings) { foreach (const QString &kdeDir, kdeDirs) { QSettings *settings = kdeSettings.value(kdeDir); if (!settings) { - const QString kdeGlobalsPath = kdeGlobals(kdeDir); + const QString kdeGlobalsPath = kdeGlobals(kdeDir, kdeVersion); if (QFileInfo(kdeGlobalsPath).isReadable()) { settings = new QSettings(kdeGlobalsPath, QSettings::IniFormat); kdeSettings.insert(kdeDir, settings); @@ -334,9 +337,9 @@ static inline bool kdeColor(QPalette *pal, QPalette::ColorRole role, const QVari return true; } -void QKdeThemePrivate::readKdeSystemPalette(const QStringList &kdeDirs, QHash &kdeSettings, QPalette *pal) +void QKdeThemePrivate::readKdeSystemPalette(const QStringList &kdeDirs, int kdeVersion, QHash &kdeSettings, QPalette *pal) { - if (!kdeColor(pal, QPalette::Button, readKdeSetting(QStringLiteral("Colors:Button/BackgroundNormal"), kdeDirs, kdeSettings))) { + if (!kdeColor(pal, QPalette::Button, readKdeSetting(QStringLiteral("Colors:Button/BackgroundNormal"), kdeDirs, kdeVersion, kdeSettings))) { // kcolorscheme.cpp: SetDefaultColors const QColor defaultWindowBackground(214, 210, 208); const QColor defaultButtonBackground(223, 220, 217); @@ -344,18 +347,18 @@ void QKdeThemePrivate::readKdeSystemPalette(const QStringList &kdeDirs, QHash 4) + // Plasma 5 follows XDG spec + // but uses the same config file format: + return new QKdeTheme(QStandardPaths::standardLocations(QStandardPaths::GenericConfigLocation), kdeVersion); + // Determine KDE prefixes in the following priority order: // - KDEHOME and KDEDIRS environment variables // - ~/.kde() -- cgit v1.2.3 From df49755d7427a1f67ab0a8944c720d66a820dfeb Mon Sep 17 00:00:00 2001 From: Samuel Nevala Date: Thu, 27 Aug 2015 09:16:09 +0300 Subject: winrt: Add missing Q_DECL_OVERRIDE and fix white space. Change-Id: Ibbcb637dac4d531934786fff25f7b8c36ef5ebed Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrtscreen.cpp | 2 -- src/plugins/platforms/winrt/qwinrtscreen.h | 12 ++++++------ 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 2a7cbaa159..e52f038605 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -419,9 +419,7 @@ public: #endif // Q_OS_WINPHONE QScopedPointer cursor; - QHash touchPoints; - QSizeF logicalSize; QSurfaceFormat surfaceFormat; qreal logicalDpi; diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h index 796e6abb80..4112e49c4d 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.h +++ b/src/plugins/platforms/winrt/qwinrtscreen.h @@ -82,17 +82,17 @@ class QWinRTScreen : public QPlatformScreen public: explicit QWinRTScreen(ABI::Windows::UI::Xaml::IWindow *xamlWindow); ~QWinRTScreen(); - QRect geometry() const; - int depth() const; - QImage::Format format() const; + QRect geometry() const Q_DECL_OVERRIDE; + int depth() const Q_DECL_OVERRIDE; + QImage::Format format() const Q_DECL_OVERRIDE; QSizeF physicalSize() const Q_DECL_OVERRIDE; QDpi logicalDpi() const Q_DECL_OVERRIDE; qreal scaleFactor() const; - QPlatformCursor *cursor() const; + QPlatformCursor *cursor() const Q_DECL_OVERRIDE; Qt::KeyboardModifiers keyboardModifiers() const; - Qt::ScreenOrientation nativeOrientation() const; - Qt::ScreenOrientation orientation() const; + Qt::ScreenOrientation nativeOrientation() const Q_DECL_OVERRIDE; + Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE; QWindow *topWindow() const; void addWindow(QWindow *window); -- cgit v1.2.3 From 9cdbf48c3375feb9bff2e8a4749ec47b9831b15c Mon Sep 17 00:00:00 2001 From: Samuel Nevala Date: Wed, 26 Aug 2015 15:11:39 +0300 Subject: winrt: Fix MessageDialog show on windows phone. Run native dialog show on XAML thread. Change-Id: I6273340e87d70aae21c838d9d7646a233c1f48be Task-Id: QTBUG-47938 Reviewed-by: Andrew Knight --- .../platforms/winrt/qwinrtmessagedialoghelper.cpp | 26 +++++++++++++--------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp index 4fc1fea626..68bf1fdcac 100644 --- a/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp +++ b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp @@ -38,7 +38,9 @@ #include "qwinrttheme.h" #include +#include +#include #include #include #include @@ -168,16 +170,20 @@ bool QWinRTMessageDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModa } } - ComPtr> op; - hr = dialog->ShowAsync(&op); - RETURN_FALSE_IF_FAILED("Failed to show dialog"); - hr = op->put_Completed(Callback(this, &QWinRTMessageDialogHelper::onCompleted).Get()); - RETURN_FALSE_IF_FAILED("Failed to set dialog callback"); - - d->shown = true; - hr = op.As(&d->info); - RETURN_FALSE_IF_FAILED("Failed to acquire AsyncInfo for MessageDialog"); - + hr = QEventDispatcherWinRT::runOnXamlThread([this, d, dialog]() { + HRESULT hr; + ComPtr> op; + hr = dialog->ShowAsync(&op); + RETURN_HR_IF_FAILED("Failed to show dialog"); + hr = op->put_Completed(Callback(this, &QWinRTMessageDialogHelper::onCompleted).Get()); + RETURN_HR_IF_FAILED("Failed to set dialog callback"); + d->shown = true; + hr = op.As(&d->info); + RETURN_HR_IF_FAILED("Failed to acquire AsyncInfo for MessageDialog"); + return hr; + }); + + RETURN_FALSE_IF_FAILED("Failed to show dialog") return true; } -- cgit v1.2.3 From 2117a76136e6e3e48f70d7a444b06c0ee0ff9ec4 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 26 Aug 2015 15:09:50 +0200 Subject: QPlatformFileDialogHelper::cleanFilterList(): Allow for ',' in glob. RCS files (text/plain) have the glob pattern "*,v", which caused the regular expression match to fail. Task-number: QTBUG-47923 Change-Id: I7d8682ef51306cb4da58a2b3880842bd99892ea3 Reviewed-by: David Faure --- src/gui/kernel/qplatformdialoghelper.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/kernel/qplatformdialoghelper.cpp b/src/gui/kernel/qplatformdialoghelper.cpp index 25894fd504..20dc716d89 100644 --- a/src/gui/kernel/qplatformdialoghelper.cpp +++ b/src/gui/kernel/qplatformdialoghelper.cpp @@ -651,12 +651,13 @@ void QPlatformFileDialogHelper::setOptions(const QSharedPointer\\$%&=^~:\\|]*)\\)$"; +"^(.*)\\(([a-zA-Z0-9_.,*? +;#\\-\\[\\]@\\{\\}/!<>\\$%&=^~:\\|]*)\\)$"; // Makes a list of filters from a normal filter string "Image Files (*.png *.jpg)" QStringList QPlatformFileDialogHelper::cleanFilterList(const QString &filter) { QRegExp regexp(QString::fromLatin1(filterRegExp)); + Q_ASSERT(regexp.isValid()); QString f = filter; int i = regexp.indexIn(f); if (i >= 0) -- cgit v1.2.3 From 79a4cb1e4f8ec2f519db0cd4f01522a0d56e31e7 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 26 Aug 2015 12:02:40 +0200 Subject: Fix some qdoc-warnings. qtbase/src/widgets/kernel/qaction.cpp:1257: warning: Can't link to 'QApplication::setAttribute()' qtbase/src/widgets/kernel/qapplication.cpp:519: warning: Can't link to 'arguments()' qtbase/src/widgets/kernel/qapplication.cpp:1939: warning: Can't link to 'quit()' qtbase/src/widgets/kernel/qapplication.cpp:2946: warning: Can't link to 'quit()' qtbase/src/widgets/kernel/qapplication.cpp:2946: warning: Can't link to 'exit()' qtbase/src/widgets/kernel/qapplication.cpp:2946: warning: Can't link to 'processEvents()' qtbase/src/widgets/widgets/qmenu.cpp:1354: warning: Can't link to 'Recent Files Example' qtbase/examples/widgets/doc/src/tetrix.qdoc:28: warning: Can't link to 'QApplication::quit()' qtbase/src/testlib/qtestcase.cpp:268: warning: Undocumented parameter 'timeout' in QTRY_VERIFY2_WITH_TIMEOUT() qtbase/src/corelib/global/qnamespace.qdoc:2427: warning: Can't link to 'QApplication::setLayoutDirection()' qtbase/src/corelib/global/qnamespace.qdoc:751: warning: Can't link to 'QApplication::setDesktopSettingsAware()' Change-Id: Ic8170a40fb1cd84e3fb4dd75d9429f4b485f8bd9 Reviewed-by: Martin Smith --- src/corelib/global/qnamespace.qdoc | 4 ++-- src/testlib/qtestcase.cpp | 2 +- src/widgets/kernel/qaction.cpp | 2 +- src/widgets/kernel/qapplication.cpp | 8 ++++---- src/widgets/widgets/qmenu.cpp | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index a912e65d30..38eb64601d 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -772,7 +772,7 @@ \value UI_FadeTooltip Show tooltip fading effects. \value UI_AnimateToolBox Reserved - \sa QApplication::setEffectEnabled(), QApplication::setDesktopSettingsAware() + \sa QApplication::setEffectEnabled(), QGuiApplication::setDesktopSettingsAware() */ /*! \enum Qt::AspectRatioMode @@ -2443,7 +2443,7 @@ When LayoutDirectionAuto is used in conjunction with text layouting, it will imply that the text directionality is determined from the content of the string to be layouted. - \sa QApplication::setLayoutDirection(), QWidget::setLayoutDirection(), QTextOption::setTextDirection(), QString::isRightToLeft() + \sa QGuiApplication::setLayoutDirection(), QWidget::setLayoutDirection(), QTextOption::setTextDirection(), QString::isRightToLeft() */ /*! diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 1a74bab538..f9ae6138ad 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -272,7 +272,7 @@ static void stackTrace() The QTRY_VERIFY2_WITH_TIMEOUT macro is similar to QTRY_VERIFY_WITH_TIMEOUT() except that it outputs a verbose \a message when \a condition is still false - after the specified timeout. The \a message is a plain C string. + after the specified \a timeout. The \a message is a plain C string. Example: \code diff --git a/src/widgets/kernel/qaction.cpp b/src/widgets/kernel/qaction.cpp index 95c4877eb9..1563d020b6 100644 --- a/src/widgets/kernel/qaction.cpp +++ b/src/widgets/kernel/qaction.cpp @@ -1270,7 +1270,7 @@ QAction::MenuRole QAction::menuRole() const For example: \snippet code/src_gui_kernel_qaction.cpp 0 - \sa QAction::icon, QApplication::setAttribute() + \sa QAction::icon, QCoreApplication::setAttribute() */ void QAction::setIconVisibleInMenu(bool visible) { diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index f82fac836a..eaadcd5e2a 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -558,7 +558,7 @@ void QApplicationPrivate::process_cmdline() and will make the application wait until a debugger connects to it. \endlist - \sa arguments() + \sa QCoreApplication::arguments() */ #ifdef Q_QDOC @@ -1951,7 +1951,7 @@ bool QApplicationPrivate::tryCloseAllWindows() \l quitOnLastWindowClosed to false. \sa quitOnLastWindowClosed, lastWindowClosed(), QWidget::close(), - QWidget::closeEvent(), lastWindowClosed(), quit(), topLevelWidgets(), + QWidget::closeEvent(), lastWindowClosed(), QCoreApplication::quit(), topLevelWidgets(), QWidget::isWindow() */ void QApplication::closeAllWindows() @@ -2969,8 +2969,8 @@ int QApplication::startDragDistance() application will have time to exit its event loop and execute code at the end of the \c{main()} function, after the QApplication::exec() call. - \sa quitOnLastWindowClosed, quit(), exit(), processEvents(), - QCoreApplication::exec() + \sa quitOnLastWindowClosed, QCoreApplication::quit(), QCoreApplication::exit(), + QCoreApplication::processEvents(), QCoreApplication::exec() */ int QApplication::exec() { diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index a7c58ab332..0556c02b64 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -1443,7 +1443,7 @@ void QMenu::initStyleOption(QStyleOptionMenuItem *option, const QAction *action) addSeparator(), and addMenu(). \sa QMenuBar, {fowler}{GUI Design Handbook: Menu, Drop-Down and Pop-Up}, - {Application Example}, {Menus Example}, {Recent Files Example} + {Application Example}, {Menus Example} */ -- cgit v1.2.3 From 3fe645ecc9aaf4522183c39f5c9a78ebc1c90674 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Wed, 19 Aug 2015 15:01:19 +0200 Subject: Optimize set color component in RGBA64 After the removal of direct access through type punning, the direct color setters can be better optimized. Change-Id: Icaa5b1f8c8fe90863dd42fa4dfb5a2998c273465 Reviewed-by: Gunnar Sletta --- src/gui/painting/qrgba64.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/gui/painting/qrgba64.h b/src/gui/painting/qrgba64.h index cca9019959..264ec394cd 100644 --- a/src/gui/painting/qrgba64.h +++ b/src/gui/painting/qrgba64.h @@ -113,10 +113,10 @@ public: Q_DECL_CONSTEXPR quint16 green() const { return rgba >> GreenShift; } Q_DECL_CONSTEXPR quint16 blue() const { return rgba >> BlueShift; } Q_DECL_CONSTEXPR quint16 alpha() const { return rgba >> AlphaShift; } - void setRed(quint16 _red) { *this = fromRgba64(_red, green(), blue(), alpha()); } - void setGreen(quint16 _green) { *this = fromRgba64(red(), _green, blue(), alpha()); } - void setBlue(quint16 _blue) { *this = fromRgba64(red(), green(), _blue, alpha()); } - void setAlpha(quint16 _alpha) { *this = fromRgba64(red(), green(), blue(), _alpha); } + void setRed(quint16 _red) { rgba = (rgba & ~(Q_UINT64_C(0xffff) << RedShift)) | (quint64(_red) << RedShift); } + void setGreen(quint16 _green) { rgba = (rgba & ~(Q_UINT64_C(0xffff) << GreenShift)) | (quint64(_green) << GreenShift); } + void setBlue(quint16 _blue) { rgba = (rgba & ~(Q_UINT64_C(0xffff) << BlueShift)) | (quint64(_blue) << BlueShift); } + void setAlpha(quint16 _alpha) { rgba = (rgba & ~(Q_UINT64_C(0xffff) << AlphaShift)) | (quint64(_alpha) << AlphaShift); } Q_DECL_CONSTEXPR quint8 red8() const { return div_257(red()); } Q_DECL_CONSTEXPR quint8 green8() const { return div_257(green()); } @@ -161,16 +161,16 @@ public: } private: - static Q_DECL_CONSTEXPR quint64 alphaMask() { return quint64(0xffff) << AlphaShift; } + static Q_DECL_CONSTEXPR quint64 alphaMask() { return Q_UINT64_C(0xffff) << AlphaShift; } static Q_DECL_CONSTEXPR uint div_257_floor(uint x) { return (x - (x >> 8)) >> 8; } static Q_DECL_CONSTEXPR uint div_257(uint x) { return div_257_floor(x + 128); } static Q_DECL_CONSTEXPR uint div_65535(uint x) { return (x + (x>>16) + 0x8000U) >> 16; } Q_DECL_RELAXED_CONSTEXPR QRgba64 unpremultiplied_32bit() const { - const quint16 a = alpha(); - if (a == 0xffff || a == 0) + if (isOpaque() || isTransparent()) return *this; + const quint32 a = alpha(); const quint16 r = (quint32(red()) * 0xffff + a/2) / a; const quint16 g = (quint32(green()) * 0xffff + a/2) / a; const quint16 b = (quint32(blue()) * 0xffff + a/2) / a; @@ -178,9 +178,9 @@ private: } Q_DECL_RELAXED_CONSTEXPR QRgba64 unpremultiplied_64bit() const { - const quint16 a = alpha(); - if (a == 0xffff || a == 0) + if (isOpaque() || isTransparent()) return *this; + const quint64 a = alpha(); const quint64 fa = (Q_UINT64_C(0xffff00008000) + a/2) / a; const quint16 r = (red() * fa + 0x80000000) >> 32; const quint16 g = (green() * fa + 0x80000000) >> 32; -- cgit v1.2.3 From ac9643c85ff829583c8be958b5eea4d543070882 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Wed, 29 Apr 2015 12:34:16 +0200 Subject: Make flushWindowSystemEvents return ev. accepted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit flushWindowSystemEvents() now returns whether the most recent event added to the queue was accepted by Qt or not. Use QAtomicInt to store the accepted state in order to avoid a data race on it between the Gui thread and the event poster thread. Change-Id: I6c111fdaecda5c514307ca0749a54075fe8e872f Reviewed-by: Jørgen Lind --- src/gui/kernel/qwindowsysteminterface.cpp | 19 ++++++++++++++++--- src/gui/kernel/qwindowsysteminterface.h | 2 +- src/gui/kernel/qwindowsysteminterface_p.h | 2 ++ 3 files changed, 19 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 88cf2dac93..01f4be6dd0 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -49,6 +49,7 @@ QElapsedTimer QWindowSystemInterfacePrivate::eventTime; bool QWindowSystemInterfacePrivate::synchronousWindowSystemEvents = false; QWaitCondition QWindowSystemInterfacePrivate::eventsFlushed; QMutex QWindowSystemInterfacePrivate::flushEventMutex; +QAtomicInt QWindowSystemInterfacePrivate::eventAccepted; QWindowSystemEventHandler *QWindowSystemInterfacePrivate::eventHandler; //------------------------------------------------------------ @@ -618,17 +619,21 @@ void QWindowSystemInterface::deferredFlushWindowSystemEvents(QEventLoop::Process QWindowSystemInterfacePrivate::eventsFlushed.wakeOne(); } -void QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags) +/*! + Make Qt Gui process all events on the event queue immediately. Return the + accepted state for the last event on the queue. +*/ +bool QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags) { const int count = QWindowSystemInterfacePrivate::windowSystemEventQueue.count(); if (!count) - return; + return false; if (!QGuiApplication::instance()) { qWarning().nospace() << "QWindowSystemInterface::flushWindowSystemEvents() invoked after " "QGuiApplication destruction, discarding " << count << " events."; QWindowSystemInterfacePrivate::windowSystemEventQueue.clear(); - return; + return false; } if (QThread::currentThread() != QGuiApplication::instance()->thread()) { QMutexLocker locker(&QWindowSystemInterfacePrivate::flushEventMutex); @@ -638,6 +643,7 @@ void QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ProcessEventsFl } else { sendWindowSystemEvents(flags); } + return QWindowSystemInterfacePrivate::eventAccepted.load() > 0; } bool QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::ProcessEventsFlags flags) @@ -659,6 +665,13 @@ bool QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::ProcessEventsFla nevents++; QGuiApplicationPrivate::processWindowSystemEvent(event); } + + // Record the accepted state for the processed event + // (excluding flush events). This state can then be + // returned by flushWindowSystemEvents(). + if (event->type != QWindowSystemInterfacePrivate::FlushEvents) + QWindowSystemInterfacePrivate::eventAccepted.store(event->eventAccepted); + delete event; } diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h index ace1a4fe24..3e0b788c0f 100644 --- a/src/gui/kernel/qwindowsysteminterface.h +++ b/src/gui/kernel/qwindowsysteminterface.h @@ -213,7 +213,7 @@ public: // For event dispatcher implementations static bool sendWindowSystemEvents(QEventLoop::ProcessEventsFlags flags); static void setSynchronousWindowSystemEvents(bool enable); - static void flushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents); + static bool flushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents); static void deferredFlushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags); static int windowSystemEventsQueued(); }; diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h index cc0ca6bf81..430800f137 100644 --- a/src/gui/kernel/qwindowsysteminterface_p.h +++ b/src/gui/kernel/qwindowsysteminterface_p.h @@ -51,6 +51,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -488,6 +489,7 @@ public: static QWaitCondition eventsFlushed; static QMutex flushEventMutex; + static QAtomicInt eventAccepted; static QList fromNativeTouchPoints(const QList &points, -- cgit v1.2.3 From ee767c838a0e0a91394a24b21d44d862d3b60416 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Wed, 29 Apr 2015 13:17:31 +0200 Subject: Implement threaded synchronous WS events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make handleWindowSystemEvent() support being called from secondary threads in synchronousWindowSystemEvent mode. This is implemented by posting the event to the Gui event queue (which will wake the Qt Gui thread), and then calling flushWindowSystemEvents which will block the calling thread until the event has been processed. Change-Id: I7e8e68c1e0290c17105563268e316b0f8205b3ce Reviewed-by: Jørgen Lind --- src/gui/kernel/qwindowsysteminterface.cpp | 33 +++++++++++++++++++++++-------- src/gui/kernel/qwindowsysteminterface_p.h | 1 + 2 files changed, 26 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 01f4be6dd0..0a9da737dc 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -442,18 +442,33 @@ void QWindowSystemInterfacePrivate::removeWindowSystemEvent(WindowSystemEvent *e windowSystemEventQueue.remove(event); } +void QWindowSystemInterfacePrivate::postWindowSystemEvent(WindowSystemEvent *ev) +{ + windowSystemEventQueue.append(ev); + QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::qt_qpa_core_dispatcher(); + if (dispatcher) + dispatcher->wakeUp(); +} + bool QWindowSystemInterfacePrivate::handleWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *ev) { bool accepted = true; if (synchronousWindowSystemEvents) { - QGuiApplicationPrivate::processWindowSystemEvent(ev); - accepted = ev->eventAccepted; - delete ev; + if (QThread::currentThread() == QGuiApplication::instance()->thread()) { + // Process the event immediately on the current thread and return the accepted state. + QGuiApplicationPrivate::processWindowSystemEvent(ev); + accepted = ev->eventAccepted; + delete ev; + } else { + // Post the event on the Qt main thread queue and flush the queue. + // This will wake up the Gui thread which will process the event. + // Return the accepted state for the last event on the queue, + // which is the event posted by this function. + postWindowSystemEvent(ev); + accepted = QWindowSystemInterface::flushWindowSystemEvents(); + } } else { - windowSystemEventQueue.append(ev); - QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::qt_qpa_core_dispatcher(); - if (dispatcher) - dispatcher->wakeUp(); + postWindowSystemEvent(ev); } return accepted; } @@ -636,9 +651,11 @@ bool QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ProcessEventsFl return false; } if (QThread::currentThread() != QGuiApplication::instance()->thread()) { + // Post a FlushEvents event which will trigger a call back to + // deferredFlushWindowSystemEvents from the Gui thread. QMutexLocker locker(&QWindowSystemInterfacePrivate::flushEventMutex); QWindowSystemInterfacePrivate::FlushEventsEvent *e = new QWindowSystemInterfacePrivate::FlushEventsEvent(flags); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + QWindowSystemInterfacePrivate::postWindowSystemEvent(e); QWindowSystemInterfacePrivate::eventsFlushed.wait(&QWindowSystemInterfacePrivate::flushEventMutex); } else { sendWindowSystemEvents(flags); diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h index 430800f137..e48d1e965b 100644 --- a/src/gui/kernel/qwindowsysteminterface_p.h +++ b/src/gui/kernel/qwindowsysteminterface_p.h @@ -482,6 +482,7 @@ public: static WindowSystemEvent *getNonUserInputWindowSystemEvent(); static WindowSystemEvent *peekWindowSystemEvent(EventType t); static void removeWindowSystemEvent(WindowSystemEvent *event); + static void postWindowSystemEvent(WindowSystemEvent *ev); static bool handleWindowSystemEvent(WindowSystemEvent *ev); static QElapsedTimer eventTime; -- cgit v1.2.3 From c4015f13f383d8fa418fff5961fc190c7fcbab2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Mon, 27 Apr 2015 22:32:57 +0200 Subject: Document handleWindowSystemEvent() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Document asynchronous and synchronous mode behavior. Change-Id: I2dc1256af5b3a8014025c89c65d41480f18f0701 Reviewed-by: Jørgen Lind --- src/gui/kernel/qwindowsysteminterface.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src') diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 0a9da737dc..3500792f4e 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -450,6 +450,19 @@ void QWindowSystemInterfacePrivate::postWindowSystemEvent(WindowSystemEvent *ev) dispatcher->wakeUp(); } +/*! + Handles a window system event. + + By default this function posts the event on the window system event queue and + wakes the Gui event dispatcher. Qt Gui will then handle the event asynchonously + at a later point. The return value is not used in asynchronous mode and will + always be true. + + In synchronous mode Qt Gui will process the event immediately. The return value + indicates if Qt accepted the event. + + \sa flushWindowSystemEvents(), setSynchronousWindowSystemEvents() +*/ bool QWindowSystemInterfacePrivate::handleWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *ev) { bool accepted = true; -- cgit v1.2.3 From 9ff74f14876dea3a21c1dab389577c54e3bf1bc5 Mon Sep 17 00:00:00 2001 From: Samuel Nevala Date: Wed, 26 Aug 2015 10:26:31 +0300 Subject: winrt: Work around broken screen rotation on Windows Phone 8.1. Expose on orientation change clears bad frames caused by race between Qt and ANGLE. Change-Id: I8970c6be36133d861c718a946d9e9b7a5e88cc2c Task-Id: QTBUG-44333 Reviewed-by: Andrew Knight --- src/plugins/platforms/winrt/qwinrtscreen.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index e52f038605..6c40d5a1d2 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -1048,6 +1048,7 @@ HRESULT QWinRTScreen::onOrientationChanged(IDisplayInformation *, IInspectable * if (d->orientation != newOrientation) { d->orientation = newOrientation; QWindowSystemInterface::handleScreenOrientationChange(screen(), d->orientation); + handleExpose(); // Clean broken frames caused by race between Qt and ANGLE } return S_OK; } -- cgit v1.2.3 From 8c1fcbcd83214d7cc7efc63c12f907538664821e Mon Sep 17 00:00:00 2001 From: Samuel Nevala Date: Wed, 26 Aug 2015 15:30:36 +0300 Subject: Declare StandardButton & ButtonRole types for cross-thread use. On windows phone native dialog interaction is handled from XMAL thread. Declare and register dialog helpers StandardButton and ButtonRole for cross-thread usage. Change-Id: Ic1842a5af8a1122fdffb766b4f723d272bdbcac2 Task-Id: QTBUG-47941 Reviewed-by: Andrew Knight --- src/gui/kernel/qplatformdialoghelper.cpp | 2 ++ src/gui/kernel/qplatformdialoghelper.h | 5 +++++ 2 files changed, 7 insertions(+) (limited to 'src') diff --git a/src/gui/kernel/qplatformdialoghelper.cpp b/src/gui/kernel/qplatformdialoghelper.cpp index 20dc716d89..f69efe0935 100644 --- a/src/gui/kernel/qplatformdialoghelper.cpp +++ b/src/gui/kernel/qplatformdialoghelper.cpp @@ -119,6 +119,8 @@ static const int buttonRoleLayouts[2][5][14] = QPlatformDialogHelper::QPlatformDialogHelper() { + qRegisterMetaType(); + qRegisterMetaType(); } QPlatformDialogHelper::~QPlatformDialogHelper() diff --git a/src/gui/kernel/qplatformdialoghelper.h b/src/gui/kernel/qplatformdialoghelper.h index ec88770862..936dbdfa89 100644 --- a/src/gui/kernel/qplatformdialoghelper.h +++ b/src/gui/kernel/qplatformdialoghelper.h @@ -160,6 +160,11 @@ Q_SIGNALS: void reject(); }; +QT_END_NAMESPACE +Q_DECLARE_METATYPE(QPlatformDialogHelper::StandardButton) +Q_DECLARE_METATYPE(QPlatformDialogHelper::ButtonRole) +QT_BEGIN_NAMESPACE + class Q_GUI_EXPORT QColorDialogOptions { public: -- cgit v1.2.3 From fb60f225e67db6c548fc2c5dfbe172251993daba Mon Sep 17 00:00:00 2001 From: Samuel Nevala Date: Thu, 27 Aug 2015 09:17:05 +0300 Subject: winrt: Enable window visibility for the root window. - Minimized and Hidden: hide the status bar and collapse winrt native ui element. - Windowed and Maximized: show the status bar and re-size the window. - FullScreen and AutomaticVisibility: hide the status bar and re-size the window. Showing & hiding the status bar and re-sizing the window affect only the windows phone build. Change-Id: Iaa412382bffc14e470720f2213bb3f6851f57a6b Task-Id: QTBUG-47811 Reviewed-by: Andrew Knight --- src/plugins/platforms/winrt/qwinrtscreen.cpp | 114 ++++++++++++++++++++++----- src/plugins/platforms/winrt/qwinrtscreen.h | 15 ++++ src/plugins/platforms/winrt/qwinrtwindow.cpp | 79 +++++++++++++++---- src/plugins/platforms/winrt/qwinrtwindow.h | 1 + 4 files changed, 174 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 6c40d5a1d2..563753cfcb 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -83,6 +83,9 @@ typedef ITypedEventHandler PointerHandler; typedef ITypedEventHandler SizeChangedHandler; typedef ITypedEventHandler VisibilityChangedHandler; typedef ITypedEventHandler DisplayInformationHandler; +#ifdef Q_OS_WINPHONE +typedef ITypedEventHandler StatusBarHandler; +#endif QT_BEGIN_NAMESPACE @@ -405,6 +408,10 @@ typedef HRESULT (__stdcall ICoreWindow::*CoreWindowCallbackRemover)(EventRegistr uint qHash(CoreWindowCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); } typedef HRESULT (__stdcall IDisplayInformation::*DisplayCallbackRemover)(EventRegistrationToken); uint qHash(DisplayCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); } +#ifdef Q_OS_WINPHONE +typedef HRESULT (__stdcall IStatusBar::*StatusBarCallbackRemover)(EventRegistrationToken); +uint qHash(StatusBarCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); } +#endif class QWinRTScreenPrivate { @@ -416,7 +423,7 @@ public: ComPtr displayInformation; #ifdef Q_OS_WINPHONE ComPtr statusBar; -#endif // Q_OS_WINPHONE +#endif QScopedPointer cursor; QHash touchPoints; @@ -434,6 +441,9 @@ public: QHash windowTokens; QHash displayTokens; +#ifdef Q_OS_WINPHONE + QHash statusBarTokens; +#endif }; // To be called from the XAML thread @@ -473,8 +483,10 @@ QWinRTScreen::QWinRTScreen(Xaml::IWindow *xamlWindow) Q_ASSERT_SUCCEEDED(hr); hr = d->coreWindow->add_PointerWheelChanged(Callback(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerWheelChanged]); Q_ASSERT_SUCCEEDED(hr); +#ifndef Q_OS_WINPHONE hr = d->coreWindow->add_SizeChanged(Callback(this, &QWinRTScreen::onSizeChanged).Get(), &d->windowTokens[&ICoreWindow::remove_SizeChanged]); Q_ASSERT_SUCCEEDED(hr); +#endif hr = d->coreWindow->add_Activated(Callback(this, &QWinRTScreen::onActivated).Get(), &d->windowTokens[&ICoreWindow::remove_Activated]); Q_ASSERT_SUCCEEDED(hr); hr = d->coreWindow->add_Closed(Callback(this, &QWinRTScreen::onClosed).Get(), &d->windowTokens[&ICoreWindow::remove_Closed]); @@ -544,6 +556,10 @@ QWinRTScreen::QWinRTScreen(Xaml::IWindow *xamlWindow) Q_ASSERT_SUCCEEDED(hr); hr = statusBarStatics->GetForCurrentView(&d->statusBar); Q_ASSERT_SUCCEEDED(hr); + hr = d->statusBar->add_Showing(Callback(this, &QWinRTScreen::onStatusBarShowing).Get(), &d->statusBarTokens[&IStatusBar::remove_Showing]); + Q_ASSERT_SUCCEEDED(hr); + hr = d->statusBar->add_Hiding(Callback(this, &QWinRTScreen::onStatusBarHiding).Get(), &d->statusBarTokens[&IStatusBar::remove_Hiding]); + Q_ASSERT_SUCCEEDED(hr); #endif // Q_OS_WINPHONE } @@ -563,6 +579,12 @@ QWinRTScreen::~QWinRTScreen() hr = (d->displayInformation.Get()->*i.key())(i.value()); Q_ASSERT_SUCCEEDED(hr); } +#ifdef Q_OS_WINPHONE + for (QHash::const_iterator i = d->statusBarTokens.begin(); i != d->statusBarTokens.end(); ++i) { + hr = (d->statusBar.Get()->*i.key())(i.value()); + Q_ASSERT_SUCCEEDED(hr); + } +#endif //Q_OS_WINPHONE return hr; }); RETURN_VOID_IF_FAILED("Failed to unregister screen event callbacks"); @@ -574,6 +596,31 @@ QRect QWinRTScreen::geometry() const return QRect(QPoint(), (d->logicalSize * d->scaleFactor).toSize()); } +#ifdef Q_OS_WINPHONE +QRect QWinRTScreen::availableGeometry() const +{ + Q_D(const QWinRTScreen); + QRect statusBar; + QEventDispatcherWinRT::runOnXamlThread([d, &statusBar]() { + HRESULT hr; + Rect rect; + hr = d->statusBar->get_OccludedRect(&rect); + Q_ASSERT_SUCCEEDED(hr); + statusBar.setRect(qRound(rect.X * d->scaleFactor), + qRound(rect.Y * d->scaleFactor), + qRound(rect.Width * d->scaleFactor), + qRound(rect.Height * d->scaleFactor)); + return S_OK; + }); + + return geometry().adjusted( + d->orientation == Qt::LandscapeOrientation ? statusBar.width() : 0, + d->orientation == Qt::PortraitOrientation ? statusBar.height() : 0, + d->orientation == Qt::InvertedLandscapeOrientation ? -statusBar.width() : 0, + 0); +} +#endif //Q_OS_WINPHONE + int QWinRTScreen::depth() const { return 32; @@ -659,6 +706,26 @@ Xaml::IDependencyObject *QWinRTScreen::canvas() const return d->canvas.Get(); } +#ifdef Q_OS_WINPHONE +void QWinRTScreen::setStatusBarVisibility(bool visible, QWindow *window) +{ + Q_D(QWinRTScreen); + if (!window || (window->flags() & Qt::WindowType_Mask) != Qt::Window) + return; + + QEventDispatcherWinRT::runOnXamlThread([d, visible]() { + HRESULT hr; + ComPtr op; + if (visible) + hr = d->statusBar->ShowAsync(&op); + else + hr = d->statusBar->HideAsync(&op); + Q_ASSERT_SUCCEEDED(hr); + return S_OK; + }); +} +#endif //Q_OS_WINPHONE + QWindow *QWinRTScreen::topWindow() const { Q_D(const QWinRTScreen); @@ -672,16 +739,9 @@ void QWinRTScreen::addWindow(QWindow *window) return; #ifdef Q_OS_WINPHONE - if (d->statusBar && (window->flags() & Qt::WindowType_Mask) == Qt::Window) { - QEventDispatcherWinRT::runOnXamlThread([this, d]() { - HRESULT hr; - ComPtr op; - hr = d->statusBar->HideAsync(&op); - Q_ASSERT_SUCCEEDED(hr); - return S_OK; - }); - } -#endif // Q_OS_WINPHONE + if (window->visibility() != QWindow::Maximized && window->visibility() != QWindow::Windowed) + setStatusBarVisibility(false, window); +#endif d->visibleWindows.prepend(window); QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason); @@ -691,6 +751,12 @@ void QWinRTScreen::addWindow(QWindow *window) void QWinRTScreen::removeWindow(QWindow *window) { Q_D(QWinRTScreen); + +#ifdef Q_OS_WINPHONE + if (window->visibility() == QWindow::Minimized) + setStatusBarVisibility(false, window); +#endif + const bool wasTopWindow = window == topWindow(); if (!d->visibleWindows.removeAll(window)) return; @@ -987,13 +1053,8 @@ HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs * HRESULT hr; hr = d->coreWindow->get_Bounds(&size); RETURN_OK_IF_FAILED("Failed to get window bounds"); - QSizeF logicalSize = QSizeF(size.Width, size.Height); - if (d->logicalSize == logicalSize) - return S_OK; - - d->logicalSize = logicalSize; - const QRect newGeometry = geometry(); - QWindowSystemInterface::handleScreenGeometryChange(screen(), newGeometry, newGeometry); + d->logicalSize = QSizeF(size.Width, size.Height); + QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), availableGeometry()); QPlatformScreen::resizeMaximizedWindows(); handleExpose(); return S_OK; @@ -1047,6 +1108,9 @@ HRESULT QWinRTScreen::onOrientationChanged(IDisplayInformation *, IInspectable * Qt::ScreenOrientation newOrientation = static_cast(static_cast(qtOrientationsFromNative(displayOrientation))); if (d->orientation != newOrientation) { d->orientation = newOrientation; +#ifdef Q_OS_WINPHONE + onSizeChanged(nullptr, nullptr); +#endif QWindowSystemInterface::handleScreenOrientationChange(screen(), d->orientation); handleExpose(); // Clean broken frames caused by race between Qt and ANGLE } @@ -1086,4 +1150,18 @@ HRESULT QWinRTScreen::onDpiChanged(IDisplayInformation *, IInspectable *) return S_OK; } +#ifdef Q_OS_WINPHONE +HRESULT QWinRTScreen::onStatusBarShowing(IStatusBar *, IInspectable *) +{ + onSizeChanged(nullptr, nullptr); + return S_OK; +} + +HRESULT QWinRTScreen::onStatusBarHiding(IStatusBar *, IInspectable *) +{ + onSizeChanged(nullptr, nullptr); + return S_OK; +} +#endif //Q_OS_WINPHONE + QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h index 4112e49c4d..3297617740 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.h +++ b/src/plugins/platforms/winrt/qwinrtscreen.h @@ -61,6 +61,9 @@ namespace ABI { struct IDependencyObject; struct IWindow; } + namespace ViewManagement { + struct IStatusBar; + } } namespace Graphics { namespace Display { @@ -83,6 +86,9 @@ public: explicit QWinRTScreen(ABI::Windows::UI::Xaml::IWindow *xamlWindow); ~QWinRTScreen(); QRect geometry() const Q_DECL_OVERRIDE; +#ifdef Q_OS_WINPHONE + QRect availableGeometry() const Q_DECL_OVERRIDE; +#endif int depth() const Q_DECL_OVERRIDE; QImage::Format format() const Q_DECL_OVERRIDE; QSizeF physicalSize() const Q_DECL_OVERRIDE; @@ -105,6 +111,10 @@ public: ABI::Windows::UI::Core::ICoreWindow *coreWindow() const; ABI::Windows::UI::Xaml::IDependencyObject *canvas() const; +#ifdef Q_OS_WINPHONE + void setStatusBarVisibility(bool visible, QWindow *window); +#endif + private: void handleExpose(); @@ -124,6 +134,11 @@ private: HRESULT onOrientationChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *); HRESULT onDpiChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *); +#ifdef Q_OS_WINPHONE + HRESULT onStatusBarShowing(ABI::Windows::UI::ViewManagement::IStatusBar *, IInspectable *); + HRESULT onStatusBarHiding(ABI::Windows::UI::ViewManagement::IStatusBar *, IInspectable *); +#endif + QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QWinRTScreen) }; diff --git a/src/plugins/platforms/winrt/qwinrtwindow.cpp b/src/plugins/platforms/winrt/qwinrtwindow.cpp index 634d62ef24..23e4e163e4 100644 --- a/src/plugins/platforms/winrt/qwinrtwindow.cpp +++ b/src/plugins/platforms/winrt/qwinrtwindow.cpp @@ -64,9 +64,22 @@ using namespace Microsoft::WRL::Wrappers; using namespace ABI::Windows::Foundation; using namespace ABI::Windows::Foundation::Collections; using namespace ABI::Windows::UI; +using namespace ABI::Windows::UI::Xaml; +using namespace ABI::Windows::UI::Xaml::Controls; QT_BEGIN_NAMESPACE +static void setUIElementVisibility(IUIElement *uiElement, bool visibility) +{ + Q_ASSERT(uiElement); + QEventDispatcherWinRT::runOnXamlThread([uiElement, visibility]() { + HRESULT hr; + hr = uiElement->put_Visibility(visibility ? Visibility_Visible : Visibility_Collapsed); + Q_ASSERT_SUCCEEDED(hr); + return S_OK; + }); +} + class QWinRTWindowPrivate { public: @@ -74,8 +87,11 @@ public: QSurfaceFormat surfaceFormat; QString windowTitle; + Qt::WindowState state; - ComPtr swapChainPanel; + ComPtr swapChainPanel; + ComPtr canvas; + ComPtr uiElement; }; QWinRTWindow::QWinRTWindow(QWindow *window) @@ -101,24 +117,26 @@ QWinRTWindow::QWinRTWindow(QWindow *window) d->surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer); HRESULT hr; + hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Controls_Canvas).Get(), + IID_PPV_ARGS(&d->canvas)); + Q_ASSERT_SUCCEEDED(hr); hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() { // Create a new swapchain and place it inside the canvas HRESULT hr; hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Controls_SwapChainPanel).Get(), &d->swapChainPanel); Q_ASSERT_SUCCEEDED(hr); - ComPtr uiElement; - hr = d->swapChainPanel.As(&uiElement); + hr = d->swapChainPanel.As(&d->uiElement); Q_ASSERT_SUCCEEDED(hr); - ComPtr canvas = d->screen->canvas(); - ComPtr panel; + ComPtr canvas = d->screen->canvas(); + ComPtr panel; hr = canvas.As(&panel); Q_ASSERT_SUCCEEDED(hr); - ComPtr> children; + ComPtr> children; hr = panel->get_Children(&children); Q_ASSERT_SUCCEEDED(hr); - hr = children->Append(uiElement.Get()); + hr = children->Append(d->uiElement.Get()); Q_ASSERT_SUCCEEDED(hr); return S_OK; }); @@ -134,20 +152,18 @@ QWinRTWindow::~QWinRTWindow() HRESULT hr; hr = QEventDispatcherWinRT::runOnXamlThread([d]() { HRESULT hr; - ComPtr canvas = d->screen->canvas(); - ComPtr panel; + ComPtr canvas = d->screen->canvas(); + ComPtr panel; hr = canvas.As(&panel); Q_ASSERT_SUCCEEDED(hr); - ComPtr> children; + ComPtr> children; hr = panel->get_Children(&children); Q_ASSERT_SUCCEEDED(hr); - ComPtr uiElement; - hr = d->swapChainPanel.As(&uiElement); Q_ASSERT_SUCCEEDED(hr); quint32 index; boolean found; - hr = children->IndexOf(uiElement.Get(), &index, &found); + hr = children->IndexOf(d->uiElement.Get(), &index, &found); Q_ASSERT_SUCCEEDED(hr); if (found) { hr = children->RemoveAt(index); @@ -181,7 +197,8 @@ void QWinRTWindow::setGeometry(const QRect &rect) Q_D(QWinRTWindow); if (window()->isTopLevel()) { - QPlatformWindow::setGeometry(d->screen->geometry()); + QPlatformWindow::setGeometry(window()->flags() & Qt::MaximizeUsingFullscreenGeometryHint + ? d->screen->geometry() : d->screen->availableGeometry()); QWindowSystemInterface::handleGeometryChange(window(), geometry()); } else { QPlatformWindow::setGeometry(rect); @@ -191,10 +208,16 @@ void QWinRTWindow::setGeometry(const QRect &rect) HRESULT hr; hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() { HRESULT hr; + const QRect windowGeometry = geometry(); + const QPointF topLeft= QPointF(windowGeometry.topLeft()) / d->screen->scaleFactor(); + hr = d->canvas->SetTop(d->uiElement.Get(), topLeft.y()); + Q_ASSERT_SUCCEEDED(hr); + hr = d->canvas->SetLeft(d->uiElement.Get(), topLeft.x()); + Q_ASSERT_SUCCEEDED(hr); ComPtr frameworkElement; hr = d->swapChainPanel.As(&frameworkElement); Q_ASSERT_SUCCEEDED(hr); - const QSizeF size = QSizeF(geometry().size()) / d->screen->scaleFactor(); + const QSizeF size = QSizeF(windowGeometry.size()) / d->screen->scaleFactor(); hr = frameworkElement->put_Width(size.width()); Q_ASSERT_SUCCEEDED(hr); hr = frameworkElement->put_Height(size.height()); @@ -209,10 +232,13 @@ void QWinRTWindow::setVisible(bool visible) Q_D(QWinRTWindow); if (!window()->isTopLevel()) return; - if (visible) + if (visible) { d->screen->addWindow(window()); - else + setUIElementVisibility(d->uiElement.Get(), d->state != Qt::WindowMinimized); + } else { d->screen->removeWindow(window()); + setUIElementVisibility(d->uiElement.Get(), false); + } } void QWinRTWindow::setWindowTitle(const QString &title) @@ -249,4 +275,23 @@ qreal QWinRTWindow::devicePixelRatio() const return screen()->devicePixelRatio(); } +void QWinRTWindow::setWindowState(Qt::WindowState state) +{ + Q_D(QWinRTWindow); + if (d->state == state) + return; + +#ifdef Q_OS_WINPHONE + d->screen->setStatusBarVisibility(state == Qt::WindowMaximized || state == Qt::WindowNoState, window()); +#endif + + if (state == Qt::WindowMinimized) + setUIElementVisibility(d->uiElement.Get(), false); + + if (d->state == Qt::WindowMinimized) + setUIElementVisibility(d->uiElement.Get(), true); + + d->state = state; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtwindow.h b/src/plugins/platforms/winrt/qwinrtwindow.h index 88c149b080..2957a7498b 100644 --- a/src/plugins/platforms/winrt/qwinrtwindow.h +++ b/src/plugins/platforms/winrt/qwinrtwindow.h @@ -61,6 +61,7 @@ public: WId winId() const Q_DECL_OVERRIDE; qreal devicePixelRatio() const Q_DECL_OVERRIDE; + void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE; private: QScopedPointer d_ptr; -- cgit v1.2.3 From 29af8741b68db1dff82de9f12d818524cb6d9147 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 19 Aug 2015 12:29:41 +0200 Subject: Windows: Improve debug output of mime conversion handling. Introduce convenience function for obtaining the format name and use that. Add debug operator for struct FORMATETC including format name. Replace all code enclosed in #ifdef QMIME_DEBUG by qCDebug(). Task-number: QTBUG-47656 Change-Id: Ibb3c860c57edee4a31e8f5f37e3245feebed52a1 Reviewed-by: Joerg Bornemann --- .../platforms/windows/qwindowsclipboard.cpp | 5 +- src/plugins/platforms/windows/qwindowsmime.cpp | 105 +++++++++++++++++---- src/plugins/platforms/windows/qwindowsmime.h | 8 ++ src/plugins/platforms/windows/qwindowsole.cpp | 17 +--- 4 files changed, 101 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowsclipboard.cpp b/src/plugins/platforms/windows/qwindowsclipboard.cpp index 925427ac30..97459a4d97 100644 --- a/src/plugins/platforms/windows/qwindowsclipboard.cpp +++ b/src/plugins/platforms/windows/qwindowsclipboard.cpp @@ -109,8 +109,11 @@ static QDebug operator<<(QDebug d, const QMimeData *mimeData) IDataObject *QWindowsClipboardRetrievalMimeData::retrieveDataObject() const { IDataObject * pDataObj = 0; - if (OleGetClipboard(&pDataObj) == S_OK) + if (OleGetClipboard(&pDataObj) == S_OK) { + if (QWindowsContext::verbose > 1) + qCDebug(lcQpaMime) << __FUNCTION__ << pDataObj; return pDataObj; + } return 0; } diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp index 622352e987..375a7f11db 100644 --- a/src/plugins/platforms/windows/qwindowsmime.cpp +++ b/src/plugins/platforms/windows/qwindowsmime.cpp @@ -299,8 +299,6 @@ static bool qt_read_dibv5(QDataStream &s, QImage &image) return true; } -//#define QMIME_DEBUG - // helpers for using global memory static int getCf(const FORMATETC &formatetc) @@ -380,6 +378,73 @@ static bool canGetData(int cf, IDataObject * pDataObj) return true; } +#ifndef QT_NO_DEBUG_OUTPUT +QDebug operator<<(QDebug d, const FORMATETC &tc) +{ + QDebugStateSaver saver(d); + d.nospace(); + d << "FORMATETC(cfFormat=" << tc.cfFormat << ' '; + switch (tc.cfFormat) { + case CF_TEXT: + d << "CF_TEXT"; + break; + case CF_BITMAP: + d << "CF_BITMAP"; + break; + case CF_TIFF: + d << "CF_TIFF"; + break; + case CF_OEMTEXT: + d << "CF_OEMTEXT"; + break; + case CF_DIB: + d << "CF_DIB"; + break; + case CF_DIBV5: + d << "CF_DIBV5"; + break; + case CF_UNICODETEXT: + d << "CF_UNICODETEXT"; + break; +#ifndef Q_OS_WINCE + case CF_ENHMETAFILE: + d << "CF_ENHMETAFILE"; + break; +#endif // !Q_OS_WINCE + default: + d << QWindowsMimeConverter::clipboardFormatName(tc.cfFormat); + break; + } + d << ", dwAspect=" << tc.dwAspect << ", lindex=" << tc.lindex + << ", tymed=" << tc.tymed << ", ptd=" << tc.ptd << ')'; + return d; +} + +QDebug operator<<(QDebug d, IDataObject *dataObj) +{ + QDebugStateSaver saver(d); + d.nospace(); + d.noquote(); + d << "IDataObject("; + if (dataObj) { // Output formats contained in IDataObject. + IEnumFORMATETC *enumFormatEtc; + if (SUCCEEDED(dataObj->EnumFormatEtc(DATADIR_GET, &enumFormatEtc)) && enumFormatEtc) { + FORMATETC formatEtc[1]; + ULONG fetched; + if (SUCCEEDED(enumFormatEtc->Reset())) { + while (SUCCEEDED(enumFormatEtc->Next(1, formatEtc, &fetched)) && fetched) + d << formatEtc[0] << ','; + enumFormatEtc->Release(); + } + } + } else { + d << '0'; + } + d << ')'; + return d; +} +#endif // !QT_NO_DEBUG_OUTPUT + /*! \class QWindowsMime \brief The QWindowsMime class maps open-standard MIME to Window Clipboard formats. @@ -894,11 +959,7 @@ QVariant QWindowsMimeHtml::convertToMime(const QString &mime, IDataObject *pData QVariant result; if (canConvertToMime(mime, pDataObj)) { QByteArray html = getData(CF_HTML, pDataObj); -#ifdef QMIME_DEBUG - qDebug("QWindowsMimeHtml::convertToMime"); - qDebug("raw :"); - qDebug(html); -#endif + qCDebug(lcQpaMime) << __FUNCTION__ << "raw:" << html; int start = html.indexOf("StartHTML:"); int end = html.indexOf("EndHTML:"); @@ -996,6 +1057,8 @@ QVector QWindowsMimeImage::formatsForMime(const QString &mimeType, co formatetcs += setCf(CF_DIBV5); formatetcs += setCf(CF_DIB); } + if (!formatetcs.isEmpty()) + qCDebug(lcQpaMime) << __FUNCTION__ << mimeType << formatetcs; return formatetcs; } @@ -1216,9 +1279,7 @@ QVariant QBuiltInMimes::convertToMime(const QString &mimeType, IDataObject *pDat if (canConvertToMime(mimeType, pDataObj)) { QByteArray data = getData(inFormats.key(mimeType), pDataObj); if (!data.isEmpty()) { -#ifdef QMIME_DEBUG - qDebug("QBuiltInMimes::convertToMime()"); -#endif + qCDebug(lcQpaMime) << __FUNCTION__; if (mimeType == QLatin1String("text/html") && preferredType == QVariant::String) { // text/html is in wide chars on windows (compatible with Mozilla) val = QString::fromWCharArray((const wchar_t *)data.data()); @@ -1326,6 +1387,8 @@ QVector QLastResortMimes::formatsForMime(const QString &mimeType, con that->formats.insert(cf, mimeType); formatetcs += setCf(cf); } + if (!formatetcs.isEmpty()) + qCDebug(lcQpaMime) << __FUNCTION__ << mimeType << formatetcs; return formatetcs; } static const char x_qt_windows_mime[] = "application/x-qt-windows-mime;value=\""; @@ -1400,11 +1463,8 @@ QString QLastResortMimes::mimeForFormat(const FORMATETC &formatetc) const if (!format.isEmpty()) return format; - wchar_t buffer[256]; - int len = GetClipboardFormatName(getCf(formatetc), buffer, 256); - - if (len) { - QString clipFormat = QString::fromWCharArray(buffer, len); + const QString clipFormat = QWindowsMimeConverter::clipboardFormatName(getCf(formatetc)); + if (!clipFormat.isEmpty()) { #ifndef QT_NO_DRAGANDDROP if (QInternalMimeData::canReadData(clipFormat)) format = clipFormat; @@ -1470,15 +1530,12 @@ QStringList QWindowsMimeConverter::allMimesForFormats(IDataObject *pDataObj) con if (hr == NOERROR) { FORMATETC fmtetc; while (S_OK == fmtenum->Next(1, &fmtetc, 0)) { -#if defined(QMIME_DEBUG) - wchar_t buf[256] = {0}; - GetClipboardFormatName(fmtetc.cfFormat, buf, 255); - qDebug("CF = %d : %s", fmtetc.cfFormat, qPrintable(QString::fromWCharArray(buf))); -#endif for (int i= m_mimes.size() - 1; i >= 0; --i) { QString format = m_mimes.at(i)->mimeForFormat(fmtetc); if (!format.isEmpty() && !formats.contains(format)) { formats += format; + if (QWindowsContext::verbose > 1 && lcQpaMime().isDebugEnabled()) + qCDebug(lcQpaMime) << __FUNCTION__ << fmtetc << format; } } // as documented in MSDN to avoid possible memleak @@ -1494,6 +1551,7 @@ QStringList QWindowsMimeConverter::allMimesForFormats(IDataObject *pDataObj) con QWindowsMime * QWindowsMimeConverter::converterFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const { ensureInitialized(); + qCDebug(lcQpaMime) << __FUNCTION__ << formatetc; for (int i = m_mimes.size()-1; i >= 0; --i) { if (m_mimes.at(i)->canConvertFromMime(formatetc, mimeData)) return m_mimes.at(i); @@ -1528,6 +1586,13 @@ void QWindowsMimeConverter::ensureInitialized() const } } +QString QWindowsMimeConverter::clipboardFormatName(int cf) +{ + wchar_t buf[256] = {0}; + return GetClipboardFormatName(cf, buf, 255) + ? QString::fromWCharArray(buf) : QString(); +} + QVariant QWindowsMimeConverter::convertToMime(const QStringList &mimeTypes, IDataObject *pDataObj, QVariant::Type preferredType, diff --git a/src/plugins/platforms/windows/qwindowsmime.h b/src/plugins/platforms/windows/qwindowsmime.h index 952410e14b..17fddef1bc 100644 --- a/src/plugins/platforms/windows/qwindowsmime.h +++ b/src/plugins/platforms/windows/qwindowsmime.h @@ -42,6 +42,7 @@ QT_BEGIN_NAMESPACE +class QDebug; class QMimeData; class QWindowsMime @@ -83,6 +84,8 @@ public: void registerMime(QWindowsMime *mime); void unregisterMime(QWindowsMime *mime) { m_mimes.removeOne(mime); } + static QString clipboardFormatName(int cf); + private: void ensureInitialized() const; @@ -90,6 +93,11 @@ private: mutable int m_internalMimeCount; }; +#ifndef QT_NO_DEBUG_OUTPUT +QDebug operator<<(QDebug, const FORMATETC &); +QDebug operator<<(QDebug d, IDataObject *); +#endif + QT_END_NAMESPACE #endif // QWINDOWSMIME_H diff --git a/src/plugins/platforms/windows/qwindowsole.cpp b/src/plugins/platforms/windows/qwindowsole.cpp index 6f5a521af8..e480c1ebcf 100644 --- a/src/plugins/platforms/windows/qwindowsole.cpp +++ b/src/plugins/platforms/windows/qwindowsole.cpp @@ -132,12 +132,6 @@ QWindowsOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium) { HRESULT hr = ResultFromScode(DATA_E_FORMATETC); - if (QWindowsContext::verbose > 1 && lcQpaMime().isDebugEnabled()) { - wchar_t buf[256] = {0}; - GetClipboardFormatName(pformatetc->cfFormat, buf, 255); - qCDebug(lcQpaMime) <<__FUNCTION__ << "CF = " << pformatetc->cfFormat << QString::fromWCharArray(buf); - } - if (data) { const QWindowsMimeConverter &mc = QWindowsContext::instance()->mimeConverter(); if (QWindowsMime *converter = mc.converterFromMime(*pformatetc, data)) @@ -145,11 +139,8 @@ QWindowsOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium) hr = ResultFromScode(S_OK); } - if (QWindowsContext::verbose > 1) { - wchar_t buf[256] = {0}; - GetClipboardFormatName(pformatetc->cfFormat, buf, 255); - qCDebug(lcQpaMime) <<__FUNCTION__ << "CF = " << pformatetc->cfFormat << " returns 0x" << int(hr) << dec; - } + if (QWindowsContext::verbose > 1 && lcQpaMime().isDebugEnabled()) + qCDebug(lcQpaMime) <<__FUNCTION__ << *pformatetc << "returns" << hex << showbase << quint64(hr); return hr; } @@ -211,7 +202,7 @@ STDMETHODIMP QWindowsOleDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC FAR* ppenumFormatEtc) { if (QWindowsContext::verbose > 1) - qCDebug(lcQpaMime) << __FUNCTION__; + qCDebug(lcQpaMime) << __FUNCTION__ << "dwDirection=" << dwDirection; if (!data) return ResultFromScode(DATA_E_FORMATETC); @@ -274,7 +265,7 @@ QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QVector &fmtetcs) m_dwRefs(1), m_nIndex(0), m_isNull(false) { if (QWindowsContext::verbose > 1) - qCDebug(lcQpaMime) << __FUNCTION__; + qCDebug(lcQpaMime) << __FUNCTION__ << fmtetcs; m_lpfmtetcs.reserve(fmtetcs.count()); for (int idx = 0; idx < fmtetcs.count(); ++idx) { LPFORMATETC destetc = new FORMATETC(); -- cgit v1.2.3 From 1b459a8124b77fdef12e05d8a77b471be9097776 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Fri, 10 Jul 2015 15:03:43 +0200 Subject: QAbstractSocket: Always set errorString right after socketError Otherwise errorString() might not match error() in a statusChanged handler. Change-Id: If1250b4552412eabe88457dee031e4ef3f533838 Reviewed-by: Alex Trotsenko Reviewed-by: Oswald Buddenhagen Reviewed-by: Thiago Macieira --- src/network/socket/qabstractsocket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 009bc90bf5..d1b13c1191 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -2086,10 +2086,10 @@ bool QAbstractSocket::waitForConnected(int msecs) if ((timedOut && state() != ConnectedState) || state() == ConnectingState) { d->socketError = SocketTimeoutError; + setErrorString(tr("Socket operation timed out")); d->state = UnconnectedState; emit stateChanged(d->state); d->resetSocketLayer(); - setErrorString(tr("Socket operation timed out")); } #if defined (QABSTRACTSOCKET_DEBUG) -- cgit v1.2.3 From ba94e26b8b233456b004084892464ec55b20800c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Thu, 20 Aug 2015 15:37:04 +0200 Subject: Cocoa: Clean up context creation. Make the fallback to creating an unshared context actually work by using correct [initWithFormat: ] code. Warn and return early on context creation failure instead of continuing and crashing. Change-Id: Ic88f419eaa717436aefc9c1da36c47e0ccb3e956 Task-number: QTBUG-47825 Reviewed-by: Laszlo Agocs --- src/plugins/platforms/cocoa/qcocoaglcontext.mm | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm index 1d8a1c5e70..0f9b8b900d 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm @@ -146,19 +146,25 @@ QCocoaGLContext::QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLCo QMacAutoReleasePool pool; // For the SG Canvas render thread + // create native context for the requested pixel format and share NSOpenGLPixelFormat *pixelFormat = static_cast (qcgl_createNSOpenGLPixelFormat(m_format)); m_shareContext = share ? static_cast(share)->nsOpenGLContext() : nil; + m_context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:m_shareContext]; - m_context = [NSOpenGLContext alloc]; - [m_context initWithFormat:pixelFormat shareContext:m_shareContext]; - + // retry without sharing on context creation failure. if (!m_context && m_shareContext) { - // try without shared context m_shareContext = nil; - [m_context initWithFormat:pixelFormat shareContext:nil]; + m_context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil]; + if (m_context) + qWarning("QCocoaGLContext: Falling back to unshared context."); } + // give up if we still did not get a native context [pixelFormat release]; + if (!m_context) { + qWarning("QCocoaGLContext: Failed to create context."); + return; + } const GLint interval = format.swapInterval() >= 0 ? format.swapInterval() : 1; [m_context setValues:&interval forParameter:NSOpenGLCPSwapInterval]; -- cgit v1.2.3 From 54dbdc26bacd3ab776c99ebef734404ef2e08ce5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 17 Aug 2015 17:59:06 +0200 Subject: Move min left/right bearing calculations to QFontEngine baseclass The logic used in the FreeType font engine can be generalized and move to the QFontEngine baseclass. This allows the CoreText font engine to correctly report the minimum left/right bearings, which decreases the chance that an optimization in QTextLayout's line breaking algorithm will produce wrong results. The calculation of left and right bearing has been moved to the glyph_metrics_t type to reduce code duplication. This allows us to use the with and height of the bounding box to determine if the glyph has any contours. Change-Id: I864697d3f31ed56f22f04666199b6c5023c5e585 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/text/qfontengine.cpp | 60 +++++++++++++++++++--- src/gui/text/qfontengine_ft.cpp | 49 ------------------ src/gui/text/qfontengine_ft_p.h | 4 -- src/gui/text/qfontengine_p.h | 8 ++- src/gui/text/qtextengine_p.h | 16 ++++++ src/gui/text/qtextlayout.cpp | 13 +++-- .../fontdatabases/mac/qfontengine_coretext.mm | 10 ---- .../fontdatabases/mac/qfontengine_coretext_p.h | 2 - 8 files changed, 86 insertions(+), 76 deletions(-) (limited to 'src') diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 2087bad9f6..102946b545 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -54,6 +54,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -235,10 +236,14 @@ Q_AUTOTEST_EXPORT QList QFontEngine_stopCollectingEngines() // QFontEngine +#define kBearingNotInitialized std::numeric_limits::max() + QFontEngine::QFontEngine(Type type) : m_type(type), ref(0), font_(0), font_destroy_func(0), - face_(0), face_destroy_func(0) + face_(0), face_destroy_func(0), + m_minLeftBearing(kBearingNotInitialized), + m_minRightBearing(kBearingNotInitialized) { faceData.user_data = this; faceData.get_font_table = qt_get_font_table_default; @@ -562,11 +567,55 @@ void QFontEngine::getGlyphPositions(const QGlyphLayout &glyphs, const QTransform void QFontEngine::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing) { glyph_metrics_t gi = boundingBox(glyph); - bool isValid = gi.isValid(); if (leftBearing != 0) - *leftBearing = isValid ? gi.x.toReal() : 0.0; + *leftBearing = gi.leftBearing().toReal(); if (rightBearing != 0) - *rightBearing = isValid ? (gi.xoff - gi.x - gi.width).toReal() : 0.0; + *rightBearing = gi.rightBearing().toReal(); +} + +qreal QFontEngine::minLeftBearing() const +{ + if (m_minLeftBearing == kBearingNotInitialized) + minRightBearing(); // Initializes both (see below) + + return m_minLeftBearing; +} + +qreal QFontEngine::minRightBearing() const +{ + if (m_minRightBearing == kBearingNotInitialized) { + + // To balance performance and correctness we only look at a subset of the + // possible glyphs in the font, based on which characters are more likely + // to have a left or right bearing. + static const ushort characterSubset[] = { + '(', 'C', 'F', 'K', 'V', 'X', 'Y', ']', '_', 'f', 'r', '|', + 127, 205, 645, 884, 922, 1070, 12386 + }; + + // The font may have minimum bearings larger than 0, so we have to start at the max + m_minLeftBearing = m_minRightBearing = std::numeric_limits::max(); + + for (uint i = 0; i < (sizeof(characterSubset) / sizeof(ushort)); ++i) { + const glyph_t glyph = glyphIndex(characterSubset[i]); + if (!glyph) + continue; + + glyph_metrics_t glyphMetrics = const_cast(this)->boundingBox(glyph); + + // Glyphs with no contours shouldn't contribute to bearings + if (!glyphMetrics.width || !glyphMetrics.height) + continue; + + m_minLeftBearing = qMin(m_minLeftBearing, glyphMetrics.leftBearing().toReal()); + m_minRightBearing = qMin(m_minRightBearing, glyphMetrics.rightBearing().toReal()); + } + + if (m_minLeftBearing == kBearingNotInitialized || m_minRightBearing == kBearingNotInitialized) + qWarning() << "Failed to compute left/right minimum bearings for" << fontDef.family; + } + + return m_minRightBearing; } glyph_metrics_t QFontEngine::tightBoundingBox(const QGlyphLayout &glyphs) @@ -1469,8 +1518,7 @@ QFixed QFontEngine::lastRightBearing(const QGlyphLayout &glyphs, bool round) glyph_t glyph = glyphs.glyphs[glyphs.numGlyphs - 1]; glyph_metrics_t gi = boundingBox(glyph); if (gi.isValid()) - return round ? QFixed(qRound(gi.xoff - gi.x - gi.width)) - : QFixed(gi.xoff - gi.x - gi.width); + return round ? qRound(gi.rightBearing()) : gi.rightBearing(); } return 0; } diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 246df127ad..0d28785aa1 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -688,7 +688,6 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format, symbol = bool(fontDef.family.contains(QLatin1String("symbol"), Qt::CaseInsensitive)); } - lbearing = rbearing = SHRT_MIN; freetype->computeSize(fontDef, &xsize, &ysize, &defaultGlyphSet.outline_drawing); FT_Face face = lockFace(); @@ -1258,54 +1257,6 @@ qreal QFontEngineFT::maxCharWidth() const return metrics.max_advance >> 6; } -static const ushort char_table[] = { - 40, - 67, - 70, - 75, - 86, - 88, - 89, - 91, - 95, - 102, - 114, - 124, - 127, - 205, - 645, - 884, - 922, - 1070, - 12386 -}; - -static const int char_table_entries = sizeof(char_table)/sizeof(ushort); - - -qreal QFontEngineFT::minLeftBearing() const -{ - if (lbearing == SHRT_MIN) - (void) minRightBearing(); // calculates both - return lbearing.toReal(); -} - -qreal QFontEngineFT::minRightBearing() const -{ - if (rbearing == SHRT_MIN) { - lbearing = rbearing = 0; - for (int i = 0; i < char_table_entries; ++i) { - const glyph_t glyph = glyphIndex(char_table[i]); - if (glyph != 0) { - glyph_metrics_t gi = const_cast(this)->boundingBox(glyph); - lbearing = qMin(lbearing, gi.x); - rbearing = qMin(rbearing, (gi.xoff - gi.x - gi.width)); - } - } - } - return rbearing.toReal(); -} - QFixed QFontEngineFT::lineThickness() const { return line_thickness; diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h index b81e51bf2e..83f9a4ef3d 100644 --- a/src/gui/text/qfontengine_ft_p.h +++ b/src/gui/text/qfontengine_ft_p.h @@ -208,8 +208,6 @@ private: virtual QFixed averageCharWidth() const Q_DECL_OVERRIDE; virtual qreal maxCharWidth() const Q_DECL_OVERRIDE; - virtual qreal minLeftBearing() const Q_DECL_OVERRIDE; - virtual qreal minRightBearing() const Q_DECL_OVERRIDE; virtual QFixed lineThickness() const Q_DECL_OVERRIDE; virtual QFixed underlinePosition() const Q_DECL_OVERRIDE; @@ -324,8 +322,6 @@ private: int xsize; int ysize; - mutable QFixed lbearing; - mutable QFixed rbearing; QFixed line_thickness; QFixed underline_position; diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index 780104bc37..5282a4033e 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -214,8 +214,8 @@ public: virtual QFixed underlinePosition() const; virtual qreal maxCharWidth() const = 0; - virtual qreal minLeftBearing() const { return qreal(); } - virtual qreal minRightBearing() const { return qreal(); } + virtual qreal minLeftBearing() const; + virtual qreal minRightBearing() const; virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0); @@ -323,6 +323,10 @@ private: private: QVariant m_userData; + + mutable qreal m_minLeftBearing; + mutable qreal m_minRightBearing; + }; Q_DECLARE_OPERATORS_FOR_FLAGS(QFontEngine::ShaperFlags) diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index d2b39f274c..160daa0cfd 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -107,6 +107,22 @@ struct Q_GUI_EXPORT glyph_metrics_t glyph_metrics_t transformed(const QTransform &xform) const; inline bool isValid() const {return x != 100000 && y != 100000;} + + inline QFixed leftBearing() const + { + if (!isValid()) + return QFixed(); + + return x; + } + + inline QFixed rightBearing() const + { + if (!isValid()) + return QFixed(); + + return xoff - x - width; + } }; Q_DECLARE_TYPEINFO(glyph_metrics_t, Q_PRIMITIVE_TYPE); diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 0c729c74d1..d68a59fae3 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1966,9 +1966,16 @@ void QTextLine::layout_helper(int maxGlyphs) // end up breaking due to the current glyph being too wide. QFixed previousRightBearing = lbh.rightBearing; - // We ignore the right bearing if the minimum negative bearing is too little to - // expand the text beyond the edge. - if (lbh.calculateNewWidth(line) - lbh.minimumRightBearing > line.width) + // We skip calculating the right bearing if the minimum negative bearing is too + // small to possibly expand the text beyond the edge. Note that this optimization + // will in some cases fail, as the minimum right bearing reported by the font + // engine may not cover all the glyphs in the font. The result is that we think + // we don't need to break at the current glyph (because the right bearing is 0), + // and when we then end up breaking on the next glyph we compute the right bearing + // and end up with a line width that is slightly larger width than what was requested. + // Unfortunately we can't remove this optimization as it will slow down text + // layouting significantly, so we accept the slight correctnes issue. + if ((lbh.calculateNewWidth(line) + qAbs(lbh.minimumRightBearing)) > line.width) lbh.calculateRightBearing(); if (lbh.checkFullOtherwiseExtend(line)) { diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 7e1dfd9275..732aead62a 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -361,16 +361,6 @@ qreal QCoreTextFontEngine::maxCharWidth() const return bb.xoff.toReal(); } -qreal QCoreTextFontEngine::minLeftBearing() const -{ - return 0; -} - -qreal QCoreTextFontEngine::minRightBearing() const -{ - return 0; -} - void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight) { QVarLengthArray positions; diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h index f8ec1d326f..1c33ae7d84 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h @@ -96,8 +96,6 @@ public: QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE; glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed, const QTransform &matrix, GlyphFormat) Q_DECL_OVERRIDE; QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE; - qreal minRightBearing() const Q_DECL_OVERRIDE; - qreal minLeftBearing() const Q_DECL_OVERRIDE; QFixed emSquareSize() const Q_DECL_OVERRIDE; bool supportsTransformation(const QTransform &transform) const Q_DECL_OVERRIDE; -- cgit v1.2.3 From 8981703817f2a1a54a788d30e721935cec5ed9b8 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Mon, 17 Aug 2015 09:33:28 +0200 Subject: QUuid: Also use CoCreateGuid on WinRt/Winphone and WinCE Change-Id: Ie44bd50fa1f2d4224f65d08fb4d721c3651b49ac Reviewed-by: Friedemann Kleint Reviewed-by: Joerg Bornemann --- src/corelib/plugin/quuid.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/corelib/plugin/quuid.cpp b/src/corelib/plugin/quuid.cpp index 812e2c9fb6..8b6dfc6932 100644 --- a/src/corelib/plugin/quuid.cpp +++ b/src/corelib/plugin/quuid.cpp @@ -891,7 +891,7 @@ bool QUuid::operator>(const QUuid &other) const Q_DECL_NOTHROW \sa variant(), version() */ -#if defined(Q_OS_WIN32) +#if defined(Q_OS_WIN) QT_BEGIN_INCLUDE_NAMESPACE #include // For CoCreateGuid @@ -905,7 +905,7 @@ QUuid QUuid::createUuid() return result; } -#else // !Q_OS_WIN32 +#else // Q_OS_WIN QT_BEGIN_INCLUDE_NAMESPACE #include "qdatetime.h" @@ -989,7 +989,7 @@ QUuid QUuid::createUuid() return result; } -#endif // !Q_OS_WIN32 +#endif // !Q_OS_WIN /*! \fn bool QUuid::operator==(const GUID &guid) const -- cgit v1.2.3 From 4b340402b97b83790b3d71a8244a246eec4f8abd Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Tue, 1 Sep 2015 08:49:31 +0200 Subject: WinRT: Fixed possible integer overflow in timer registration code Task-number: QTBUG-48012 Change-Id: If1b80e59c13230bc0a62c6fa3d45b6e2272b9e28 Reviewed-by: Andrew Knight --- src/corelib/kernel/qeventdispatcher_winrt.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp index f771974a24..490a7c566a 100644 --- a/src/corelib/kernel/qeventdispatcher_winrt.cpp +++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp @@ -288,7 +288,8 @@ void QEventDispatcherWinRT::registerTimer(int timerId, int interval, Qt::TimerTy } TimeSpan period; - period.Duration = interval ? (interval * 10000) : 1; // TimeSpan is based on 100-nanosecond units + // TimeSpan is based on 100-nanosecond units + period.Duration = qMax(qint64(1), qint64(interval) * 10000); const HANDLE handle = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, SYNCHRONIZE | EVENT_MODIFY_STATE); const HANDLE cancelHandle = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, SYNCHRONIZE|EVENT_MODIFY_STATE); HRESULT hr = runOnXamlThread([&]() { -- cgit v1.2.3 From c486cacba8fc6f22f8479ae588a399ae402f3bd0 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 2 Sep 2015 16:26:41 +0200 Subject: Testlib/Windows: Output crash information on stdout instead of stderr. Make it easier to capture information about crashing tests in log files, since it is not possible to do something like foo > log.txt 2> errlog.txt on Windows. Adapt selftest. [ChangeLog][QtTest][Important Behavior Changes] Crash/exception information is now logged to standard output on Windows. Task-number: QTBUG-47370 Change-Id: I3e6a2d25855ed0f20516418a031990b562f5f757 Reviewed-by: Simon Hausmann --- src/testlib/qtestcase.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index f9ae6138ad..7f199182f9 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -2796,33 +2796,34 @@ static LONG WINAPI windowsFaultHandler(struct _EXCEPTION_POINTERS *exInfo) appName[0] = 0; const void *exceptionAddress = exInfo->ExceptionRecord->ExceptionAddress; - fprintf(stderr, "A crash occurred in %s.\n\n" - "Exception address: 0x%p\n" - "Exception code : 0x%lx\n", - appName, exceptionAddress, exInfo->ExceptionRecord->ExceptionCode); + printf("A crash occurred in %s.\n\n" + "Exception address: 0x%p\n" + "Exception code : 0x%lx\n", + appName, exceptionAddress, exInfo->ExceptionRecord->ExceptionCode); DebugSymbolResolver resolver(GetCurrentProcess()); if (resolver.isValid()) { DebugSymbolResolver::Symbol exceptionSymbol = resolver.resolveSymbol(DWORD64(exceptionAddress)); if (exceptionSymbol.name) { - fprintf(stderr, "Nearby symbol : %s\n", exceptionSymbol.name); + printf("Nearby symbol : %s\n", exceptionSymbol.name); delete [] exceptionSymbol.name; } void *stack[maxStackFrames]; - fputs("\nStack:\n", stderr); + fputs("\nStack:\n", stdout); const unsigned frameCount = CaptureStackBackTrace(0, DWORD(maxStackFrames), stack, NULL); for (unsigned f = 0; f < frameCount; ++f) { DebugSymbolResolver::Symbol symbol = resolver.resolveSymbol(DWORD64(stack[f])); if (symbol.name) { - fprintf(stderr, "#%3u: %s() - 0x%p\n", f + 1, symbol.name, (const void *)symbol.address); + printf("#%3u: %s() - 0x%p\n", f + 1, symbol.name, (const void *)symbol.address); delete [] symbol.name; } else { - fprintf(stderr, "#%3u: Unable to obtain symbol\n", f + 1); + printf("#%3u: Unable to obtain symbol\n", f + 1); } } } - fputc('\n', stderr); + fputc('\n', stdout); + fflush(stdout); return EXCEPTION_EXECUTE_HANDLER; } -- cgit v1.2.3 From c5068866cfa88c41b3bb8ccc5083b7798128e9b2 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Wed, 2 Sep 2015 19:33:14 +0200 Subject: Add a window title for the QPrintDialog Properties dialog Change-Id: Ia74edf45e78fb81256da86d572459b3ed38663d4 Reviewed-by: Friedemann Kleint --- src/printsupport/dialogs/qprintdialog_unix.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/printsupport/dialogs/qprintdialog_unix.cpp b/src/printsupport/dialogs/qprintdialog_unix.cpp index 502ff7d98a..a15fd51c98 100644 --- a/src/printsupport/dialogs/qprintdialog_unix.cpp +++ b/src/printsupport/dialogs/qprintdialog_unix.cpp @@ -231,6 +231,7 @@ public: QPrintPropertiesDialog::QPrintPropertiesDialog(QAbstractPrintDialog *parent) : QDialog(parent) { + setWindowTitle(tr("Printer Properties")); QVBoxLayout *lay = new QVBoxLayout(this); this->setLayout(lay); QWidget *content = new QWidget(this); -- cgit v1.2.3 From 041fae00351164fbd72763e4bd947fdeb9956a5d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 20 Aug 2015 14:22:13 -0700 Subject: Fix crash on exit caused by QStringLiterals These QStringLiterals are passed to QtDBus, which records them. They will be used even after the libQt5XcbQpa.so library is unloaded, which causes a crash on exit, one that even valgrind gets lost on. Change-Id: I7de033f80b0e4431b7f1ffff13fc4888e45a346a Reviewed-by: Albert Astals Cid Reviewed-by: Richard J. Moore Reviewed-by: Frederik Gladhorn --- src/platformsupport/linuxaccessibility/dbusconnection.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/platformsupport/linuxaccessibility/dbusconnection.cpp b/src/platformsupport/linuxaccessibility/dbusconnection.cpp index 637b06549a..ae1ba1819a 100644 --- a/src/platformsupport/linuxaccessibility/dbusconnection.cpp +++ b/src/platformsupport/linuxaccessibility/dbusconnection.cpp @@ -47,8 +47,11 @@ QT_BEGIN_NAMESPACE -QString A11Y_SERVICE = QStringLiteral("org.a11y.Bus"); -QString A11Y_PATH = QStringLiteral("/org/a11y/bus"); +/* note: do not change these to QStringLiteral; + we are unloaded before QtDBus is done using the strings. + */ +#define A11Y_SERVICE QLatin1String("org.a11y.Bus") +#define A11Y_PATH QLatin1String("/org/a11y/bus") /*! \class DBusConnection @@ -137,7 +140,7 @@ void DBusConnection::connectA11yBus(const QString &address) qWarning("Could not find Accessibility DBus address."); return; } - m_a11yConnection = QDBusConnection(QDBusConnection::connectToBus(address, QStringLiteral("a11y"))); + m_a11yConnection = QDBusConnection(QDBusConnection::connectToBus(address, QLatin1String("a11y"))); if (m_enabled) emit enabledChanged(true); -- cgit v1.2.3 From 5953109a04e16df1abb87d37a676a0a51e7a2eca Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Tue, 18 Aug 2015 17:23:56 -0700 Subject: Fix QSysInfo::windowsVersion() for good. Task-number: QTBUG-38439 Task-number: QTBUG-43444 Change-Id: I9870200806f2ca378b0977dee0674d89e2c6836c Reviewed-by: Andrew Knight Reviewed-by: Friedemann Kleint Reviewed-by: Thiago Macieira --- src/corelib/global/qglobal.cpp | 139 +++++++++++++++++------------------------ 1 file changed, 56 insertions(+), 83 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 77ac53f7e9..f0208846aa 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -1935,91 +1935,69 @@ QWindowsSockInit::~QWindowsSockInit() Q_GLOBAL_STATIC(QWindowsSockInit, winsockInit) # endif // QT_BOOTSTRAPPED -# ifndef Q_OS_WINCE - -// Determine Windows versions >= 8 by querying the version of kernel32.dll. -static inline bool determineWinOsVersionPost8(OSVERSIONINFO *result) -{ - typedef WORD (WINAPI* PtrGetFileVersionInfoSizeW)(LPCWSTR, LPDWORD); - typedef BOOL (WINAPI* PtrVerQueryValueW)(LPCVOID, LPCWSTR, LPVOID, PUINT); - typedef BOOL (WINAPI* PtrGetFileVersionInfoW)(LPCWSTR, DWORD, DWORD, LPVOID); - - QSystemLibrary versionLib(QStringLiteral("version")); - if (!versionLib.load()) - return false; - PtrGetFileVersionInfoSizeW getFileVersionInfoSizeW = (PtrGetFileVersionInfoSizeW)versionLib.resolve("GetFileVersionInfoSizeW"); - PtrVerQueryValueW verQueryValueW = (PtrVerQueryValueW)versionLib.resolve("VerQueryValueW"); - PtrGetFileVersionInfoW getFileVersionInfoW = (PtrGetFileVersionInfoW)versionLib.resolve("GetFileVersionInfoW"); - if (!getFileVersionInfoSizeW || !verQueryValueW || !getFileVersionInfoW) - return false; - - const wchar_t kernel32Dll[] = L"kernel32.dll"; - DWORD handle; - const DWORD size = getFileVersionInfoSizeW(kernel32Dll, &handle); - if (!size) - return false; - QScopedArrayPointer versionInfo(new BYTE[size]); - if (!getFileVersionInfoW(kernel32Dll, handle, size, versionInfo.data())) - return false; - UINT uLen; - VS_FIXEDFILEINFO *fileInfo = Q_NULLPTR; - if (!verQueryValueW(versionInfo.data(), L"\\", (LPVOID *)&fileInfo, &uLen)) - return false; - const DWORD fileVersionMS = fileInfo->dwFileVersionMS; - const DWORD fileVersionLS = fileInfo->dwFileVersionLS; - result->dwMajorVersion = HIWORD(fileVersionMS); - result->dwMinorVersion = LOWORD(fileVersionMS); - result->dwBuildNumber = HIWORD(fileVersionLS); - return true; -} +#endif // !Q_OS_WINRT -// Fallback for determining Windows versions >= 8 by looping using the -// version check macros. Note that it will return build number=0 to avoid -// inefficient looping. -static inline void determineWinOsVersionFallbackPost8(OSVERSIONINFO *result) +#ifdef Q_OS_WINRT +static inline HMODULE moduleHandleForFunction(LPCVOID address) { - result->dwBuildNumber = 0; - DWORDLONG conditionMask = 0; - VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); - VER_SET_CONDITION(conditionMask, VER_PLATFORMID, VER_EQUAL); - OSVERSIONINFOEX checkVersion = { sizeof(OSVERSIONINFOEX), result->dwMajorVersion, 0, - result->dwBuildNumber, result->dwPlatformId, {'\0'}, 0, 0, 0, 0, 0 }; - for ( ; VerifyVersionInfo(&checkVersion, VER_MAJORVERSION | VER_PLATFORMID, conditionMask); ++checkVersion.dwMajorVersion) - result->dwMajorVersion = checkVersion.dwMajorVersion; - conditionMask = 0; - checkVersion.dwMajorVersion = result->dwMajorVersion; - checkVersion.dwMinorVersion = 0; - VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_EQUAL); - VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); - VER_SET_CONDITION(conditionMask, VER_PLATFORMID, VER_EQUAL); - for ( ; VerifyVersionInfo(&checkVersion, VER_MAJORVERSION | VER_MINORVERSION | VER_PLATFORMID, conditionMask); ++checkVersion.dwMinorVersion) - result->dwMinorVersion = checkVersion.dwMinorVersion; + // This is a widely used, decades-old technique for retrieving the handle + // of a module and is effectively equivalent to GetModuleHandleEx + // (which is unavailable on WinRT) + MEMORY_BASIC_INFORMATION mbi = { 0, 0, 0, 0, 0, 0, 0 }; + if (VirtualQuery(address, &mbi, sizeof(mbi)) == 0) + return 0; + return reinterpret_cast(mbi.AllocationBase); } - -# endif // !Q_OS_WINCE +#endif static inline OSVERSIONINFO winOsVersion() { OSVERSIONINFO result = { sizeof(OSVERSIONINFO), 0, 0, 0, 0, {'\0'}}; + +#ifndef Q_OS_WINCE +#define GetProcAddressA GetProcAddress +#endif + + // GetModuleHandle is not supported in WinRT and linking to it at load time + // will not pass the Windows App Certification Kit... but it exists and is functional, + // so use some unusual but widely used techniques to get a pointer to it +#ifdef Q_OS_WINRT + // 1. Get HMODULE of kernel32.dll, using the address of some function exported by that DLL + HMODULE kernelModule = moduleHandleForFunction(reinterpret_cast(VirtualQuery)); + if (Q_UNLIKELY(!kernelModule)) + return result; + + // 2. Get pointer to GetModuleHandle so we can then load other arbitrary modules (DLLs) + typedef HMODULE(WINAPI *GetModuleHandleFunction)(LPCWSTR); + GetModuleHandleFunction pGetModuleHandle = reinterpret_cast( + GetProcAddressA(kernelModule, "GetModuleHandleW")); + if (Q_UNLIKELY(!pGetModuleHandle)) + return result; +#else +#define pGetModuleHandle GetModuleHandleW +#endif + + HMODULE ntdll = pGetModuleHandle(L"ntdll.dll"); + if (Q_UNLIKELY(!ntdll)) + return result; + + // NTSTATUS is not defined on WinRT + typedef LONG NTSTATUS; + typedef NTSTATUS (NTAPI *RtlGetVersionFunction)(LPOSVERSIONINFO); + + // RtlGetVersion is documented public API but we must load it dynamically + // because linking to it at load time will not pass the Windows App Certification Kit + // https://msdn.microsoft.com/en-us/library/windows/hardware/ff561910.aspx + RtlGetVersionFunction pRtlGetVersion = reinterpret_cast( + GetProcAddressA(ntdll, "RtlGetVersion")); + if (Q_UNLIKELY(!pRtlGetVersion)) + return result; + // GetVersionEx() has been deprecated in Windows 8.1 and will return - // only Windows 8 from that version on. -# if defined(_MSC_VER) && _MSC_VER >= 1800 -# pragma warning( push ) -# pragma warning( disable : 4996 ) -# endif - GetVersionEx(&result); -# if defined(_MSC_VER) && _MSC_VER >= 1800 -# pragma warning( pop ) -# endif -# ifndef Q_OS_WINCE - if (result.dwMajorVersion == 6 && result.dwMinorVersion == 2) { - if (!determineWinOsVersionPost8(&result)) - determineWinOsVersionFallbackPost8(&result); - } -# endif // !Q_OS_WINCE + // only Windows 8 from that version on, so use the kernel API function. + pRtlGetVersion(&result); // always returns STATUS_SUCCESS return result; } -#endif // !Q_OS_WINRT QSysInfo::WinVersion QSysInfo::windowsVersion() { @@ -2039,11 +2017,10 @@ QSysInfo::WinVersion QSysInfo::windowsVersion() static QSysInfo::WinVersion winver; if (winver) return winver; -#ifdef Q_OS_WINRT - winver = QSysInfo::WV_WINDOWS8_1; -#else winver = QSysInfo::WV_NT; const OSVERSIONINFO osver = winOsVersion(); + if (osver.dwMajorVersion == 0) + return QSysInfo::WV_None; #ifdef Q_OS_WINCE DWORD qt_cever = 0; qt_cever = osver.dwMajorVersion * 100; @@ -2123,7 +2100,6 @@ QSysInfo::WinVersion QSysInfo::windowsVersion() } } #endif -#endif // !Q_OS_WINRT return winver; } @@ -2594,10 +2570,7 @@ QString QSysInfo::kernelType() */ QString QSysInfo::kernelVersion() { -#ifdef Q_OS_WINRT - // TBD - return QString(); -#elif defined(Q_OS_WIN) +#ifdef Q_OS_WIN const OSVERSIONINFO osver = winOsVersion(); return QString::number(int(osver.dwMajorVersion)) + QLatin1Char('.') + QString::number(int(osver.dwMinorVersion)) + QLatin1Char('.') + QString::number(int(osver.dwBuildNumber)); -- cgit v1.2.3 From 296422fc636acce0af3afc5824dcc3128f319f7c Mon Sep 17 00:00:00 2001 From: Samuel Nevala Date: Fri, 28 Aug 2015 13:32:55 +0300 Subject: winrt: Add support for native pickers for Windows Phone. Support picking file(s), folder and save file via native component on Windows Phone. Task-Id: QTBUG-44833 Change-Id: Ibffc1cf3c133c9fbf9c92e0a4f874c4e197c50ee Reviewed-by: Oliver Wolff --- .../platforms/winrt/qwinrtfiledialoghelper.cpp | 280 ++++++++++++++++++--- .../platforms/winrt/qwinrtfiledialoghelper.h | 12 +- src/winmain/qtmain_winrt.cpp | 24 +- 3 files changed, 273 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp index e1b2a07d5f..05b1fd76b1 100644 --- a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp +++ b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp @@ -37,25 +37,32 @@ #include "qwinrtfiledialoghelper.h" #include "qwinrtfileengine.h" +#include #include #include #include #include +#include +#include #include #include #include +#include using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::ApplicationModel::Activation; using namespace ABI::Windows::Foundation; using namespace ABI::Windows::Foundation::Collections; using namespace ABI::Windows::Storage; using namespace ABI::Windows::Storage::Pickers; +#ifndef Q_OS_WINPHONE typedef IAsyncOperationCompletedHandler SingleFileHandler; typedef IAsyncOperationCompletedHandler *> MultipleFileHandler; typedef IAsyncOperationCompletedHandler SingleFolderHandler; +#endif QT_BEGIN_NAMESPACE @@ -142,6 +149,16 @@ private: QVector impl; }; +#ifdef Q_OS_WINPHONE +class QActivationEvent : public QEvent +{ +public: + IInspectable *args() const { + return reinterpret_cast(d); + } +}; +#endif + template static bool initializePicker(HSTRING runtimeId, T **picker, const QSharedPointer &options) { @@ -200,6 +217,99 @@ static bool initializeOpenPickerOptions(T *picker, const QSharedPointer picker2; + hr = picker->QueryInterface(IID_PPV_ARGS(picker2.GetAddressOf())); + RETURN_HR_IF_FAILED("Failed to cast file picker"); + if (singleFile) + return picker2->PickSingleFileAndContinue(); + else + return picker2->PickMultipleFilesAndContinue(); + }); + RETURN_FALSE_IF_FAILED("Failed to open file picker"); + QAbstractEventDispatcher *eventDispatcher = QCoreApplication::eventDispatcher(); + Q_ASSERT(eventDispatcher); + eventDispatcher->installEventFilter(helper); + return true; +#else + if (singleFile) { + ComPtr> op; + hr = picker->PickSingleFileAsync(&op); + RETURN_FALSE_IF_FAILED("Failed to open single file picker"); + hr = op->put_Completed(Callback(helper, &QWinRTFileDialogHelper::onSingleFilePicked).Get()); + RETURN_FALSE_IF_FAILED("Failed to attach file picker callback"); + } else { + ComPtr *>> op; + hr = picker->PickMultipleFilesAsync(&op); + RETURN_FALSE_IF_FAILED("Failed to open multi file picker"); + hr = op->put_Completed(Callback(helper, &QWinRTFileDialogHelper::onMultipleFilesPicked).Get()); + RETURN_FALSE_IF_FAILED("Failed to attach multi file callback"); + } + return true; +#endif +} + +static bool pickFolder(IFolderPicker *picker, QWinRTFileDialogHelper *helper) +{ + Q_ASSERT(picker); + Q_ASSERT(helper); + HRESULT hr; +#ifdef Q_OS_WINPHONE + hr = QEventDispatcherWinRT::runOnXamlThread([picker]() { + HRESULT hr; + ComPtr picker2; + hr = picker->QueryInterface(IID_PPV_ARGS(picker2.GetAddressOf())); + RETURN_HR_IF_FAILED("Failed to cast folder picker"); + return picker2->PickFolderAndContinue(); + }); + RETURN_FALSE_IF_FAILED("Failed to open folder picker"); + QAbstractEventDispatcher *eventDispatcher = QCoreApplication::eventDispatcher(); + Q_ASSERT(eventDispatcher); + eventDispatcher->installEventFilter(helper); +#else + ComPtr> op; + hr = picker->PickSingleFolderAsync(&op); + RETURN_FALSE_IF_FAILED("Failed to open folder picker"); + hr = op->put_Completed(Callback(helper, &QWinRTFileDialogHelper::onSingleFolderPicked).Get()); + RETURN_FALSE_IF_FAILED("Failed to attach folder picker callback"); +#endif + return true; +} + +static bool pickSaveFile(IFileSavePicker *picker, QWinRTFileDialogHelper *helper) +{ + Q_ASSERT(picker); + Q_ASSERT(helper); + HRESULT hr; +#ifdef Q_OS_WINPHONE + hr = QEventDispatcherWinRT::runOnXamlThread([picker]() { + HRESULT hr; + ComPtr picker2; + hr = picker->QueryInterface(IID_PPV_ARGS(picker2.GetAddressOf())); + RETURN_HR_IF_FAILED("Failed to cast save file picker"); + return picker2->PickSaveFileAndContinue(); + }); + RETURN_FALSE_IF_FAILED("Failed to open single file picker"); + QAbstractEventDispatcher *eventDispatcher = QCoreApplication::eventDispatcher(); + Q_ASSERT(eventDispatcher); + eventDispatcher->installEventFilter(helper); +#else + ComPtr> op; + hr = picker->PickSaveFileAsync(&op); + RETURN_FALSE_IF_FAILED("Failed to open save file picker"); + hr = op->put_Completed(Callback(helper, &QWinRTFileDialogHelper::onSingleFilePicked).Get()); + RETURN_FALSE_IF_FAILED("Failed to attach save file picker callback"); +#endif + return true; +} + class QWinRTFileDialogHelperPrivate { public: @@ -260,18 +370,9 @@ bool QWinRTFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModalit if (!initializeOpenPickerOptions(picker.Get(), dialogOptions)) return false; - if (dialogOptions->fileMode() == QFileDialogOptions::ExistingFiles) { - ComPtr *>> op; - hr = picker->PickMultipleFilesAsync(&op); - RETURN_FALSE_IF_FAILED("Failed to open multi file picker"); - hr = op->put_Completed(Callback(this, &QWinRTFileDialogHelper::onMultipleFilesPicked).Get()); - } else { - ComPtr> op; - hr = picker->PickSingleFileAsync(&op); - RETURN_FALSE_IF_FAILED("Failed to open single file picker"); - hr = op->put_Completed(Callback(this, &QWinRTFileDialogHelper::onSingleFilePicked).Get()); - } - RETURN_FALSE_IF_FAILED("Failed to attach file picker callback"); + if (!pickFiles(picker.Get(), this, dialogOptions->fileMode() == QFileDialogOptions::ExistingFile)) + return false; + break; } case QFileDialogOptions::Directory: @@ -284,11 +385,9 @@ bool QWinRTFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModalit if (!initializeOpenPickerOptions(picker.Get(), dialogOptions)) return false; - ComPtr> op; - hr = picker->PickSingleFolderAsync(&op); - RETURN_FALSE_IF_FAILED("Failed to open folder picker"); - hr = op->put_Completed(Callback(this, &QWinRTFileDialogHelper::onSingleFolderPicked).Get()); - RETURN_FALSE_IF_FAILED("Failed to attach folder picker callback"); + if (!pickFolder(picker.Get(), this)) + return false; + break; } } @@ -344,11 +443,9 @@ bool QWinRTFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModalit RETURN_FALSE_IF_FAILED("Failed to set suggested file name"); } - ComPtr> op; - hr = picker->PickSaveFileAsync(&op); - RETURN_FALSE_IF_FAILED("Failed to open save file picker"); - hr = op->put_Completed(Callback(this, &QWinRTFileDialogHelper::onSingleFilePicked).Get()); - RETURN_FALSE_IF_FAILED("Failed to attach file picker callback"); + if (!pickSaveFile(picker.Get(), this)) + return false; + break; } } @@ -367,6 +464,68 @@ void QWinRTFileDialogHelper::hide() d->shown = false; } +#ifdef Q_OS_WINPHONE +bool QWinRTFileDialogHelper::eventFilter(QObject *, QEvent *e) +{ + if (e->type() != QEvent::WinEventAct) + return false; + + HRESULT hr; + QActivationEvent *event = static_cast(e); + ComPtr inspectable = event->args(); + ComPtr arguments; + hr = inspectable.As(&arguments); + Q_ASSERT_SUCCEEDED(hr); + + ActivationKind activationKind; + hr = arguments->get_Kind(&activationKind); + Q_ASSERT_SUCCEEDED(hr); + + // Handle only File, Folder and Save file pick continuation here. + if (activationKind != ActivationKind_PickFileContinuation + && activationKind != ActivationKind_PickFolderContinuation + && activationKind != ActivationKind_PickSaveFileContinuation) { + return false; + } + + QAbstractEventDispatcher *eventDispatcher = QCoreApplication::eventDispatcher(); + Q_ASSERT(eventDispatcher); + eventDispatcher->removeEventFilter(this); + e->accept(); + + if (activationKind == ActivationKind_PickFileContinuation) { + ComPtr fileContinuationArgs; + hr = arguments.As(&fileContinuationArgs); + Q_ASSERT_SUCCEEDED(hr); + ComPtr> files; + hr = fileContinuationArgs->get_Files(&files); + Q_ASSERT_SUCCEEDED(hr); + hr = onFilesPicked(files.Get()); + Q_ASSERT_SUCCEEDED(hr); + } else if (activationKind == ActivationKind_PickFolderContinuation) { + ComPtr folderContinuationArgs; + hr = arguments.As(&folderContinuationArgs); + Q_ASSERT_SUCCEEDED(hr); + ComPtr folder; + hr = folderContinuationArgs->get_Folder(&folder); + Q_ASSERT_SUCCEEDED(hr); + hr = onFolderPicked(folder.Get()); + Q_ASSERT_SUCCEEDED(hr); + } else { + ComPtr saveFileContinuationArgs; + hr = arguments.As(&saveFileContinuationArgs); + Q_ASSERT_SUCCEEDED(hr); + ComPtr file; + hr = saveFileContinuationArgs->get_File(&file); + Q_ASSERT_SUCCEEDED(hr); + hr = onFilePicked(file.Get()); + Q_ASSERT_SUCCEEDED(hr); + } + + return true; +} +#endif + void QWinRTFileDialogHelper::setDirectory(const QUrl &directory) { Q_D(QWinRTFileDialogHelper); @@ -403,6 +562,7 @@ QString QWinRTFileDialogHelper::selectedNameFilter() const return d->selectedNameFilter; } +#ifndef Q_OS_WINPHONE HRESULT QWinRTFileDialogHelper::onSingleFilePicked(IAsyncOperation *args, AsyncStatus status) { Q_D(QWinRTFileDialogHelper); @@ -419,14 +579,7 @@ HRESULT QWinRTFileDialogHelper::onSingleFilePicked(IAsyncOperation file; hr = args->GetResults(&file); Q_ASSERT_SUCCEEDED(hr); - if (!file) { - emit reject(); - return S_OK; - } - - appendFile(file.Get()); - emit accept(); - return S_OK; + return onFilePicked(file.Get()); } HRESULT QWinRTFileDialogHelper::onMultipleFilesPicked(IAsyncOperation *> *args, AsyncStatus status) @@ -445,17 +598,50 @@ HRESULT QWinRTFileDialogHelper::onMultipleFilesPicked(IAsyncOperation> fileList; hr = args->GetResults(&fileList); RETURN_HR_IF_FAILED("Failed to get file list"); + return onFilesPicked(fileList.Get()); +} + +HRESULT QWinRTFileDialogHelper::onSingleFolderPicked(IAsyncOperation *args, AsyncStatus status) +{ + Q_D(QWinRTFileDialogHelper); + + QEventLoopLocker locker(&d->loop); + d->shown = false; + d->selectedFiles.clear(); + if (status == Canceled || status == Error) { + emit reject(); + return S_OK; + } + + HRESULT hr; + ComPtr folder; + hr = args->GetResults(&folder); + Q_ASSERT_SUCCEEDED(hr); + return onFolderPicked(folder.Get()); +} +#endif //Q_OS_WINPHONE + +HRESULT QWinRTFileDialogHelper::onFilesPicked(IVectorView *files) +{ +#ifdef Q_OS_WINPHONE + Q_D(QWinRTFileDialogHelper); + QEventLoopLocker locker(&d->loop); + d->shown = false; + d->selectedFiles.clear(); +#endif + HRESULT hr; quint32 size; - hr = fileList->get_Size(&size); + hr = files->get_Size(&size); Q_ASSERT_SUCCEEDED(hr); if (!size) { emit reject(); return S_OK; } + for (quint32 i = 0; i < size; ++i) { ComPtr file; - hr = fileList->GetAt(i, &file); + hr = files->GetAt(i, &file); Q_ASSERT_SUCCEEDED(hr); appendFile(file.Get()); } @@ -464,28 +650,40 @@ HRESULT QWinRTFileDialogHelper::onMultipleFilesPicked(IAsyncOperation *args, AsyncStatus status) +HRESULT QWinRTFileDialogHelper::onFolderPicked(IStorageFolder *folder) { +#ifdef Q_OS_WINPHONE Q_D(QWinRTFileDialogHelper); - QEventLoopLocker locker(&d->loop); d->shown = false; d->selectedFiles.clear(); - if (status == Canceled || status == Error) { +#endif + + if (!folder) { emit reject(); return S_OK; } - HRESULT hr; - ComPtr folder; - hr = args->GetResults(&folder); - Q_ASSERT_SUCCEEDED(hr); - if (!folder) { + appendFile(folder); + emit accept(); + return S_OK; +} + +HRESULT QWinRTFileDialogHelper::onFilePicked(IStorageFile *file) +{ +#ifdef Q_OS_WINPHONE + Q_D(QWinRTFileDialogHelper); + QEventLoopLocker locker(&d->loop); + d->shown = false; + d->selectedFiles.clear(); +#endif + + if (!file) { emit reject(); return S_OK; } - appendFile(folder.Get()); + appendFile(file); emit accept(); return S_OK; } diff --git a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.h b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.h index 51b79c84ef..d6bacd2db9 100644 --- a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.h +++ b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.h @@ -47,6 +47,7 @@ namespace ABI { class StorageFile; class StorageFolder; struct IStorageFile; + struct IStorageFolder; } namespace Foundation { enum class AsyncStatus; @@ -71,6 +72,9 @@ public: void exec() Q_DECL_OVERRIDE; bool show(Qt::WindowFlags, Qt::WindowModality, QWindow *) Q_DECL_OVERRIDE; void hide() Q_DECL_OVERRIDE; +#ifdef Q_OS_WINPHONE + bool eventFilter(QObject *o, QEvent *e) Q_DECL_OVERRIDE; +#endif bool defaultNameFilterDisables() const Q_DECL_OVERRIDE { return false; } void setDirectory(const QUrl &directory) Q_DECL_OVERRIDE; @@ -81,13 +85,19 @@ public: void selectNameFilter(const QString &selectedNameFilter) Q_DECL_OVERRIDE; QString selectedNameFilter() const; -private: +#ifndef Q_OS_WINPHONE HRESULT onSingleFilePicked(ABI::Windows::Foundation::IAsyncOperation *, ABI::Windows::Foundation::AsyncStatus); HRESULT onMultipleFilesPicked(ABI::Windows::Foundation::IAsyncOperation *> *, ABI::Windows::Foundation::AsyncStatus); HRESULT onSingleFolderPicked(ABI::Windows::Foundation::IAsyncOperation *, ABI::Windows::Foundation::AsyncStatus); +#endif + +private: + HRESULT onFilesPicked(ABI::Windows::Foundation::Collections::IVectorView *files); + HRESULT onFolderPicked(ABI::Windows::Storage::IStorageFolder *folder); + HRESULT onFilePicked(ABI::Windows::Storage::IStorageFile *file); void appendFile(IInspectable *); QScopedPointer d_ptr; diff --git a/src/winmain/qtmain_winrt.cpp b/src/winmain/qtmain_winrt.cpp index d9f8c8f991..b7125eec59 100644 --- a/src/winmain/qtmain_winrt.cpp +++ b/src/winmain/qtmain_winrt.cpp @@ -70,6 +70,7 @@ extern "C" { #include #include #include +#include #include #include @@ -109,6 +110,24 @@ static void devMessageHandler(QtMsgType type, const QMessageLogContext &context, defaultMessageHandler(type, context, message); } +class QActivationEvent : public QEvent +{ +public: + explicit QActivationEvent(IInspectable *args) + : QEvent(QEvent::WinEventAct) + { + setAccepted(false); + args->AddRef(); + d = reinterpret_cast(args); + } + + ~QActivationEvent() { + IUnknown *args = reinterpret_cast(d); + args->Release(); + d = nullptr; + } +}; + class AppContainer : public RuntimeClass { public: @@ -158,7 +177,10 @@ public: private: HRESULT __stdcall OnActivated(IActivatedEventArgs *args) Q_DECL_OVERRIDE { - return base->OnActivated(args); + QAbstractEventDispatcher *dispatcher = QCoreApplication::eventDispatcher(); + if (dispatcher) + QCoreApplication::postEvent(dispatcher, new QActivationEvent(args)); + return S_OK; } HRESULT __stdcall OnLaunched(ILaunchActivatedEventArgs *launchArgs) Q_DECL_OVERRIDE -- cgit v1.2.3 From 6313ff8a6298d221f0ededba12d6e4a9de777c98 Mon Sep 17 00:00:00 2001 From: Samuel Nevala Date: Fri, 4 Sep 2015 12:50:12 +0300 Subject: winrt: Fix top level window geometry. Set screen geometry only for top level window. For other window types (dialog, popup and etc.) use their own geometry. Change-Id: I47e45a9fc6f08587ea284d89d56e419907471572 Task-Id: QTBUG-48089 Reviewed-by: Andrew Knight --- src/plugins/platforms/winrt/qwinrtwindow.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/winrt/qwinrtwindow.cpp b/src/plugins/platforms/winrt/qwinrtwindow.cpp index 23e4e163e4..cebc9e15c2 100644 --- a/src/plugins/platforms/winrt/qwinrtwindow.cpp +++ b/src/plugins/platforms/winrt/qwinrtwindow.cpp @@ -196,8 +196,9 @@ void QWinRTWindow::setGeometry(const QRect &rect) { Q_D(QWinRTWindow); - if (window()->isTopLevel()) { - QPlatformWindow::setGeometry(window()->flags() & Qt::MaximizeUsingFullscreenGeometryHint + const Qt::WindowFlags windowFlags = window()->flags(); + if (window()->isTopLevel() && (windowFlags & Qt::WindowType_Mask) == Qt::Window) { + QPlatformWindow::setGeometry(windowFlags & Qt::MaximizeUsingFullscreenGeometryHint ? d->screen->geometry() : d->screen->availableGeometry()); QWindowSystemInterface::handleGeometryChange(window(), geometry()); } else { -- cgit v1.2.3 From 72e5fda3bd1b50ee3e0da0b5ef6505e632f7f5bc Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Tue, 25 Aug 2015 16:00:01 +0200 Subject: qdoc: Correctly resolve non-function links that end in parentheses If QDoc fails to find a function node for a link target that ends in parentheses, it must retry to find another type of node, as page/section titles can sometimes resemble function signatures. This fixes a regression introduced by commit 8c5ce68f. Change-Id: I675fe5b93ecc8a1823c0a5f817fb4b80b4e63320 Task-number: QTBUG-47919 Reviewed-by: Alex Blasche Reviewed-by: Martin Smith --- src/tools/qdoc/qdocdatabase.cpp | 32 ++++++++++---------------------- 1 file changed, 10 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/tools/qdoc/qdocdatabase.cpp b/src/tools/qdoc/qdocdatabase.cpp index 5ca8e36ef9..6312deacbf 100644 --- a/src/tools/qdoc/qdocdatabase.cpp +++ b/src/tools/qdoc/qdocdatabase.cpp @@ -306,15 +306,12 @@ const Node* QDocForest::findNodeForTarget(QStringList& targetPath, { int flags = SearchBaseClasses | SearchEnumValues; - QString entity = targetPath.at(0); - targetPath.removeFirst(); + QString entity = targetPath.takeFirst(); QStringList entityPath = entity.split("::"); QString target; - if (!targetPath.isEmpty()) { - target = targetPath.at(0); - targetPath.removeFirst(); - } + if (!targetPath.isEmpty()) + target = targetPath.takeFirst(); foreach (Tree* t, searchOrder()) { const Node* n = t->findNodeForTarget(entityPath, target, relative, flags, genus, ref); @@ -1703,37 +1700,28 @@ const Node* QDocDatabase::findNodeForAtom(const Atom* a, const Node* relative, Q function = first.left(position); node = domain->findFunctionNode(function, params, 0, genus); } - else { + if (!node) { int flags = SearchBaseClasses | SearchEnumValues; QStringList nodePath = first.split("::"); QString target; targetPath.removeFirst(); - if (!targetPath.isEmpty()) { - target = targetPath.at(0); - targetPath.removeFirst(); - } + if (!targetPath.isEmpty()) + target = targetPath.takeFirst(); if (relative && relative->tree()->physicalModuleName() != domain->physicalModuleName()) relative = 0; - node = domain->findNodeForTarget(nodePath, target, relative, flags, genus, ref); - return node; + return domain->findNodeForTarget(nodePath, target, relative, flags, genus, ref); } } else { - if (first.endsWith(".html")) { + if (first.endsWith(".html")) node = findNodeByNameAndType(QStringList(first), Node::Document); - // the path may also refer to an example file with .html extension - if (!node && first.contains("/")) - return findNodeForTarget(targetPath, relative, genus, ref); - } else if (first.endsWith(QChar(')'))) { node = findFunctionNode(first, relative, genus); if (Generator::debugging()) qDebug() << " node:" << node; } - else { - node = findNodeForTarget(targetPath, relative, genus, ref); - return node; - } + if (!node) + return findNodeForTarget(targetPath, relative, genus, ref); } if (node && ref.isEmpty()) { -- cgit v1.2.3 From 9c6a49078ae0da65f605384ba16e2a46e19ff5a1 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Fri, 28 Aug 2015 15:01:17 +0200 Subject: qdoc: Introduce codeprefix & codesuffix, re-introduce codeindent In order to provide acceptable results for styling the documentation for rendering using QTextBrowser (instead of a full browser engine), QDoc needs flexibility in adjusting the generated HTML. This commit introduces and documents codeprefix and codesuffix variables for qdocconf, and re-introduces the once-removed support for codeindent. The default codeindent value is reset to 0. These changes have no effect to the generated output unless the above variables are defined. Change-Id: I6eb40dc0700725622e5a525ef19b5626b3b2b6a5 Reviewed-by: Martin Smith --- src/tools/qdoc/config.cpp | 2 ++ src/tools/qdoc/config.h | 4 ++++ src/tools/qdoc/doc/qdoc-manual-qdocconf.qdoc | 7 +++++++ src/tools/qdoc/generator.cpp | 5 ++++- src/tools/qdoc/generator.h | 4 +++- src/tools/qdoc/htmlgenerator.cpp | 17 +++++++++-------- src/tools/qdoc/htmlgenerator.h | 2 ++ src/tools/qdoc/main.cpp | 4 ++-- 8 files changed, 33 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/tools/qdoc/config.cpp b/src/tools/qdoc/config.cpp index beb0bae291..ae6bbaf5da 100644 --- a/src/tools/qdoc/config.cpp +++ b/src/tools/qdoc/config.cpp @@ -53,6 +53,8 @@ QString ConfigStrings::BASE = QStringLiteral("base"); QString ConfigStrings::BASEDIR = QStringLiteral("basedir"); QString ConfigStrings::BUILDVERSION = QStringLiteral("buildversion"); QString ConfigStrings::CODEINDENT = QStringLiteral("codeindent"); +QString ConfigStrings::CODEPREFIX = QStringLiteral("codeprefix"); +QString ConfigStrings::CODESUFFIX = QStringLiteral("codesuffix"); QString ConfigStrings::CPPCLASSESPAGE = QStringLiteral("cppclassespage"); QString ConfigStrings::DEFINES = QStringLiteral("defines"); QString ConfigStrings::DEPENDS = QStringLiteral("depends"); diff --git a/src/tools/qdoc/config.h b/src/tools/qdoc/config.h index 8d6a124bd1..740568ca0c 100644 --- a/src/tools/qdoc/config.h +++ b/src/tools/qdoc/config.h @@ -165,6 +165,8 @@ struct ConfigStrings static QString BASEDIR; static QString BUILDVERSION; static QString CODEINDENT; + static QString CODEPREFIX; + static QString CODESUFFIX; static QString CPPCLASSESPAGE; static QString DEFINES; static QString DEPENDS; @@ -241,6 +243,8 @@ struct ConfigStrings #define CONFIG_BASEDIR ConfigStrings::BASEDIR #define CONFIG_BUILDVERSION ConfigStrings::BUILDVERSION #define CONFIG_CODEINDENT ConfigStrings::CODEINDENT +#define CONFIG_CODEPREFIX ConfigStrings::CODEPREFIX +#define CONFIG_CODESUFFIX ConfigStrings::CODESUFFIX #define CONFIG_CPPCLASSESPAGE ConfigStrings::CPPCLASSESPAGE #define CONFIG_DEFINES ConfigStrings::DEFINES #define CONFIG_DEPENDS ConfigStrings::DEPENDS diff --git a/src/tools/qdoc/doc/qdoc-manual-qdocconf.qdoc b/src/tools/qdoc/doc/qdoc-manual-qdocconf.qdoc index 2472b0f4fb..01a0e7f578 100644 --- a/src/tools/qdoc/doc/qdoc-manual-qdocconf.qdoc +++ b/src/tools/qdoc/doc/qdoc-manual-qdocconf.qdoc @@ -185,6 +185,13 @@ to adjust the appearance of certain types of HTML elements, this level of indentation is not always required. + \target codeprefix-variable + \target codesuffix-variable + \section1 codeprefix, codesuffix + + The \c codeprefix and \c codesuffix variables specify a pair of + strings that each code snippet is enclosed in. + \target defines-variable \section1 defines diff --git a/src/tools/qdoc/generator.cpp b/src/tools/qdoc/generator.cpp index dc731f0121..5037d95640 100644 --- a/src/tools/qdoc/generator.cpp +++ b/src/tools/qdoc/generator.cpp @@ -2115,11 +2115,14 @@ void Generator::terminateGenerator() Trims trailing whitespace off the \a string and returns the trimmed string. */ -QString Generator::trimmedTrailing(const QString& string) +QString Generator::trimmedTrailing(const QString& string, const QString &prefix, const QString &suffix) { QString trimmed = string; while (trimmed.length() > 0 && trimmed[trimmed.length() - 1].isSpace()) trimmed.truncate(trimmed.length() - 1); + + trimmed.append(suffix); + trimmed.prepend(prefix); return trimmed; } diff --git a/src/tools/qdoc/generator.h b/src/tools/qdoc/generator.h index 6c44cd189c..025f516986 100644 --- a/src/tools/qdoc/generator.h +++ b/src/tools/qdoc/generator.h @@ -139,7 +139,9 @@ protected: static QString outputSuffix(const Node* node); static void singularPlural(Text& text, const NodeList& nodes); static void supplementAlsoList(const Node *node, QList &alsoList); - static QString trimmedTrailing(const QString &string); + static QString trimmedTrailing(const QString &string, + const QString &prefix, + const QString &suffix); static QString sinceTitles[]; void initializeTextOutput(); diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp index 18d2af5810..eaa6de42ef 100644 --- a/src/tools/qdoc/htmlgenerator.cpp +++ b/src/tools/qdoc/htmlgenerator.cpp @@ -220,8 +220,9 @@ void HtmlGenerator::initializeGenerator(const Config &config) ++edition; } - // The following line was changed to fix QTBUG-27798 - //codeIndent = config.getInt(CONFIG_CODEINDENT); + codeIndent = config.getInt(CONFIG_CODEINDENT); // QTBUG-27798 + codePrefix = config.getString(CONFIG_CODEPREFIX); + codeSuffix = config.getString(CONFIG_CODESUFFIX); /* The help file write should be allocated once and only once @@ -584,23 +585,23 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark break; case Atom::Code: out() << "
"
-              << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()),relative))
+              << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()),relative), codePrefix, codeSuffix)
               << "
\n"; break; case Atom::Qml: out() << "
"
-              << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()),relative))
+              << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()),relative), codePrefix, codeSuffix)
               << "
\n"; break; case Atom::JavaScript: out() << "
"
-              << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()),relative))
+              << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()),relative), codePrefix, codeSuffix)
               << "
\n"; break; case Atom::CodeNew: out() << "

you can rewrite it as

\n" << "
"
-              << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()),relative))
+              << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()),relative), codePrefix, codeSuffix)
               << "
\n"; break; case Atom::CodeOld: @@ -608,7 +609,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark // fallthrough case Atom::CodeBad: out() << "
"
-              << trimmedTrailing(protectEnc(plainCode(indent(codeIndent,atom->string()))))
+              << trimmedTrailing(protectEnc(plainCode(indent(codeIndent,atom->string()))), codePrefix, codeSuffix)
               << "
\n"; break; case Atom::DivLeft: @@ -2370,7 +2371,7 @@ void HtmlGenerator::generateIncludes(const Aggregate *inner, CodeMarker *marker) out() << "
"
               << trimmedTrailing(highlightedCode(indent(codeIndent,
                                                         marker->markedUpIncludes(inner->includes())),
-                                                 inner))
+                                                 inner), codePrefix, codeSuffix)
               << "
"; } } diff --git a/src/tools/qdoc/htmlgenerator.h b/src/tools/qdoc/htmlgenerator.h index d46fc9ebee..bbb8f12e3e 100644 --- a/src/tools/qdoc/htmlgenerator.h +++ b/src/tools/qdoc/htmlgenerator.h @@ -233,6 +233,8 @@ private: QHash refMap; int codeIndent; + QString codePrefix; + QString codeSuffix; HelpProjectWriter *helpProjectWriter; bool inObsoleteLink; QRegExp funcLeftParen; diff --git a/src/tools/qdoc/main.cpp b/src/tools/qdoc/main.cpp index 3833cbb5dd..d6e00b4833 100644 --- a/src/tools/qdoc/main.cpp +++ b/src/tools/qdoc/main.cpp @@ -729,7 +729,7 @@ int main(int argc, char **argv) Location::startLoggingProgress(); /* - The default indent for code is 4. + The default indent for code is 0. The default value for false is 0. The default supported file extensions are cpp, h, qdoc and qml. The default language is c++. @@ -738,7 +738,7 @@ int main(int argc, char **argv) And those are all the default values for configuration variables. */ if (defaults.isEmpty()) { - defaults.insert(CONFIG_CODEINDENT, QLatin1String("4")); + defaults.insert(CONFIG_CODEINDENT, QLatin1String("0")); defaults.insert(CONFIG_FALSEHOODS, QLatin1String("0")); defaults.insert(CONFIG_FILEEXTENSIONS, QLatin1String("*.cpp *.h *.qdoc *.qml")); defaults.insert(CONFIG_LANGUAGE, QLatin1String("Cpp")); -- cgit v1.2.3 From 8a79e4d6784766d03aca50ebdfdf1c9175298326 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Fri, 4 Sep 2015 11:55:04 +0200 Subject: qdoc: Fix issue with findNodeForTarget() QDoc was searching for nodes using empty target string in some cases (when the string contained no '::' but genus was set to either QML or CPP). This resulted in random nodes being returned from findUnambiguousTarget(), causing mislinking without any warnings. Change-Id: I1bd434ec7470580cf5cb8083c2b74c37ef562473 Reviewed-by: Martin Smith --- src/tools/qdoc/tree.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/tools/qdoc/tree.cpp b/src/tools/qdoc/tree.cpp index d64903e61e..f8f88e6b91 100644 --- a/src/tools/qdoc/tree.cpp +++ b/src/tools/qdoc/tree.cpp @@ -721,12 +721,8 @@ const Node* Tree::findNodeForTarget(const QStringList& path, QString& ref) const { const Node* node = 0; - QString p; - if (path.size() > 1) - p = path.join(QString("::")); - else if ((genus == Node::DontCare) || (genus == Node::DOC)) { - p = path.at(0); - node = findDocumentNodeByTitle(p); + if ((genus == Node::DontCare) || (genus == Node::DOC)) { + node = findDocumentNodeByTitle(path.at(0)); if (node) { if (!target.isEmpty()) { ref = getRef(target, node); @@ -737,7 +733,8 @@ const Node* Tree::findNodeForTarget(const QStringList& path, return node; } } - node = findUnambiguousTarget(p, ref); + + node = findUnambiguousTarget(path.join(QStringLiteral("::")), ref); if (node) { if (!target.isEmpty()) { ref = getRef(target, node); -- cgit v1.2.3 From a5cc210decde2a1becaf5f0da41a8e6ae1a7f7ad Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Mon, 7 Sep 2015 10:25:46 +0200 Subject: Doc: Move selected \keywords to be \targets instead QDoc now handles \keyword slightly differently - it no longer generates a unique html anchor at the location it appears in. Instead, it'll inherit the anchor of the documentation item it appears in. Therefore, switch the \keyword commands that are used for linking to a subsection within a page to be \targets instead, so they'll get an anchor and not link to the top of the page. Change-Id: Iec6d3f0edbcfb0aec95e222615eca9de2b0e153e Reviewed-by: Martin Smith --- src/corelib/doc/src/containers.qdoc | 18 +++++++++--------- src/corelib/doc/src/implicit-sharing.qdoc | 6 +++--- src/corelib/io/qtextstream.cpp | 2 +- src/corelib/json/qjsonarray.cpp | 12 ++++++------ src/corelib/tools/qregexp.cpp | 2 +- src/widgets/doc/src/model-view-programming.qdoc | 2 +- src/widgets/doc/src/widgets-and-layouts/layout.qdoc | 2 +- .../doc/src/windows-and-dialogs/mainwindow.qdoc | 2 +- 8 files changed, 23 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/corelib/doc/src/containers.qdoc b/src/corelib/doc/src/containers.qdoc index f8d0d3eb05..0ae3817ac7 100644 --- a/src/corelib/doc/src/containers.qdoc +++ b/src/corelib/doc/src/containers.qdoc @@ -169,8 +169,8 @@ convenience, the containers are forward declared in \c . - \keyword assignable data type - \keyword assignable data types + \target assignable data type + \target assignable data types The values stored in the various containers can be of any \e{assignable data type}. To qualify, a type must provide a @@ -220,7 +220,7 @@ \codeline \snippet streaming/main.cpp 2 - \keyword default-constructed value + \target default-constructed value The documentation of certain container class functions refer to \e{default-constructed values}; for example, QVector @@ -546,7 +546,7 @@ The above example only shows a problem with QVector, but the problem exists for all the implicitly shared Qt containers. - \keyword foreach + \target foreach \section1 The foreach Keyword If you just want to iterate over all the items in a container @@ -655,11 +655,11 @@ To describe algorithmic complexity, we use the following terminology, based on the "big Oh" notation: - \keyword constant time - \keyword logarithmic time - \keyword linear time - \keyword linear-logarithmic time - \keyword quadratic time + \target constant time + \target logarithmic time + \target linear time + \target linear-logarithmic time + \target quadratic time \list \li \b{Constant time:} O(1). A function is said to run in constant diff --git a/src/corelib/doc/src/implicit-sharing.qdoc b/src/corelib/doc/src/implicit-sharing.qdoc index 57ebf55c17..d5a8e327ac 100644 --- a/src/corelib/doc/src/implicit-sharing.qdoc +++ b/src/corelib/doc/src/implicit-sharing.qdoc @@ -71,8 +71,8 @@ data. The shared data is deleted when the reference count becomes zero. - \keyword deep copy - \keyword shallow copy + \target deep copy + \target shallow copy When dealing with shared objects, there are two ways of copying an object. We usually speak about \e deep and \e shallow copies. A deep @@ -142,6 +142,6 @@ (QMap, QVector, etc.) while you use \l{STL-style iterators}{STL-style iterator}. See \l{Implicit sharing iterator problem}. - \keyword implicitly shared classes + \target implicitly shared classes \annotatedlist shared */ diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp index 8ad1c2852c..64038695e3 100644 --- a/src/corelib/io/qtextstream.cpp +++ b/src/corelib/io/qtextstream.cpp @@ -121,7 +121,7 @@ static const int QTEXTSTREAM_BUFFERSIZE = 16384; digits of the generated number. Some extra number formatting options are also available through setNumberFlags(). - \keyword QTextStream manipulators + \target QTextStream manipulators Like \c in the standard C++ library, QTextStream also defines several global manipulator functions: diff --git a/src/corelib/json/qjsonarray.cpp b/src/corelib/json/qjsonarray.cpp index dd27603d6d..bb33dbde74 100644 --- a/src/corelib/json/qjsonarray.cpp +++ b/src/corelib/json/qjsonarray.cpp @@ -533,8 +533,8 @@ bool QJsonArray::contains(const QJsonValue &value) const \a i must be a valid index position in the array (i.e., \c{0 <= i < size()}). - The return value is of type \keyword QJsonValueRef, a helper class for QJsonArray - and QJsonObject. When you get an object of type \keyword QJsonValueRef, you can + The return value is of type QJsonValueRef, a helper class for QJsonArray + and QJsonObject. When you get an object of type QJsonValueRef, you can use it as if it were a reference to a QJsonValue. If you assign to it, the assignment will apply to the character in the QJsonArray of QJsonObject from which you got the reference. @@ -739,8 +739,8 @@ bool QJsonArray::operator!=(const QJsonArray &other) const You can change the value of an item by using operator*() on the left side of an assignment. - The return value is of type \keyword QJsonValueRef, a helper class for QJsonArray - and QJsonObject. When you get an object of type \keyword QJsonValueRef, you can + The return value is of type QJsonValueRef, a helper class for QJsonArray + and QJsonObject. When you get an object of type QJsonValueRef, you can use it as if it were a reference to a QJsonValue. If you assign to it, the assignment will apply to the character in the QJsonArray of QJsonObject from which you got the reference. @@ -759,8 +759,8 @@ bool QJsonArray::operator!=(const QJsonArray &other) const This function is provided to make QJsonArray iterators behave like C++ pointers. - The return value is of type \keyword QJsonValueRef, a helper class for QJsonArray - and QJsonObject. When you get an object of type \keyword QJsonValueRef, you can + The return value is of type QJsonValueRef, a helper class for QJsonArray + and QJsonObject. When you get an object of type QJsonValueRef, you can use it as if it were a reference to a QJsonValue. If you assign to it, the assignment will apply to the character in the QJsonArray of QJsonObject from which you got the reference. diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp index c52e4b5a7c..82de664a56 100644 --- a/src/corelib/tools/qregexp.cpp +++ b/src/corelib/tools/qregexp.cpp @@ -492,7 +492,7 @@ int qFindString(const QChar *haystack, int haystackLen, int from, when it is followed by 'char'. \endtable - \keyword QRegExp wildcard matching + \target QRegExp wildcard matching \section1 Wildcard Matching Most command shells such as \e bash or \e cmd.exe support "file diff --git a/src/widgets/doc/src/model-view-programming.qdoc b/src/widgets/doc/src/model-view-programming.qdoc index 098bb39fe2..0032e77c6a 100644 --- a/src/widgets/doc/src/model-view-programming.qdoc +++ b/src/widgets/doc/src/model-view-programming.qdoc @@ -2301,7 +2301,7 @@ {fetchMore()} must be reimplemented as their default implementation returns false and does nothing. - \keyword Model/View Classes + \target Model/View Classes \section1 The Model/View Classes These classes use the model/view design pattern in which the diff --git a/src/widgets/doc/src/widgets-and-layouts/layout.qdoc b/src/widgets/doc/src/widgets-and-layouts/layout.qdoc index 3f093ab2d6..60281ce109 100644 --- a/src/widgets/doc/src/widgets-and-layouts/layout.qdoc +++ b/src/widgets/doc/src/widgets-and-layouts/layout.qdoc @@ -197,7 +197,7 @@ \section2 Stretch Factors - \keyword stretch factor + \target stretch factor Widgets are normally created without any stretch factor set. When they are laid out in a layout the widgets are given a share of space in accordance diff --git a/src/widgets/doc/src/windows-and-dialogs/mainwindow.qdoc b/src/widgets/doc/src/windows-and-dialogs/mainwindow.qdoc index 0e52944bb0..6e58fe4499 100644 --- a/src/widgets/doc/src/windows-and-dialogs/mainwindow.qdoc +++ b/src/widgets/doc/src/windows-and-dialogs/mainwindow.qdoc @@ -78,7 +78,7 @@ design ideas. Creating designs visually and reading the code generated by \l{uic} is a great way to learn Qt! - \keyword window geometry + \target window geometry \section1 Window Geometry QWidget provides several functions that deal with a widget's -- cgit v1.2.3 From ae50ee8adf178280d129c646fcbbe14db9272fd9 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Mon, 7 Sep 2015 14:16:43 +0300 Subject: Fix macro in qthread_win The dependent macro Q_OS_WINRT is not yet in scope when PCH is disabled, and it was missing parentheses anyway. Use WINAPI_FAMILY here instead, as it's just as good. Change-Id: Ib33904a9173f4f262c57ba1c27b37019f12827e7 Reviewed-by: Oliver Wolff --- src/corelib/thread/qthread_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index 57eeb10b7d..72f04ff7af 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -32,7 +32,7 @@ ****************************************************************************/ //#define WINVER 0x0500 -#if !defined Q_OS_WINRT && (_WIN32_WINNT < 0x0400) +#if !defined(WINAPI_FAMILY) && (_WIN32_WINNT < 0x0400) #define _WIN32_WINNT 0x0400 #endif -- cgit v1.2.3 From 4bbdfaa8ff5b6087b3edf4676ea87a4c0af3f700 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 4 Sep 2015 16:20:54 +0200 Subject: Fix some qdoc warnings. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qtbase/src/corelib/io/qdebug.cpp:698: warning: Class QDebugStateSaver has no \inmodule command; using project name by default: QtCore qtbase/src/gui/opengl/qopenglframebufferobject.cpp:1138: warning: Can't link to 'takeTextures()' qtbase/src/gui/opengl/qopenglframebufferobject.cpp:1159: warning: Can't link to 'takeTextures()' qtbase/src/gui/opengl/qopenglframebufferobject.cpp:953: warning: No such parameter 'height' in QOpenGLFramebufferObject::addColorAttachment() qtbase/src/gui/opengl/qopenglframebufferobject.cpp:953: warning: No such parameter 'width' in QOpenGLFramebufferObject::addColorAttachment() qtbase/src/gui/opengl/qopenglframebufferobject.cpp:953: warning: Undocumented parameter 'size' in QOpenGLFramebufferObject::addColorAttachment() qtbase/src/gui/painting/qpaintdevice.qdoc:80: warning: Undocumented enum item 'PdmDevicePixelRatioScaled' in QPaintDevice::PaintDeviceMetric qtbase/src/testlib/qbenchmarkmetric.cpp:154: warning: Invalid use of '\relates' (already a member of 'QTest') qtbase/src/testlib/qbenchmarkmetric.cpp:81: warning: Invalid use of '\relates' (already a member of 'QTest') qtbase/src/widgets/dialogs/qdialog.cpp:152: warning: Can't link to 'QCloseEvent::ignore()' qtbase/src/widgets/dialogs/qdialog.cpp:557: warning: Can't link to 'QApplication::quit()' qtbase/src/widgets/kernel/qwidget.cpp:8326: warning: Can't link to 'QCloseEvent::accept()' qtbase/src/widgets/kernel/qwidget.cpp:8326: warning: Can't link to 'QCloseEvent::ignore()' qtbase/src/widgets/kernel/qwidget.cpp:9300: warning: Can't link to 'QWheelEvent::accept()' qtbase/src/widgets/kernel/qwidget.cpp:9300: warning: Can't link to 'QWheelEvent::ignore()' qtbase/src/widgets/kernel/qwidget.cpp:9321: warning: Can't link to 'QTabletEvent::accept()' qtbase/src/widgets/kernel/qwidget.cpp:9321: warning: Can't link to 'QTabletEvent::ignore()' qtbase/src/widgets/kernel/qwidget.cpp:9373: warning: Can't link to 'QKeyEvent::ignore()' Change-Id: I97ae85398181645c1054c303e5c8a87deb619409 Reviewed-by: Martin Smith Reviewed-by: Topi Reiniö --- src/corelib/io/qdebug.cpp | 2 +- src/gui/opengl/qopenglframebufferobject.cpp | 8 ++++---- src/gui/painting/qpaintdevice.qdoc | 8 +++++++- src/testlib/qbenchmarkmetric.cpp | 2 -- src/widgets/dialogs/qdialog.cpp | 4 ++-- src/widgets/kernel/qwidget.cpp | 14 +++++++------- src/widgets/widgets/qmenubar.cpp | 2 +- 7 files changed, 22 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp index 54a705b72b..13eccce9da 100644 --- a/src/corelib/io/qdebug.cpp +++ b/src/corelib/io/qdebug.cpp @@ -697,7 +697,7 @@ QDebug &QDebug::resetFormat() /*! \class QDebugStateSaver - + \inmodule QtCore \brief Convenience class for custom QDebug operators Saves the settings used by QDebug, and restores them upon destruction, diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp index 3596591cf6..0e162713ce 100644 --- a/src/gui/opengl/qopenglframebufferobject.cpp +++ b/src/gui/opengl/qopenglframebufferobject.cpp @@ -951,8 +951,8 @@ QOpenGLFramebufferObject::~QOpenGLFramebufferObject() } /*! - Creates and attaches an additional texture or renderbuffer of size \a width - and \a height. + Creates and attaches an additional texture or renderbuffer of \a size width + and height. There is always an attachment at GL_COLOR_ATTACHMENT0. Call this function to set up additional attachments at GL_COLOR_ATTACHMENT1, @@ -1142,7 +1142,7 @@ GLuint QOpenGLFramebufferObject::texture() const \since 5.6 - \sa takeTextures(), texture() + \sa takeTexture(), texture() */ QVector QOpenGLFramebufferObject::textures() const { @@ -1172,7 +1172,7 @@ QVector QOpenGLFramebufferObject::textures() const \since 5.3 - \sa texture(), bind(), release(), takeTextures() + \sa texture(), bind(), release() */ GLuint QOpenGLFramebufferObject::takeTexture() { diff --git a/src/gui/painting/qpaintdevice.qdoc b/src/gui/painting/qpaintdevice.qdoc index a83acdd21a..ef5deb154d 100644 --- a/src/gui/painting/qpaintdevice.qdoc +++ b/src/gui/painting/qpaintdevice.qdoc @@ -118,7 +118,13 @@ values are 1 for normal-dpi displays and 2 for high-dpi "retina" displays. - \sa metric() + \value PdmDevicePixelRatioScaled The scaled device pixel ratio for the device. + This is identical to PdmDevicePixelRatio, except that the value is scaled by a + constant factor in order to support paint devices with fractional scale factors. + The constant scaling factor used is devicePixelRatioFScale(). This enum value + has been introduced in Qt 5.6. + + \sa metric(), devicePixelRatioF() */ /*! diff --git a/src/testlib/qbenchmarkmetric.cpp b/src/testlib/qbenchmarkmetric.cpp index ee212a49d0..f6d2c20a4a 100644 --- a/src/testlib/qbenchmarkmetric.cpp +++ b/src/testlib/qbenchmarkmetric.cpp @@ -79,7 +79,6 @@ */ /*! - \relates QTest \since 4.7 Returns the enum value \a metric as a character string. */ @@ -152,7 +151,6 @@ const char * QTest::benchmarkMetricName(QBenchmarkMetric metric) }; /*! - \relates QTest \since 4.7 Retuns the units of measure for the specified \a metric. */ diff --git a/src/widgets/dialogs/qdialog.cpp b/src/widgets/dialogs/qdialog.cpp index 054c220b84..d04241fee0 100644 --- a/src/widgets/dialogs/qdialog.cpp +++ b/src/widgets/dialogs/qdialog.cpp @@ -243,7 +243,7 @@ void QDialogPrivate::deletePlatformHelper() \section1 Escape Key If the user presses the Esc key in a dialog, QDialog::reject() - will be called. This will cause the window to close: The \l{QCloseEvent}{close event} cannot be \l{QCloseEvent::ignore()}{ignored}. + will be called. This will cause the window to close: The \l{QCloseEvent}{close event} cannot be \l{QEvent::ignore()}{ignored}. \section1 Extensibility @@ -565,7 +565,7 @@ int QDialog::exec() last window closed, the QApplication::lastWindowClosed() signal is emitted. - \sa accept(), reject(), QApplication::activeWindow(), QApplication::quit() + \sa accept(), reject(), QApplication::activeWindow(), QCoreApplication::quit() */ void QDialog::done(int r) diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 32c52ade56..b9628cfa1e 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -8328,8 +8328,8 @@ bool QWidgetPrivate::close_helper(CloseMode mode) otherwise returns \c false. First it sends the widget a QCloseEvent. The widget is - \l{hide()}{hidden} if it \l{QCloseEvent::accept()}{accepts} - the close event. If it \l{QCloseEvent::ignore()}{ignores} + \l{hide()}{hidden} if it \l{QEvent::accept()}{accepts} + the close event. If it \l{QEvent::ignore()}{ignores} the event, nothing happens. The default implementation of QWidget::closeEvent() accepts the close event. @@ -9302,12 +9302,12 @@ void QWidget::mouseDoubleClickEvent(QMouseEvent *event) subclass to receive wheel events for the widget. If you reimplement this handler, it is very important that you - \l{QWheelEvent}{ignore()} the event if you do not handle + \l{QEvent}{ignore()} the event if you do not handle it, so that the widget's parent can interpret it. The default implementation ignores the event. - \sa QWheelEvent::ignore(), QWheelEvent::accept(), event(), + \sa QEvent::ignore(), QEvent::accept(), event(), QWheelEvent */ @@ -9323,12 +9323,12 @@ void QWidget::wheelEvent(QWheelEvent *event) subclass to receive tablet events for the widget. If you reimplement this handler, it is very important that you - \l{QTabletEvent}{ignore()} the event if you do not handle + \l{QEvent}{ignore()} the event if you do not handle it, so that the widget's parent can interpret it. The default implementation ignores the event. - \sa QTabletEvent::ignore(), QTabletEvent::accept(), event(), + \sa QEvent::ignore(), QEvent::accept(), event(), QTabletEvent */ @@ -9388,7 +9388,7 @@ void QWidget::keyPressEvent(QKeyEvent *event) need to call QKeyEvent::accept() - just do not call the base class implementation if you act upon the key. - \sa keyPressEvent(), QKeyEvent::ignore(), setFocusPolicy(), + \sa keyPressEvent(), QEvent::ignore(), setFocusPolicy(), focusInEvent(), focusOutEvent(), event(), QKeyEvent */ diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp index 91775e3862..d382131075 100644 --- a/src/widgets/widgets/qmenubar.cpp +++ b/src/widgets/widgets/qmenubar.cpp @@ -638,7 +638,7 @@ void QMenuBar::initStyleOption(QStyleOptionMenuItem *option, const QAction *acti \row \li quit or exit \li Application Menu | Quit \li If this entry is not found a default Quit item will be - created to call QApplication::quit() + created to call QCoreApplication::quit() \endtable You can override this behavior by using the QAction::menuRole() -- cgit v1.2.3 From bb1d8c0edaf463ceaec931c03ec829eaff733d69 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 4 Sep 2015 14:54:07 +0200 Subject: QMacStyle: Call subElementRect() on proxy style for SE_TabBarTabText MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When drawing the tab bar text shadow, we call drawControl() on the proxy style, so we should do the same for subElementRect(). Change-Id: Ic3477d4c053d9cce42abd3f93a4e1bf265f025ce Task-number: QTBUG-41600 Reviewed-by: Morten Johan Sørvig --- src/widgets/styles/qmacstyle_mac.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index 3219952f7f..f828583d8c 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -4266,7 +4266,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter QPalette np = tab->palette; np.setColor(QPalette::WindowText, shadowColor); - QRect nr = subElementRect(SE_TabBarTabText, opt, w); + QRect nr = proxy()->subElementRect(SE_TabBarTabText, opt, w); nr.moveTop(-1); int alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextHideMnemonic; proxy()->drawItemText(p, nr, alignment, np, tab->state & State_Enabled, -- cgit v1.2.3 From 900e459dbf5291635bd98837abfd0fe05537f582 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 4 Sep 2015 17:53:11 +0200 Subject: QMacStyle: Fix splitter handle background on 10.10 or later Also refactor the multiple usages of the same OS X version check variable. Change-Id: I16e4863353670200f8f44478fa18af9a4e875b5f Task-number: QTBUG-43425 Reviewed-by: Jake Petroules --- src/widgets/styles/qmacstyle_mac.mm | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index f828583d8c..fe8ea837be 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -1960,7 +1960,7 @@ void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD const bool button = opt->type == QStyleOption::SO_Button; const bool viewItem = opt->type == QStyleOption::SO_ViewItem; const bool pressed = bdi->state == kThemeStatePressed; - const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion > QSysInfo::MV_10_9; + const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10; if (button && pressed) { if (bdi->kind == kThemePushButton) { @@ -3601,6 +3601,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter QWindow *window = w && w->window() ? w->window()->windowHandle() : QStyleHelper::styleObjectWindow(opt->styleObject); const_cast(d)->resolveCurrentNSView(window); + const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10; switch (ce) { case CE_HeaderSection: if (const QStyleOptionHeader *header = qstyleoption_cast(opt)) { @@ -3812,13 +3813,12 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter // No default button pulsating animation on Yosemite, // so we have to do few things differently. - const bool yosemiteOrLater = QSysInfo::QSysInfo::MacintoshVersion > QSysInfo::MV_10_9; // a focused auto-default button within an active window // takes precedence over a normal default button if (btn->features & QStyleOptionButton::AutoDefaultButton && opt->state & State_Active && opt->state & State_HasFocus) { - if (yosemiteOrLater) + if (usingYosemiteOrLater) d->autoDefaultButton = opt->styleObject; else d->setAutoDefaultButton(opt->styleObject); @@ -3829,7 +3829,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter if (!d->autoDefaultButton) { if (btn->features & QStyleOptionButton::DefaultButton && opt->state & State_Active) { d->defaultButton = opt->styleObject; - if (!yosemiteOrLater && !d->animation(opt->styleObject)) + if (!usingYosemiteOrLater && !d->animation(opt->styleObject)) d->startAnimation(new QStyleAnimation(opt->styleObject)); } else if (d->defaultButton == opt->styleObject) { if (QStyleAnimation *animation = d->animation(opt->styleObject)) { @@ -3851,7 +3851,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter HIThemeButtonDrawInfo bdi; d->initHIThemePushButton(btn, w, tds, &bdi); - if (yosemiteOrLater) { + if (usingYosemiteOrLater) { if (!hasMenu) { // HITheme is not drawing a nice focus frame around buttons. // We'll do it ourselves further down. @@ -3904,7 +3904,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter newRect.size.width -= QMacStylePrivate::PushButtonRightOffset - 4; } - if (hasMenu && yosemiteOrLater && bdi.kind != kThemeBevelButton) { + if (hasMenu && usingYosemiteOrLater && bdi.kind != kThemeBevelButton) { QCocoaWidget cw = cocoaWidgetFromHIThemeButtonKind(bdi.kind); cw.first = QCocoaPullDownButton; NSPopUpButton *pdb = (NSPopUpButton *)d->cocoaControl(cw); @@ -3918,7 +3918,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter else HIThemeDrawButton(&newRect, &bdi, cg, kHIThemeOrientationNormal, 0); - if (yosemiteOrLater && btn->state & State_HasFocus) { + if (usingYosemiteOrLater && btn->state & State_HasFocus) { CGRect focusRect = newRect; if (bdi.kind == kThemePushButton) focusRect.size.height += 1; // Another thing HITheme and Cocoa seem to disagree about. @@ -3949,7 +3949,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter qt_drawFocusRingOnPath(cg, pushButtonFocusRingPath); } - if (hasMenu && (!yosemiteOrLater || bdi.kind == kThemeBevelButton)) { + if (hasMenu && (!usingYosemiteOrLater || bdi.kind == kThemeBevelButton)) { int mbi = proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, w); QRect ir = btn->rect; int arrowXOffset = bdi.kind == kThemePushButton ? 6 : @@ -4121,8 +4121,6 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter } } - bool usingYosemiteOrLater = QSysInfo::MacintoshVersion > QSysInfo::MV_10_9; - HIThemeTabDrawInfo tdi; tdi.version = 1; tdi.style = kThemeTabNonFront; @@ -4234,7 +4232,6 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter ThemeTabDirection ttd = getTabDirection(myTab.shape); bool verticalTabs = ttd == kThemeTabWest || ttd == kThemeTabEast; bool selected = (myTab.state & QStyle::State_Selected); - bool usingYosemiteOrLater = QSysInfo::MacintoshVersion > QSysInfo::MV_10_9; if (selected && !myTab.documentMode && (!usingYosemiteOrLater || myTab.state & State_Active)) @@ -4682,7 +4679,6 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter tdi.value = pb->progress; tdi.attributes = vertical ? 0 : kThemeTrackHorizontal; - const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion > QSysInfo::MV_10_9; if (isIndeterminate || (tdi.value < tdi.max && !usingYosemiteOrLater)) { if (QProgressStyleAnimation *animation = qobject_cast(d->animation(opt->styleObject))) tdi.trackInfo.progress.phase = animation->animationStep(); @@ -4765,8 +4761,8 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter HIThemeSplitterDrawInfo sdi; sdi.version = qt_mac_hitheme_version; sdi.state = tds; - sdi.adornment = qt_mac_is_metal(w) ? kHIThemeSplitterAdornmentMetal - : kHIThemeSplitterAdornmentNone; + sdi.adornment = qt_mac_is_metal(w) || usingYosemiteOrLater ? + kHIThemeSplitterAdornmentMetal : kHIThemeSplitterAdornmentNone; HIRect hirect = qt_hirectForQRect(opt->rect); HIThemeDrawPaneSplitter(&hirect, &sdi, cg, kHIThemeOrientationNormal); } else { @@ -5301,6 +5297,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex QWindow *window = widget && widget->window() ? widget->window()->windowHandle() : QStyleHelper::styleObjectWindow(opt->styleObject); const_cast(d)->resolveCurrentNSView(window); + const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10; switch (cc) { case CC_Slider: case CC_ScrollBar: @@ -5378,7 +5375,6 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex tdi.attributes |= kThemeTrackHideTrack; } - const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion > QSysInfo::MV_10_9; const bool isHorizontal = slider->orientation == Qt::Horizontal; if (cc == CC_ScrollBar && proxy()->styleHint(SH_ScrollBar_Transient, opt, widget)) { @@ -5754,7 +5750,6 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex break; case CC_ComboBox: if (const QStyleOptionComboBox *combo = qstyleoption_cast(opt)){ - const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion > QSysInfo::MV_10_9; HIThemeButtonDrawInfo bdi; d->initComboboxBdi(combo, &bdi, widget, tds); HIRect rect = qt_hirectForQRect(combo->rect); -- cgit v1.2.3 From fd2067b67bc2da7d7ee53ca2cadc9f6b81971fc0 Mon Sep 17 00:00:00 2001 From: Sze Howe Koh Date: Sun, 30 Aug 2015 09:17:02 +0800 Subject: Doc: Make QSignalBlocker more discoverable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QSignalBlocker is a wrapper for QObject::blockSignals(). Let's add a cross-reference. Change-Id: I3e7b7530eef165439965e4f83da308d9384209f3 Reviewed-by: Topi Reiniö --- src/corelib/kernel/qobject.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index b624c3880e..7f95b6a591 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1382,7 +1382,7 @@ bool QObject::eventFilter(QObject * /* watched */, QEvent * /* event */) Signals are not blocked by default. - \sa blockSignals() + \sa blockSignals(), QSignalBlocker */ /*! @@ -1397,7 +1397,7 @@ bool QObject::eventFilter(QObject * /* watched */, QEvent * /* event */) Signals emitted while being blocked are not buffered. - \sa signalsBlocked() + \sa signalsBlocked(), QSignalBlocker */ bool QObject::blockSignals(bool block) Q_DECL_NOTHROW -- cgit v1.2.3 From 8cbaea441a8c9adea6ba804b76bf3bd1e79f77b7 Mon Sep 17 00:00:00 2001 From: Aleix Pol Date: Fri, 4 Sep 2015 16:52:04 +0200 Subject: Notify when the primary screen changes Makes it possible to notify that the QGuiApplication::primaryScreen has changed. XCB backend adopts the new API, as it was accessing QGuiApplication private API directly. Change-Id: Icde05c44138265f865fa42d2cd6974c552fdc5e2 Task-number: QTBUG-38404 Task-number: QTBUG-40659 Reviewed-by: Frederik Gladhorn Reviewed-by: Shawn Rutledge --- src/gui/kernel/qguiapplication.cpp | 12 +++++++++ src/gui/kernel/qguiapplication.h | 2 ++ src/gui/kernel/qplatformintegration.cpp | 39 +++++++++++++++++++++++++++- src/gui/kernel/qplatformintegration.h | 4 +++ src/gui/kernel/qplatformscreen.cpp | 2 +- src/plugins/platforms/xcb/qxcbconnection.cpp | 9 +++---- src/widgets/kernel/qdesktopwidget.cpp | 1 + src/widgets/kernel/qdesktopwidget.h | 1 + src/widgets/kernel/qdesktopwidget.qdoc | 14 ++++++++++ 9 files changed, 76 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index d0aab734dd..87bd7ea5de 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -921,6 +921,18 @@ QList QGuiApplication::screens() \since 5.4 */ +/*! + \fn void QGuiApplication::primaryScreenChanged(QScreen *screen) + + This signal is emitted whenever the primary \a screen changes. This way + applications can keep track of the primaryScreen and react if there is a + new primary screen. + + \sa primaryScreen + + \since 5.6 +*/ + /*! Returns the highest screen device pixel ratio found on diff --git a/src/gui/kernel/qguiapplication.h b/src/gui/kernel/qguiapplication.h index c89268d8d4..d995387d66 100644 --- a/src/gui/kernel/qguiapplication.h +++ b/src/gui/kernel/qguiapplication.h @@ -70,6 +70,7 @@ class Q_GUI_EXPORT QGuiApplication : public QCoreApplication Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged) Q_PROPERTY(QString platformName READ platformName STORED false) Q_PROPERTY(bool quitOnLastWindowClosed READ quitOnLastWindowClosed WRITE setQuitOnLastWindowClosed) + Q_PROPERTY(QScreen *primaryScreen READ primaryScreen NOTIFY primaryScreenChanged STORED false) public: #ifdef Q_QDOC @@ -158,6 +159,7 @@ Q_SIGNALS: void fontDatabaseChanged(); void screenAdded(QScreen *screen); void screenRemoved(QScreen *screen); + void primaryScreenChanged(QScreen *screen); void lastWindowClosed(); void focusObjectChanged(QObject *focusObject); void focusWindowChanged(QWindow *focusWindow); diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp index e935907a62..457a420148 100644 --- a/src/gui/kernel/qplatformintegration.cpp +++ b/src/gui/kernel/qplatformintegration.cpp @@ -456,6 +456,24 @@ void QPlatformIntegration::screenAdded(QPlatformScreen *ps, bool isPrimary) QGuiApplicationPrivate::screen_list.append(screen); } emit qGuiApp->screenAdded(screen); + + if (isPrimary) + emit qGuiApp->primaryScreenChanged(screen); +} + +/*! + Just removes the screen, call destroyScreen instead. + + \sa destroyScreen() +*/ + +void QPlatformIntegration::removeScreen(QScreen *screen) +{ + const bool wasPrimary = (!QGuiApplicationPrivate::screen_list.isEmpty() && QGuiApplicationPrivate::screen_list[0] == screen); + QGuiApplicationPrivate::screen_list.removeOne(screen); + + if (wasPrimary && qGuiApp && !QGuiApplicationPrivate::screen_list.isEmpty()) + emit qGuiApp->primaryScreenChanged(QGuiApplicationPrivate::screen_list[0]); } /*! @@ -469,11 +487,30 @@ void QPlatformIntegration::screenAdded(QPlatformScreen *ps, bool isPrimary) void QPlatformIntegration::destroyScreen(QPlatformScreen *screen) { QScreen *qScreen = screen->screen(); - QGuiApplicationPrivate::screen_list.removeOne(qScreen); + removeScreen(qScreen); delete qScreen; delete screen; } +/*! + Should be called whenever the primary screen changes. + + When the screen specified as primary changes, this method will notify + QGuiApplication and emit the QGuiApplication::primaryScreenChanged signal. + */ + +void QPlatformIntegration::setPrimaryScreen(QPlatformScreen *newPrimary) +{ + QScreen* newPrimaryScreen = newPrimary->screen(); + int idx = QGuiApplicationPrivate::screen_list.indexOf(newPrimaryScreen); + Q_ASSERT(idx >= 0); + if (idx == 0) + return; + + QGuiApplicationPrivate::screen_list.swap(0, idx); + emit qGuiApp->primaryScreenChanged(newPrimaryScreen); +} + QStringList QPlatformIntegration::themeNames() const { return QStringList(); diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h index 2aa502b3d2..00c50a9861 100644 --- a/src/gui/kernel/qplatformintegration.h +++ b/src/gui/kernel/qplatformintegration.h @@ -172,9 +172,13 @@ public: virtual QOpenGLContext::OpenGLModuleType openGLModuleType(); #endif virtual void setApplicationIcon(const QIcon &icon) const; + + void removeScreen(QScreen *screen); + protected: void screenAdded(QPlatformScreen *screen, bool isPrimary = false); void destroyScreen(QPlatformScreen *screen); + void setPrimaryScreen(QPlatformScreen *newPrimary); }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qplatformscreen.cpp b/src/gui/kernel/qplatformscreen.cpp index 2fb53fe16b..d1d8eba697 100644 --- a/src/gui/kernel/qplatformscreen.cpp +++ b/src/gui/kernel/qplatformscreen.cpp @@ -56,7 +56,7 @@ QPlatformScreen::~QPlatformScreen() Q_D(QPlatformScreen); if (d->screen) { qWarning("Manually deleting a QPlatformScreen. Call QPlatformIntegration::destroyScreen instead."); - QGuiApplicationPrivate::screen_list.removeOne(d->screen); + QGuiApplicationPrivate::platformIntegration()->removeScreen(d->screen); delete d->screen; } } diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index e612cff9a3..5fd0df54d8 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -305,13 +305,10 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event) screen->updateRefreshRate(output.mode); // If the screen became primary, reshuffle the order in QGuiApplicationPrivate - // TODO: add a proper mechanism for updating primary screen if (!wasPrimary && screen->isPrimary()) { - QScreen *realScreen = static_cast(screen)->screen(); - QGuiApplicationPrivate::screen_list.removeOne(realScreen); - QGuiApplicationPrivate::screen_list.prepend(realScreen); - m_screens.removeOne(screen); - m_screens.prepend(screen); + const int idx = m_screens.indexOf(screen); + m_screens.swap(0, idx); + QXcbIntegration::instance()->setPrimaryScreen(screen); } qCDebug(lcQpaScreen) << "output has changed" << screen; } diff --git a/src/widgets/kernel/qdesktopwidget.cpp b/src/widgets/kernel/qdesktopwidget.cpp index 94716025b9..b88b3cc61d 100644 --- a/src/widgets/kernel/qdesktopwidget.cpp +++ b/src/widgets/kernel/qdesktopwidget.cpp @@ -134,6 +134,7 @@ QDesktopWidget::QDesktopWidget() setObjectName(QLatin1String("desktop")); d->_q_updateScreens(); connect(qApp, SIGNAL(screenAdded(QScreen*)), this, SLOT(_q_updateScreens())); + connect(qApp, SIGNAL(primaryScreenChanged(QScreen*)), this, SIGNAL(primaryScreenChanged())); } QDesktopWidget::~QDesktopWidget() diff --git a/src/widgets/kernel/qdesktopwidget.h b/src/widgets/kernel/qdesktopwidget.h index c0cc4f1b81..f5f7d69887 100644 --- a/src/widgets/kernel/qdesktopwidget.h +++ b/src/widgets/kernel/qdesktopwidget.h @@ -77,6 +77,7 @@ Q_SIGNALS: void resized(int); void workAreaResized(int); void screenCountChanged(int); + void primaryScreenChanged(); protected: void resizeEvent(QResizeEvent *e) Q_DECL_OVERRIDE; diff --git a/src/widgets/kernel/qdesktopwidget.qdoc b/src/widgets/kernel/qdesktopwidget.qdoc index 31a99f1acb..d1a6ecabd6 100644 --- a/src/widgets/kernel/qdesktopwidget.qdoc +++ b/src/widgets/kernel/qdesktopwidget.qdoc @@ -271,3 +271,17 @@ \sa screenCount */ + + +/*! + \fn void QDesktopWidget::primaryScreenChanged() + + \since 5.6 + + \brief This signal is emitted whenever the primary screen changes. + + \note This doesn't mean the QDesktopWidget::primaryScreen index will + necessarily be different, but now it will refer to the new primary screen. + + \sa primaryScreen, screenGeometry() +*/ -- cgit v1.2.3 From c22eceb7d097ebfe253509d001103a9a0a4a1171 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 3 Sep 2015 15:20:47 +0200 Subject: Deduplicate some code in QWindowSystemInterface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 66050f2a changed a few exported functions used by testlib so that they sent events synchronously, by calling QGuiApp processWindowSystemEvent directly. The same effect can be achieved by setting setSynchronousWindowSystemEvents to true before calling the normal QPA functions. Change-Id: Id4c67f7d315a5607885c738ca54516434125b24e Reviewed-by: Lars Knoll Reviewed-by: Tor Arne Vestbø --- src/gui/kernel/qwindowsysteminterface.cpp | 79 +++++++++++++++---------------- 1 file changed, 38 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 3500792f4e..78bce0f0e3 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -901,26 +901,23 @@ Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QWindowSystemInterface::TouchPo } #endif +// The following functions are used by testlib, and need to be synchronous to avoid +// race conditions with plugins delivering native events from secondary threads. + Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *w, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods, int timestamp) { - QWindowSystemInterfacePrivate::MouseEvent e(w, timestamp, local, global, b, mods, Qt::MouseEventNotSynthesized); - QGuiApplicationPrivate::processWindowSystemEvent(&e); + bool wasSynchronous = QWindowSystemInterfacePrivate::synchronousWindowSystemEvents; + QWindowSystemInterface::setSynchronousWindowSystemEvents(true); + QWindowSystemInterface::handleMouseEvent(w, timestamp, local, global, b, mods); + QWindowSystemInterface::setSynchronousWindowSystemEvents(wasSynchronous); } Q_GUI_EXPORT void qt_handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1) { - unsigned long timestamp = QWindowSystemInterfacePrivate::eventTime.elapsed(); - - // This is special handling needed for OS X which eventually will call sendEvent(), on other platforms - // this might not be safe, e.g., on Android. See: QGuiApplicationPrivate::processKeyEvent() for - // shortcut overriding on other platforms. -#if defined(Q_OS_OSX) - if (t == QEvent::KeyPress && QWindowSystemInterface::tryHandleShortcutEvent(w, timestamp, k, mods, text)) - return; -#endif // Q_OS_OSX - - QWindowSystemInterfacePrivate::KeyEvent e(w, timestamp, t, k, mods, text, autorep, count); - QGuiApplicationPrivate::processWindowSystemEvent(&e); + bool wasSynchronous = QWindowSystemInterfacePrivate::synchronousWindowSystemEvents; + QWindowSystemInterface::setSynchronousWindowSystemEvents(true); + QWindowSystemInterface::handleKeyEvent(w, t, k, mods, text, autorep, count); + QWindowSystemInterface::setSynchronousWindowSystemEvents(wasSynchronous); } Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1) @@ -928,37 +925,37 @@ Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int return QWindowSystemInterface::tryHandleShortcutEventToObject(o, timestamp, k, mods, text, autorep, count); } -Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *w, QTouchDevice *device, - const QList &points, - Qt::KeyboardModifiers mods = Qt::NoModifier) +static QWindowSystemInterface::TouchPoint touchPoint(const QTouchEvent::TouchPoint& pt) { - unsigned long timestamp = QWindowSystemInterfacePrivate::eventTime.elapsed(); - - if (!points.size()) // Touch events must have at least one point - return; - - if (!QTouchDevicePrivate::isRegistered(device)) // Disallow passing bogus, non-registered devices. - return; - - QEvent::Type type; - Qt::TouchPointStates states; + QWindowSystemInterface::TouchPoint p; + p.id = pt.id(); + p.flags = pt.flags(); + p.normalPosition = pt.normalizedPos(); + p.area = pt.screenRect(); + p.pressure = pt.pressure(); + p.state = pt.state(); + p.velocity = pt.velocity(); + p.rawPositions = pt.rawScreenPositions(); + return p; +} +static QList touchPointList(const QList& pointList) +{ + QList newList; - QList::const_iterator point = points.constBegin(); - QList::const_iterator end = points.constEnd(); - while (point != end) { - states |= point->state(); - ++point; - } + Q_FOREACH (QTouchEvent::TouchPoint p, pointList) + newList.append(touchPoint(p)); - // Determine the event type based on the combined point states. - type = QEvent::TouchUpdate; - if (states == Qt::TouchPointPressed) - type = QEvent::TouchBegin; - else if (states == Qt::TouchPointReleased) - type = QEvent::TouchEnd; + return newList; +} - QWindowSystemInterfacePrivate::TouchEvent e(w, timestamp, type, device, points, mods); - QGuiApplicationPrivate::processWindowSystemEvent(&e); +Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *w, QTouchDevice *device, + const QList &points, + Qt::KeyboardModifiers mods = Qt::NoModifier) +{ + bool wasSynchronous = QWindowSystemInterfacePrivate::synchronousWindowSystemEvents; + QWindowSystemInterface::setSynchronousWindowSystemEvents(true); + QWindowSystemInterface::handleTouchEvent(w, device, touchPointList(points), mods); + QWindowSystemInterface::setSynchronousWindowSystemEvents(wasSynchronous); } QWindowSystemEventHandler::~QWindowSystemEventHandler() -- cgit v1.2.3 From b253f404e8e78c6a29778733c389ea22d2681b03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 1 Sep 2015 18:54:05 +0200 Subject: iOS: Restore mirror mode using [UIScreen mainScreen] instead of nil MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The latter had the same effect, but is an invalid assignment for a value that is documented to be non-nil. Change-Id: Ice00482138481556ad839bc3721e577dafcb26fe Reviewed-by: Richard Moe Gustavsen Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiosviewcontroller.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm index be89521c04..67b33ce235 100644 --- a/src/plugins/platforms/ios/qiosviewcontroller.mm +++ b/src/plugins/platforms/ios/qiosviewcontroller.mm @@ -143,7 +143,7 @@ if (uiWindow.screen != [UIScreen mainScreen] && self.subviews.count == 1) { // Removing the last view of an external screen, go back to mirror mode - uiWindow.screen = nil; + uiWindow.screen = [UIScreen mainScreen]; uiWindow.hidden = YES; } } -- cgit v1.2.3 From 35793cea28c4bd1d6d8fbae884d9ae3c19745c61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 25 Jun 2015 14:26:06 +0200 Subject: CoreText: Respect Qt::AA_Use96Dpi flag when creating CT fonts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pixel size passed into QCoreTextFontDatabase::fontEngine() has already been scaled to take the destination DPI into account. In the normal case the destination DPI is the same as the screen's logical DPI, 72, and we end up with the pixel size being equal to the point size. But when the Qt::AA_Use96Dpi flag has been set, e.g. when running tests, the pixel size is larger than the point size, and we need to pass this information to CoreText, otherwise we end up with clipped text rendering. This was evident when looking at the lancelot baselines for OS X, which are produced using QTestLib, and hence run with Qt::AA_Use96Dpi set. Change-Id: Ib0f720bb318b2dc437172a6b712675e3dfe3f7ac Reviewed-by: Eskil Abrahamsen Blomfeldt Reviewed-by: Tor Arne Vestbø --- .../fontdatabases/mac/qcoretextfontdatabase.mm | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index 1f000421cc..357228db14 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -45,7 +45,6 @@ #include "qcoretextfontdatabase_p.h" #include "qfontengine_coretext_p.h" #include -#include #include #ifndef QT_NO_FREETYPE #include @@ -399,17 +398,14 @@ QFontEngine *QCoreTextFontDatabase::fontEngine(const QFontDef &f, void *usrPtr) } #endif + // Since we do not pass in the destination DPI to CoreText when making + // the font, we need to pass in a point size which is scaled to include + // the DPI. The default DPI for the screen is 72, thus the scale factor + // is destinationDpi / 72, but since pixelSize = pointSize / 72 * dpi, + // the pixelSize is actually the scaled point size for the destination + // DPI, and we can use that directly. qreal scaledPointSize = f.pixelSize; - // When 96 DPI is forced, the Mac plugin will use DPI 72 for some - // fonts (hardcoded in qcocoaintegration.mm) and 96 for others. This - // discrepancy makes it impossible to find the correct point size - // here without having the DPI used for the font. Until a proper - // solution (requiring API change) can be made, we simply fall back - // to passing in the point size to retain old behavior. - if (QGuiApplication::testAttribute(Qt::AA_Use96Dpi)) - scaledPointSize = f.pointSize; - CGAffineTransform matrix = qt_transform_from_fontdef(f); CTFontRef font = CTFontCreateWithFontDescriptor(descriptor, scaledPointSize, &matrix); if (font) { -- cgit v1.2.3 From 30335364a114dd145bad21e9c2519ac390cd73b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 4 Sep 2015 17:56:14 +0200 Subject: Update QPA handleExtendedKeyEvent to return the accepted state of the event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ie85a4e987eb069d4dd0dbd39860f299a7204b585 Reviewed-by: Morten Johan Sørvig Reviewed-by: Tor Arne Vestbø --- src/gui/kernel/qwindowsysteminterface.cpp | 8 ++++---- src/gui/kernel/qwindowsysteminterface.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 78bce0f0e3..91a935ad0f 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -324,18 +324,18 @@ bool QWindowSystemInterface::handleKeyEvent(QWindow *tlw, ulong timestamp, QEven return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } -void QWindowSystemInterface::handleExtendedKeyEvent(QWindow *w, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, +bool QWindowSystemInterface::handleExtendedKeyEvent(QWindow *w, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers, const QString& text, bool autorep, ushort count) { unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); - handleExtendedKeyEvent(w, time, type, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, + return handleExtendedKeyEvent(w, time, type, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count); } -void QWindowSystemInterface::handleExtendedKeyEvent(QWindow *tlw, ulong timestamp, QEvent::Type type, int key, +bool QWindowSystemInterface::handleExtendedKeyEvent(QWindow *tlw, ulong timestamp, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers, @@ -346,7 +346,7 @@ void QWindowSystemInterface::handleExtendedKeyEvent(QWindow *tlw, ulong timestam QWindowSystemInterfacePrivate::KeyEvent * e = new QWindowSystemInterfacePrivate::KeyEvent(tlw, timestamp, type, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } void QWindowSystemInterface::handleWheelEvent(QWindow *w, const QPointF & local, const QPointF & global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods) { diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h index 3e0b788c0f..99589e8aa1 100644 --- a/src/gui/kernel/qwindowsysteminterface.h +++ b/src/gui/kernel/qwindowsysteminterface.h @@ -98,12 +98,12 @@ public: static bool handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1); static bool handleKeyEvent(QWindow *w, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1); - static void handleExtendedKeyEvent(QWindow *w, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, + static bool handleExtendedKeyEvent(QWindow *w, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers, const QString& text = QString(), bool autorep = false, ushort count = 1); - static void handleExtendedKeyEvent(QWindow *w, ulong timestamp, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, + static bool handleExtendedKeyEvent(QWindow *w, ulong timestamp, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers, const QString& text = QString(), bool autorep = false, -- cgit v1.2.3 From a5fb312cd631b1c70fc199245724e077727578a5 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Thu, 10 Sep 2015 12:17:32 +0200 Subject: Fix QT_NO_ACCESSIBILITY build on OS X MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Id8b41787fb9f50296ee9e0ad1f108418565d9325 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoaaccessibility.h | 6 +++++- src/plugins/platforms/cocoa/qcocoaaccessibility.mm | 4 ++++ src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h | 6 +++++- src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm | 4 ++++ src/plugins/platforms/cocoa/qcocoaintegration.h | 2 ++ src/plugins/platforms/cocoa/qcocoaintegration.mm | 6 ++---- src/plugins/platforms/cocoa/qnsviewaccessibility.mm | 4 ++++ 7 files changed, 26 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.h b/src/plugins/platforms/cocoa/qcocoaaccessibility.h index 18ff9aeb29..228643ab26 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibility.h +++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.h @@ -38,6 +38,8 @@ #include #include +#ifndef QT_NO_ACCESSIBILITY + QT_BEGIN_NAMESPACE class QCocoaAccessibility : public QPlatformAccessibility @@ -85,4 +87,6 @@ id getValueAttribute(QAccessibleInterface *interface); QT_END_NAMESPACE -#endif +#endif // QT_NO_ACCESSIBILITY + +#endif // QCOCOAACCESIBILITY_H diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm index 03f585d19d..4e901ba015 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm @@ -37,6 +37,8 @@ QT_BEGIN_NAMESPACE +#ifndef QT_NO_ACCESSIBILITY + QCocoaAccessibility::QCocoaAccessibility() { @@ -374,5 +376,7 @@ id getValueAttribute(QAccessibleInterface *interface) } // namespace QCocoaAccessible +#endif // QT_NO_ACCESSIBILITY + QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h index 9f56d306f4..73aeae129b 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h @@ -37,6 +37,8 @@ #include "qt_mac_p.h" +#ifndef QT_NO_ACCESSIBILITY + #import #import @@ -56,4 +58,6 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QMacAccessibilityElement); -#endif +#endif // QT_NO_ACCESSIBILITY + +#endif // QCOCOAACCESIBILITYELEMENT_H diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm index 84d60df3ef..28f3b2af84 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm @@ -42,6 +42,8 @@ QT_USE_NAMESPACE +#ifndef QT_NO_ACCESSIBILITY + static void convertLineOffset(QAccessibleTextInterface *text, int &line, int &offset, NSUInteger *start = 0, NSUInteger *end = 0) { Q_ASSERT(line == -1 || offset == -1); @@ -580,3 +582,5 @@ static void convertLineOffset(QAccessibleTextInterface *text, int &line, int &of } @end + +#endif // QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index 32a08dbb0d..e7e21c356a 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -121,7 +121,9 @@ public: QCoreTextFontDatabase *fontDatabase() const Q_DECL_OVERRIDE; QCocoaNativeInterface *nativeInterface() const Q_DECL_OVERRIDE; QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE; +#ifndef QT_NO_ACCESSIBILITY QCocoaAccessibility *accessibility() const Q_DECL_OVERRIDE; +#endif QCocoaClipboard *clipboard() const Q_DECL_OVERRIDE; QCocoaDrag *drag() const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 051a1c8710..6bec6b191d 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -502,14 +502,12 @@ QPlatformInputContext *QCocoaIntegration::inputContext() const return mInputContext.data(); } +#ifndef QT_NO_ACCESSIBILITY QCocoaAccessibility *QCocoaIntegration::accessibility() const { -#ifndef QT_NO_ACCESSIBILITY return mAccessibility.data(); -#else - return 0; -#endif } +#endif QCocoaClipboard *QCocoaIntegration::clipboard() const { diff --git a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm index 93f0817aad..1f15da5b3b 100644 --- a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm +++ b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm @@ -44,6 +44,8 @@ #import +#ifndef QT_NO_ACCESSIBILITY + @implementation QNSView (QNSViewAccessibility) - (id)childAccessibleElement { @@ -80,3 +82,5 @@ } @end + +#endif // QT_NO_ACCESSIBILITY -- cgit v1.2.3 From 053bd200797dff14beffd387b0908f475c139378 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Thu, 10 Sep 2015 13:19:46 +0200 Subject: Fix QT_NO_ACCESSIBILITY build on linux Change-Id: Id9202b4ad84af0e94e59fafc3d56d8414fd5c43c Reviewed-by: J-P Nurmi --- src/widgets/styles/qgtkstyle.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/widgets/styles/qgtkstyle.cpp b/src/widgets/styles/qgtkstyle.cpp index 348727b328..7ed0dce91d 100644 --- a/src/widgets/styles/qgtkstyle.cpp +++ b/src/widgets/styles/qgtkstyle.cpp @@ -3633,6 +3633,7 @@ QRect QGtkStyle::subControlRect(ComplexControl control, const QStyleOptionComple QFont font = widget->font(); font.setBold(true); fontMetrics = QFontMetrics(font); +#ifndef QT_NO_ACCESSIBILITY } else if (QStyleHelper::isInstanceOf(groupBox->styleObject, QAccessible::Grouping)) { QVariant var = groupBox->styleObject->property("font"); if (var.isValid() && var.canConvert()) { @@ -3640,6 +3641,7 @@ QRect QGtkStyle::subControlRect(ComplexControl control, const QStyleOptionComple font.setBold(true); fontMetrics = QFontMetrics(font); } +#endif // QT_NO_ACCESSIBILITY } QSize textRect = fontMetrics.boundingRect(groupBox->text).size() + QSize(4, 4); -- cgit v1.2.3 From 47b3e7d1308f01a243745e175071b24316671021 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 9 Sep 2015 14:55:54 +0200 Subject: Fix some doc warnings. qtbase/src/gui/text/qzip.cpp:797:warn:Cannot find 'FileInfo::d' specified with '\variable' in any header file qtbase/src/opengl/doc/src/qtopengl-index.qdoc:28:warn:Can't link to 'Qt Gui' qtbase/src/opengl/doc/src/qtopengl-module.qdoc:28:warn:Can't link to 'Qt Gui' qtbase/src/widgets/widgets/qcombobox.cpp:3033:warn:Cannot find base function for '\reimp' in showPopupFromMouseEvent() qtbase/src/corelib/plugin/quuid.cpp:849: warning: Can't link to 'variant()' qtbase/src/corelib/plugin/quuid.cpp:863: warning: Can't link to 'variant()' qtbase/src/widgets/dialogs/qsidebar.cpp:72: warning: Cannot find base function for '\reimp' in mimeTypes() qtbase/src/widgets/dialogs/qsidebar.cpp:80: warning: Cannot find base function for '\reimp' in flags() qtbase/src/widgets/dialogs/qsidebar.cpp:98: warning: Cannot find base function for '\reimp' in mimeData() qtbase/src/widgets/dialogs/qsidebar.cpp:134: warning: Cannot find base function for '\reimp' in dropMimeData() qtbase/src/widgets/dialogs/qsidebar.cpp:151: warning: Cannot find base function for '\reimp' in setData() Change-Id: I39d6494eb8179f0f7532f99458736fa5e30cdc25 Reviewed-by: Leena Miettinen --- src/corelib/plugin/quuid.cpp | 4 ++-- src/gui/text/qzip.cpp | 6 ------ src/opengl/doc/src/qtopengl-index.qdoc | 2 +- src/opengl/doc/src/qtopengl-module.qdoc | 2 +- src/widgets/dialogs/qsidebar.cpp | 2 ++ src/widgets/widgets/qcombobox.cpp | 3 --- 6 files changed, 6 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/corelib/plugin/quuid.cpp b/src/corelib/plugin/quuid.cpp index 8b6dfc6932..6698b140af 100644 --- a/src/corelib/plugin/quuid.cpp +++ b/src/corelib/plugin/quuid.cpp @@ -857,7 +857,7 @@ bool QUuid::operator>(const QUuid &other) const Q_DECL_NOTHROW different variant field, the return value is determined by comparing the two \l{QUuid::Variant} {variants}. - \sa variant() + \sa QUuid::variant() */ /*! @@ -871,7 +871,7 @@ bool QUuid::operator>(const QUuid &other) const Q_DECL_NOTHROW different variant field, the return value is determined by comparing the two \l{QUuid::Variant} {variants}. - \sa variant() + \sa QUuid::variant() */ /*! diff --git a/src/gui/text/qzip.cpp b/src/gui/text/qzip.cpp index 6053466148..be002167cb 100644 --- a/src/gui/text/qzip.cpp +++ b/src/gui/text/qzip.cpp @@ -794,12 +794,6 @@ void QZipWriterPrivate::addEntry(EntryType type, const QString &fileName, const The total size of the unpacked content. */ -/*! - \variable FileInfo::d - \internal - private pointer. -*/ - /*! \class QZipReader \internal diff --git a/src/opengl/doc/src/qtopengl-index.qdoc b/src/opengl/doc/src/qtopengl-index.qdoc index d8e63547b7..a01ccc67f6 100644 --- a/src/opengl/doc/src/qtopengl-index.qdoc +++ b/src/opengl/doc/src/qtopengl-index.qdoc @@ -32,7 +32,7 @@ use OpenGL in Qt applications. \warning This module should not be used anymore for new code. Please - use the corresponding OpenGL classes in \l{Qt Gui}. + use the corresponding OpenGL classes in \l{Qt GUI}. OpenGL is a standard API for rendering 3D graphics. OpenGL only deals with 3D rendering and provides little or no support for GUI diff --git a/src/opengl/doc/src/qtopengl-module.qdoc b/src/opengl/doc/src/qtopengl-module.qdoc index 824db48754..80742dd588 100644 --- a/src/opengl/doc/src/qtopengl-module.qdoc +++ b/src/opengl/doc/src/qtopengl-module.qdoc @@ -35,7 +35,7 @@ use OpenGL in Qt applications. \warning This module should not be used anymore for new code. Please - use the corresponding OpenGL classes in \l{Qt Gui}. + use the corresponding OpenGL classes in \l{Qt GUI}. OpenGL is a standard API for rendering 3D graphics. OpenGL only deals with 3D rendering and provides little or no support for GUI diff --git a/src/widgets/dialogs/qsidebar.cpp b/src/widgets/dialogs/qsidebar.cpp index be3c060ba1..f883705cc3 100644 --- a/src/widgets/dialogs/qsidebar.cpp +++ b/src/widgets/dialogs/qsidebar.cpp @@ -60,6 +60,8 @@ void QSideBarDelegate::initStyleOption(QStyleOptionViewItem *option, } /*! + \internal + \class QUrlModel QUrlModel lets you have indexes from a QFileSystemModel to a list. When QFileSystemModel changes them QUrlModel will automatically update. diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index af2a66a838..89fd3d3d57 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -3030,9 +3030,6 @@ void QComboBox::mousePressEvent(QMouseEvent *e) d->showPopupFromMouseEvent(e); } -/*! - \reimp -*/ void QComboBoxPrivate::showPopupFromMouseEvent(QMouseEvent *e) { Q_Q(QComboBox); -- cgit v1.2.3 From a96c98fc612879fdef7f9c53753521e7cdfab749 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 10 Sep 2015 15:32:20 +0200 Subject: Fix qdoc warnings of QRgba64. qtbase/src/gui/painting/qrgba64.h:107: warning: No documentation for 'QRgba64::isOpaque()' qtbase/src/gui/painting/qrgba64.h:112: warning: No documentation for 'QRgba64::isTransparent()' qtbase/src/gui/painting/qrgba64.h:121: warning: No documentation for 'QRgba64::setAlpha()' qtbase/src/gui/painting/qrgba64.h:119: warning: No documentation for 'QRgba64::setBlue()' qtbase/src/gui/painting/qrgba64.h:118: warning: No documentation for 'QRgba64::setGreen()' qtbase/src/gui/painting/qrgba64.h:117: warning: No documentation for 'QRgba64::setRed()' qtbase/src/gui/painting/qrgba64.h:163: warning: No documentation for 'QRgba64::operator=()' Change-Id: Ic6f6a8415b8ad33917e460737824fc8856776de1 Reviewed-by: Allan Sandfeld Jensen --- src/gui/painting/qrgba64.qdoc | 64 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/painting/qrgba64.qdoc b/src/gui/painting/qrgba64.qdoc index 29da0aa390..b786e91b03 100644 --- a/src/gui/painting/qrgba64.qdoc +++ b/src/gui/painting/qrgba64.qdoc @@ -36,12 +36,18 @@ QRgba64 is a 64-bit data-structure containing four 16-bit color channels: Red, green, blue and alpha. QRgba64 can be used a replacement for QRgb when higher precision is needed. In particular a - premultiplied QRgba64 can operate on unpremultipled QRgb without loss of precision except + premultiplied QRgba64 can operate on unpremultiplied QRgb without loss of precision except for alpha 0. \sa QRgb, QColor */ +/*! + \fn QRgba64 QRgba64::operator=(quint64 rgba) + + Assigns the value \a rgba to this instance of QRgba64 and returns it. +*/ + /*! \fn static QRgba64 QRgba64::fromRgba64(quint16 r, quint16 g, quint16 b, quint16 a) @@ -74,28 +80,84 @@ \sa fromRgba() */ +/*! + \fn bool QRgba64::isOpaque() const + + Returns whether the color is fully opaque. + + \sa isTransparent(), alpha() +*/ + +/*! + \fn bool QRgba64::isTransparent() const + + Returns whether the color is transparent. + + \sa isOpaque(), alpha() +*/ + /*! \fn quint16 QRgba64::red() const Returns the 16-bit red color component. + + \sa setRed() +*/ + +/*! + \fn QRgba64::setRed(quint16 red) + + Sets the red color component of this color to \a red. + + \sa red() */ /*! \fn quint16 QRgba64::green() const Returns the 16-bit green color component. + + \sa setGreen() +*/ + +/*! + \fn QRgba64::setGreen(quint16 green) + + Sets the green color component of this color to \a green. + + \sa green() */ /*! \fn quint16 QRgba64::blue() const Returns the 16-bit blue color component. + + \sa setBlue() +*/ + +/*! + \fn QRgba64::setBlue(quint16 blue) + + Sets the blue color component of this color to \a blue. + + \sa blue() */ /*! \fn quint16 QRgba64::alpha() const Returns the 16-bit alpha channel. + + \sa setAlpha() +*/ + +/*! + \fn QRgba64::setAlpha(quint16 alpha) + + Sets the alpha of this color to \a alpha. + + \sa alpha() */ /*! -- cgit v1.2.3 From b2ca127ec42c541a00973cafe8333c187d1fcb5c Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Tue, 8 Sep 2015 10:45:57 +0200 Subject: qdoc: Allow linking to QML signals with their proper name Trying to link to QML signal documentation failed when the link string ends in parentheses: \l someSignal() This commit fixes the issue by adding QML signals into the list of primary functions, making it thereby available for findFunctionNode() method. Change-Id: Ib5a8325cd18171cdea392bcc1af676efe373f433 Task-number: QTBUG-48158 Reviewed-by: Martin Smith --- src/tools/qdoc/node.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp index 1fe0af352d..eec08e3c72 100644 --- a/src/tools/qdoc/node.cpp +++ b/src/tools/qdoc/node.cpp @@ -1189,7 +1189,9 @@ bool Aggregate::isSameSignature(const FunctionNode *f1, const FunctionNode *f2) void Aggregate::addChild(Node *child) { children_.append(child); - if ((child->type() == Function) || (child->type() == QmlMethod)) { + if (child->type() == Function + || child->type() == QmlMethod + || child->type() == QmlSignal) { FunctionNode *func = static_cast(child); QString name = func->name(); if (!primaryFunctionMap_.contains(name)) { @@ -1234,7 +1236,9 @@ void Aggregate::removeChild(Node *child) { children_.removeAll(child); enumChildren_.removeAll(child); - if (child->type() == Function) { + if (child->type() == Function + || child->type() == QmlMethod + || child->type() == QmlSignal) { QMap::Iterator primary = primaryFunctionMap_.find(child->name()); NodeList& overloads = secondaryFunctionMap_[child->name()]; if (primary != primaryFunctionMap_.end() && *primary == child) { -- cgit v1.2.3 From 15b42af11123f9d1eb4bbd79870185585103ea8d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 17 Jul 2015 12:50:56 -0700 Subject: Change the CPU feature status word to be 64-bit instead of 32-bit I'm going to need the extra bits for x86. Change-Id: Ib306f8f647014b399b87ffff13f1d3d23e138518 Reviewed-by: Oswald Buddenhagen Reviewed-by: Allan Sandfeld Jensen --- src/corelib/tools/qsimd.cpp | 51 +++++++++++++++++++++++++++------------------ src/corelib/tools/qsimd_p.h | 20 +++++++++++++----- 2 files changed, 46 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index e7917ffdac..91700c053d 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -240,7 +240,7 @@ static void xgetbv(uint in, uint &eax, uint &edx) #endif } -static inline uint detectProcessorFeatures() +static quint64 detectProcessorFeatures() { // Flags from the CR0 / XCR0 state register enum XCR0Flags { @@ -258,7 +258,7 @@ static inline uint detectProcessorFeatures() AVX512State = AVXState | OpMask | ZMM0_15Hi256 | ZMM16_31 }; - uint features = 0; + quint64 features = 0; int cpuidLevel = maxBasicCpuidSupported(); #if Q_PROCESSOR_X86 < 5 if (cpuidLevel < 1) @@ -505,27 +505,35 @@ static const int features_indices[] = { static const int features_count = (sizeof features_indices - 1) / (sizeof features_indices[0]); // record what CPU features were enabled by default in this Qt build -static const uint minFeature = qCompilerCpuFeatures; +static const quint64 minFeature = qCompilerCpuFeatures; #ifdef Q_OS_WIN #if defined(Q_CC_GNU) -# define ffs __builtin_ffs +# define ffsll __builtin_ffsll #else -int ffs(int i) +int ffsll(quint64 i) { -#ifndef Q_OS_WINCE +#if defined(Q_OS_WIN64) + unsigned long result; + return _BitScanForward64(&result, i) ? result : 0; +#elif !defined(Q_OS_WINCE) unsigned long result; - return _BitScanForward(&result, i) ? result : 0; + return _BitScanForward(&result, i) ? result : + _BitScanForward(&result, i >> 32) ? result + 32 : 0; #else return 0; #endif } #endif -#elif defined(Q_OS_ANDROID) -# define ffs __builtin_ffs +#elif defined(Q_OS_ANDROID) || defined(Q_OS_QNX) +# define ffsll __builtin_ffsll #endif -QBasicAtomicInt qt_cpu_features = Q_BASIC_ATOMIC_INITIALIZER(0); +#ifdef Q_ATOMIC_INT64_IS_SUPPORTED +Q_CORE_EXPORT QBasicAtomicInteger qt_cpu_features[1] = { Q_BASIC_ATOMIC_INITIALIZER(0) }; +#else +Q_CORE_EXPORT QBasicAtomicInteger qt_cpu_features[2] = { Q_BASIC_ATOMIC_INITIALIZER(0), Q_BASIC_ATOMIC_INITIALIZER(0) }; +#endif void qDetectCpuFeatures() { @@ -547,11 +555,11 @@ void qDetectCpuFeatures() // contains all the features that the code required. Qt 4 ran for years // like that, so it shouldn't be a problem. - qt_cpu_features.store(minFeature | QSimdInitialized); + qt_cpu_features.store(minFeature | quint32(QSimdInitialized)); return; # endif #endif - uint f = detectProcessorFeatures(); + quint64 f = detectProcessorFeatures(); QByteArray disable = qgetenv("QT_NO_CPU_FEATURE"); if (!disable.isEmpty()) { disable.prepend(' '); @@ -567,29 +575,32 @@ void qDetectCpuFeatures() bool runningOnValgrind = false; #endif if (!runningOnValgrind && (minFeature != 0 && (f & minFeature) != minFeature)) { - uint missing = minFeature & ~f; + quint64 missing = minFeature & ~f; fprintf(stderr, "Incompatible processor. This Qt build requires the following features:\n "); for (int i = 0; i < features_count; ++i) { - if (missing & (1 << i)) + if (missing & (Q_UINT64_C(1) << i)) fprintf(stderr, "%s", features_string + features_indices[i]); } fprintf(stderr, "\n"); fflush(stderr); - qFatal("Aborted. Incompatible processor: missing feature 0x%x -%s.", missing, - features_string + features_indices[ffs(missing) - 1]); + qFatal("Aborted. Incompatible processor: missing feature 0x%llx -%s.", missing, + features_string + features_indices[ffsll(missing) - 1]); } - qt_cpu_features.store(f | QSimdInitialized); + qt_cpu_features[0].store(f | quint32(QSimdInitialized)); +#ifndef Q_ATOMIC_INT64_IS_SUPPORTED + qt_cpu_features[1].store(f >> 32); +#endif } void qDumpCPUFeatures() { - uint features = qCpuFeatures(); + quint64 features = qCpuFeatures() & ~quint64(QSimdInitialized); printf("Processor features: "); for (int i = 0; i < features_count; ++i) { - if (features & (1 << i)) + if (features & (Q_UINT64_C(1) << i)) printf("%s%s", features_string + features_indices[i], - minFeature & (1 << i) ? "[required]" : ""); + minFeature & (Q_UINT64_C(1) << i) ? "[required]" : ""); } puts(""); } diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h index 8523fb09c1..6ca3836ca9 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -298,18 +298,28 @@ static const uint qCompilerCpuFeatures = 0 #endif ; -extern Q_CORE_EXPORT QBasicAtomicInt qt_cpu_features; +#ifdef Q_ATOMIC_INT64_IS_SUPPORTED +extern Q_CORE_EXPORT QBasicAtomicInteger qt_cpu_features[1]; +#else +extern Q_CORE_EXPORT QBasicAtomicInteger qt_cpu_features[2]; +#endif Q_CORE_EXPORT void qDetectCpuFeatures(); -static inline uint qCpuFeatures() +static inline quint64 qCpuFeatures() { - int features = qt_cpu_features.load(); + quint64 features = qt_cpu_features[0].load(); +#ifndef Q_ATOMIC_INT64_IS_SUPPORTED + features |= quint64(qt_cpu_features[1].load()) << 32; +#endif if (Q_UNLIKELY(features == 0)) { qDetectCpuFeatures(); - features = qt_cpu_features.load(); + features = qt_cpu_features[0].load(); +#ifndef Q_ATOMIC_INT64_IS_SUPPORTED + features |= quint64(qt_cpu_features[1].load()) << 32; +#endif Q_ASSUME(features != 0); } - return uint(features); + return features; } #define qCpuHasFeature(feature) ((qCompilerCpuFeatures & (feature)) || (qCpuFeatures() & (feature))) -- cgit v1.2.3 From 2e8bec9e4b8d229ad9f5f73d2362f21c13599816 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 8 Sep 2015 16:36:50 +0200 Subject: QImage: Use d->height directly for checking dimensions on pixel() Calling height() causes an additional function call and check for d which sums up to more than 25% of the total CPU cost of pixel() if the format is simple. Change-Id: I449a3a17dc031e607e40dc1577a5553e7490de76 Reviewed-by: Allan Sandfeld Jensen --- src/gui/image/qimage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 045e36323f..6af1580641 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -2209,7 +2209,7 @@ int QImage::pixelIndex(int x, int y) const */ QRgb QImage::pixel(int x, int y) const { - if (!d || x < 0 || x >= d->width || y < 0 || y >= height()) { + if (!d || x < 0 || x >= d->width || y < 0 || y >= d->height) { qWarning("QImage::pixel: coordinate (%d,%d) out of range", x, y); return 12345; } -- cgit v1.2.3 From a0575a85b7042a7898e7da95e32413e6e2661b0d Mon Sep 17 00:00:00 2001 From: Nobuaki Sukegawa Date: Tue, 9 Dec 2014 23:44:45 +0900 Subject: Fix typo in local variable name Change-Id: I35f55f993274d9575a3906c1d553e7b04638efe3 Reviewed-by: Simon Hausmann --- .../java/src/org/qtproject/qt5/android/bindings/QtActivity.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java index 23e08f537a..e5ed690f07 100644 --- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java +++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java @@ -243,11 +243,11 @@ public class QtActivity extends Activity @SuppressWarnings("rawtypes") Class loaderClass = m_classLoader.loadClass(loaderParams.getString(LOADER_CLASS_NAME_KEY)); // load QtLoader class Object qtLoader = loaderClass.newInstance(); // create an instance - Method perpareAppMethod = qtLoader.getClass().getMethod("loadApplication", + Method prepareAppMethod = qtLoader.getClass().getMethod("loadApplication", Activity.class, ClassLoader.class, Bundle.class); - if (!(Boolean)perpareAppMethod.invoke(qtLoader, this, m_classLoader, loaderParams)) + if (!(Boolean)prepareAppMethod.invoke(qtLoader, this, m_classLoader, loaderParams)) throw new Exception(""); QtApplication.setQtActivityDelegate(qtLoader); -- cgit v1.2.3 From 2187f0e7b08d872b2ff618be679a15e213b6c25d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sat, 12 Sep 2015 13:17:49 -0300 Subject: Add a delimiter before "TracerPid" Future-proofing against a future version of the Linux kernel adding a "FooTracerPid:" before the TracerPid entry. Change-Id: I42e7ef1a481840699a8dffff140347457902900f Reviewed-by: Simon Hausmann --- src/testlib/qtestcase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 7f199182f9..000470e9e5 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -2503,7 +2503,7 @@ static bool debuggerPresent() return false; } buffer[size] = 0; - const char tracerPidToken[] = "TracerPid:"; + const char tracerPidToken[] = "\nTracerPid:"; char *tracerPid = strstr(buffer, tracerPidToken); if (!tracerPid) { close(fd); -- cgit v1.2.3 From d878107001fced91958d08df843f85e294027e4e Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 11 Aug 2015 16:25:26 -0700 Subject: Declare QNetworkAddressEntry and QNetworkInterface as metatypes Change-Id: I7de033f80b0e4431b7f1ffff13f98c092ea3ba3e Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/network/kernel/qnetworkinterface.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/network/kernel/qnetworkinterface.h b/src/network/kernel/qnetworkinterface.h index 31d3b7b128..b3daa3d4a0 100644 --- a/src/network/kernel/qnetworkinterface.h +++ b/src/network/kernel/qnetworkinterface.h @@ -133,6 +133,9 @@ Q_NETWORK_EXPORT QDebug operator<<(QDebug debug, const QNetworkInterface &networ QT_END_NAMESPACE +Q_DECLARE_METATYPE(QNetworkAddressEntry) +Q_DECLARE_METATYPE(QNetworkInterface) + #endif // QT_NO_NETWORKINTERFACE #endif -- cgit v1.2.3 From 7bd64776825f0e025cc2597e6c1909efbb1233f7 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 11 Aug 2015 19:49:37 -0700 Subject: Use the actual iphlpapi.dll and its headers The has been present since Windows 2000 and most functions we need have been present since Windows XP and Windows CE 5.0. There's no need to do runtime detection anymore. This was necessary in Qt 4.2, when this code was introduced, because we still supported Windows 98 and Me, including Windows platform SDKs that lacked the necessary header definitions. Change-Id: I076d1e8bbd53469a24fad72cf58b1905e737f52a Reviewed-by: Friedemann Kleint --- src/network/kernel/kernel.pri | 3 +- src/network/kernel/qnetworkinterface_win.cpp | 62 +++---- src/network/kernel/qnetworkinterface_win_p.h | 251 --------------------------- 3 files changed, 23 insertions(+), 293 deletions(-) delete mode 100644 src/network/kernel/qnetworkinterface_win_p.h (limited to 'src') diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri index e539388b81..671b57ed11 100644 --- a/src/network/kernel/kernel.pri +++ b/src/network/kernel/kernel.pri @@ -34,11 +34,10 @@ android { win32: { !winrt { - HEADERS += kernel/qnetworkinterface_win_p.h SOURCES += kernel/qdnslookup_win.cpp \ kernel/qhostinfo_win.cpp \ kernel/qnetworkinterface_win.cpp - LIBS_PRIVATE += -ldnsapi + LIBS_PRIVATE += -ldnsapi -liphlpapi } else { SOURCES += kernel/qdnslookup_winrt.cpp \ kernel/qhostinfo_winrt.cpp \ diff --git a/src/network/kernel/qnetworkinterface_win.cpp b/src/network/kernel/qnetworkinterface_win.cpp index dfcfdcc91f..d73d3ecdc9 100644 --- a/src/network/kernel/qnetworkinterface_win.cpp +++ b/src/network/kernel/qnetworkinterface_win.cpp @@ -31,7 +31,7 @@ ** ****************************************************************************/ -#include "qnetworkinterface_win_p.h" +#define WIN32_LEAN_AND_MEAN 1 #include "qnetworkinterface.h" #include "qnetworkinterface_p.h" @@ -41,18 +41,20 @@ #include #include #include -#include -#include +// Since we need to include winsock2.h, we need to define WIN32_LEAN_AND_MEAN +// (above) so windows.h won't include winsock.h. +// In addition, we need to include winsock2.h before iphlpapi.h and we need +// to include ws2ipdef.h to work around an MinGW-w64 bug +// (http://sourceforge.net/p/mingw-w64/mailman/message/32935366/) +#include +#include +#include +#include -QT_BEGIN_NAMESPACE +#include -typedef DWORD (WINAPI *PtrGetAdaptersInfo)(PIP_ADAPTER_INFO, PULONG); -static PtrGetAdaptersInfo ptrGetAdaptersInfo = 0; -typedef ULONG (WINAPI *PtrGetAdaptersAddresses)(ULONG, ULONG, PVOID, PIP_ADAPTER_ADDRESSES, PULONG); -static PtrGetAdaptersAddresses ptrGetAdaptersAddresses = 0; -typedef DWORD (WINAPI *PtrGetNetworkParams)(PFIXED_INFO, PULONG); -static PtrGetNetworkParams ptrGetNetworkParams = 0; +QT_BEGIN_NAMESPACE static void resolveLibs() { @@ -60,20 +62,11 @@ static void resolveLibs() static bool done = false; if (!done) { - HINSTANCE iphlpapiHnd = QSystemLibrary::load(L"iphlpapi"); - if (iphlpapiHnd == NULL) { - done = true; - return; - } + HINSTANCE iphlpapiHnd = GetModuleHandle(L"iphlpapi"); + Q_ASSERT(iphlpapiHnd); #if defined(Q_OS_WINCE) - ptrGetAdaptersInfo = (PtrGetAdaptersInfo)GetProcAddress(iphlpapiHnd, L"GetAdaptersInfo"); - ptrGetAdaptersAddresses = (PtrGetAdaptersAddresses)GetProcAddress(iphlpapiHnd, L"GetAdaptersAddresses"); - ptrGetNetworkParams = (PtrGetNetworkParams)GetProcAddress(iphlpapiHnd, L"GetNetworkParams"); #else - ptrGetAdaptersInfo = (PtrGetAdaptersInfo)GetProcAddress(iphlpapiHnd, "GetAdaptersInfo"); - ptrGetAdaptersAddresses = (PtrGetAdaptersAddresses)GetProcAddress(iphlpapiHnd, "GetAdaptersAddresses"); - ptrGetNetworkParams = (PtrGetNetworkParams)GetProcAddress(iphlpapiHnd, "GetNetworkParams"); #endif done = true; } @@ -106,14 +99,14 @@ static QHash ipv4Netmasks() ULONG bufSize = sizeof staticBuf; QHash ipv4netmasks; - DWORD retval = ptrGetAdaptersInfo(pAdapter, &bufSize); + DWORD retval = GetAdaptersInfo(pAdapter, &bufSize); if (retval == ERROR_BUFFER_OVERFLOW) { // need more memory pAdapter = (IP_ADAPTER_INFO *)malloc(bufSize); if (!pAdapter) return ipv4netmasks; // try again - if (ptrGetAdaptersInfo(pAdapter, &bufSize) != ERROR_SUCCESS) { + if (GetAdaptersInfo(pAdapter, &bufSize) != ERROR_SUCCESS) { free(pAdapter); return ipv4netmasks; } @@ -148,14 +141,14 @@ static QList interfaceListingWinXP() ULONG flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_MULTICAST; - ULONG retval = ptrGetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAdapter, &bufSize); + ULONG retval = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAdapter, &bufSize); if (retval == ERROR_BUFFER_OVERFLOW) { // need more memory pAdapter = (IP_ADAPTER_ADDRESSES *)malloc(bufSize); if (!pAdapter) return interfaces; // try again - if (ptrGetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAdapter, &bufSize) != ERROR_SUCCESS) { + if (GetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAdapter, &bufSize) != ERROR_SUCCESS) { free(pAdapter); return interfaces; } @@ -224,36 +217,25 @@ static QList interfaceListingWinXP() return interfaces; } -static QList interfaceListing() -{ - resolveLibs(); - if (ptrGetAdaptersAddresses != NULL) - return interfaceListingWinXP(); - - // failed - return QList(); -} - QList QNetworkInterfaceManager::scan() { - return interfaceListing(); + resolveLibs(); + return interfaceListingWinXP(); } QString QHostInfo::localDomainName() { resolveLibs(); - if (ptrGetNetworkParams == NULL) - return QString(); // couldn't resolve FIXED_INFO info, *pinfo; ULONG bufSize = sizeof info; pinfo = &info; - if (ptrGetNetworkParams(pinfo, &bufSize) == ERROR_BUFFER_OVERFLOW) { + if (GetNetworkParams(pinfo, &bufSize) == ERROR_BUFFER_OVERFLOW) { pinfo = (FIXED_INFO *)malloc(bufSize); if (!pinfo) return QString(); // try again - if (ptrGetNetworkParams(pinfo, &bufSize) != ERROR_SUCCESS) { + if (GetNetworkParams(pinfo, &bufSize) != ERROR_SUCCESS) { free(pinfo); return QString(); // error } diff --git a/src/network/kernel/qnetworkinterface_win_p.h b/src/network/kernel/qnetworkinterface_win_p.h deleted file mode 100644 index 55d98d2407..0000000000 --- a/src/network/kernel/qnetworkinterface_win_p.h +++ /dev/null @@ -1,251 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QNETWORKINTERFACE_WIN_P_H -#define QNETWORKINTERFACE_WIN_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of the QLibrary class. This header file may change from -// version to version without notice, or even be removed. -// -// We mean it. -// - -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -#ifndef GAA_FLAG_INCLUDE_ALL_INTERFACES -# define GAA_FLAG_INCLUDE_ALL_INTERFACES 0x0100 -#endif -#ifndef MAX_ADAPTER_ADDRESS_LENGTH -// definitions from iptypes.h -# define MAX_ADAPTER_DESCRIPTION_LENGTH 128 // arb. -# define MAX_ADAPTER_NAME_LENGTH 256 // arb. -# define MAX_ADAPTER_ADDRESS_LENGTH 8 // arb. -# define DEFAULT_MINIMUM_ENTITIES 32 // arb. -# define MAX_HOSTNAME_LEN 128 // arb. -# define MAX_DOMAIN_NAME_LEN 128 // arb. -# define MAX_SCOPE_ID_LEN 256 // arb. - -# define GAA_FLAG_SKIP_UNICAST 0x0001 -# define GAA_FLAG_SKIP_ANYCAST 0x0002 -# define GAA_FLAG_SKIP_MULTICAST 0x0004 -# define GAA_FLAG_SKIP_DNS_SERVER 0x0008 -# define GAA_FLAG_INCLUDE_PREFIX 0x0010 -# define GAA_FLAG_SKIP_FRIENDLY_NAME 0x0020 - -# define IP_ADAPTER_DDNS_ENABLED 0x01 -# define IP_ADAPTER_REGISTER_ADAPTER_SUFFIX 0x02 -# define IP_ADAPTER_DHCP_ENABLED 0x04 -# define IP_ADAPTER_RECEIVE_ONLY 0x08 -# define IP_ADAPTER_NO_MULTICAST 0x10 -# define IP_ADAPTER_IPV6_OTHER_STATEFUL_CONFIG 0x20 - -# define MIB_IF_TYPE_OTHER 1 -# define MIB_IF_TYPE_ETHERNET 6 -# define MIB_IF_TYPE_TOKENRING 9 -# define MIB_IF_TYPE_FDDI 15 -# define MIB_IF_TYPE_PPP 23 -# define MIB_IF_TYPE_LOOPBACK 24 -# define MIB_IF_TYPE_SLIP 28 - -// definitions from Ipifcons.h -#define IF_TYPE_PPP 23 - -#endif - -// copied from MSDN online help -typedef enum { - IpPrefixOriginOther = 0, - IpPrefixOriginManual, - IpPrefixOriginWellKnown, - IpPrefixOriginDhcp, - IpPrefixOriginRouterAdvertisement -} IP_PREFIX_ORIGIN; - -typedef enum { - IpSuffixOriginOther = 0, - IpSuffixOriginManual, - IpSuffixOriginWellKnown, - IpSuffixOriginDhcp, - IpSuffixOriginLinkLayerAddress, - IpSuffixOriginRandom -} IP_SUFFIX_ORIGIN; - -typedef enum { - IpDadStateInvalid = 0, - IpDadStateTentative, - IpDadStateDuplicate, - IpDadStateDeprecated, - IpDadStatePreferred, -} IP_DAD_STATE; - -typedef enum { - IfOperStatusUp = 1, - IfOperStatusDown, - IfOperStatusTesting, - IfOperStatusUnknown, - IfOperStatusDormant, - IfOperStatusNotPresent, - IfOperStatusLowerLayerDown -} IF_OPER_STATUS; - -typedef struct _IP_ADAPTER_UNICAST_ADDRESS { - union { - ULONGLONG Alignment; - struct { - ULONG Length; - DWORD Flags; - }; - }; - struct _IP_ADAPTER_UNICAST_ADDRESS* Next; - SOCKET_ADDRESS Address; - IP_PREFIX_ORIGIN PrefixOrigin; - IP_SUFFIX_ORIGIN SuffixOrigin; - IP_DAD_STATE DadState; - ULONG ValidLifetime; - ULONG PreferredLifetime; - ULONG LeaseLifetime; -} IP_ADAPTER_UNICAST_ADDRESS, *PIP_ADAPTER_UNICAST_ADDRESS; - -typedef struct _IP_ADAPTER_ANYCAST_ADDRESS - IP_ADAPTER_ANYCAST_ADDRESS, *PIP_ADAPTER_ANYCAST_ADDRESS; - -typedef struct _IP_ADAPTER_MULTICAST_ADDRESS - IP_ADAPTER_MULTICAST_ADDRESS, - *PIP_ADAPTER_MULTICAST_ADDRESS; - -typedef struct _IP_ADAPTER_DNS_SERVER_ADDRESS - IP_ADAPTER_DNS_SERVER_ADDRESS, - *PIP_ADAPTER_DNS_SERVER_ADDRESS; - -typedef struct _IP_ADAPTER_PREFIX { - union { - ULONGLONG Alignment; - struct { - ULONG Length; - DWORD Flags; - }; - }; - struct _IP_ADAPTER_PREFIX* Next; - SOCKET_ADDRESS Address; - ULONG PrefixLength; -} IP_ADAPTER_PREFIX, - *PIP_ADAPTER_PREFIX; - -typedef struct _IP_ADAPTER_ADDRESSES { - union { - ULONGLONG Alignment; - struct { - ULONG Length; - DWORD IfIndex; - }; - }; - struct _IP_ADAPTER_ADDRESSES* Next; - PCHAR AdapterName; - PIP_ADAPTER_UNICAST_ADDRESS FirstUnicastAddress; - PIP_ADAPTER_ANYCAST_ADDRESS FirstAnycastAddress; - PIP_ADAPTER_MULTICAST_ADDRESS FirstMulticastAddress; - PIP_ADAPTER_DNS_SERVER_ADDRESS FirstDnsServerAddress; - PWCHAR DnsSuffix; - PWCHAR Description; - PWCHAR FriendlyName; - BYTE PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH]; - DWORD PhysicalAddressLength; - DWORD Flags; - DWORD Mtu; - DWORD IfType; - IF_OPER_STATUS OperStatus; - DWORD Ipv6IfIndex; - DWORD ZoneIndices[16]; - PIP_ADAPTER_PREFIX FirstPrefix; -} IP_ADAPTER_ADDRESSES, - *PIP_ADAPTER_ADDRESSES; - -typedef struct { - char String[4 * 4]; -} IP_ADDRESS_STRING, *PIP_ADDRESS_STRING, IP_MASK_STRING, *PIP_MASK_STRING; - -typedef struct _IP_ADDR_STRING { - struct _IP_ADDR_STRING* Next; - IP_ADDRESS_STRING IpAddress; - IP_MASK_STRING IpMask; - DWORD Context; -} IP_ADDR_STRING, - *PIP_ADDR_STRING; - -typedef struct _IP_ADAPTER_INFO { - struct _IP_ADAPTER_INFO* Next; - DWORD ComboIndex; - char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4]; - char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4]; - UINT AddressLength; - BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH]; - DWORD Index; - UINT Type; - UINT DhcpEnabled; - PIP_ADDR_STRING CurrentIpAddress; - IP_ADDR_STRING IpAddressList; - IP_ADDR_STRING GatewayList; - IP_ADDR_STRING DhcpServer; - BOOL HaveWins; - IP_ADDR_STRING PrimaryWinsServer; - IP_ADDR_STRING SecondaryWinsServer; - time_t LeaseObtained; - time_t LeaseExpires; -} IP_ADAPTER_INFO, - *PIP_ADAPTER_INFO; - -typedef struct { - char HostName[MAX_HOSTNAME_LEN + 4]; - char DomainName[MAX_DOMAIN_NAME_LEN + 4]; - PIP_ADDR_STRING CurrentDnsServer; - IP_ADDR_STRING DnsServerList; - UINT NodeType; - char ScopeId[MAX_SCOPE_ID_LEN + 4]; - UINT EnableRouting; - UINT EnableProxy; - UINT EnableDns; -} FIXED_INFO, *PFIXED_INFO; - -QT_END_NAMESPACE - -#endif -- cgit v1.2.3 From 181c8d80d19f975ccf943fa79107f1e839e33e68 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 11 Aug 2015 19:24:51 -0700 Subject: QNetworkInterface: get a friendlier (but not too friendly) name Since Windows Vista, the OS keeps an extra set of names for each interface, which are identifier-like and more friendly than previously, but not the user-description. For example: previous name: "{2B09D370-A032-4478-8444-495AD9301D67}" new name: "wireless_6" friendly name: "Local Area Connection* 12" Change-Id: I7de033f80b0e4431b7f1ffff13f995f983689f06 Reviewed-by: Friedemann Kleint --- src/network/kernel/kernel.pri | 2 ++ src/network/kernel/qnetworkinterface_win.cpp | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri index 671b57ed11..435bfd6c27 100644 --- a/src/network/kernel/kernel.pri +++ b/src/network/kernel/kernel.pri @@ -38,6 +38,8 @@ win32: { kernel/qhostinfo_win.cpp \ kernel/qnetworkinterface_win.cpp LIBS_PRIVATE += -ldnsapi -liphlpapi + DEFINES += WINVER=0x0600 _WIN32_WINNT=0x0600 + } else { SOURCES += kernel/qdnslookup_winrt.cpp \ kernel/qhostinfo_winrt.cpp \ diff --git a/src/network/kernel/qnetworkinterface_win.cpp b/src/network/kernel/qnetworkinterface_win.cpp index d73d3ecdc9..907638f73e 100644 --- a/src/network/kernel/qnetworkinterface_win.cpp +++ b/src/network/kernel/qnetworkinterface_win.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Intel Corporation. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtNetwork module of the Qt Toolkit. @@ -56,6 +57,9 @@ QT_BEGIN_NAMESPACE +typedef NETIO_STATUS (WINAPI *PtrConvertInterfaceLuidToName)(const NET_LUID *, PWSTR, SIZE_T); +static PtrConvertInterfaceLuidToName ptrConvertInterfaceLuidToName = 0; + static void resolveLibs() { // try to find the functions we need from Iphlpapi.dll @@ -66,7 +70,11 @@ static void resolveLibs() Q_ASSERT(iphlpapiHnd); #if defined(Q_OS_WINCE) + // since Windows Embedded Compact 7 + ptrConvertInterfaceLuidToName = (PtrConvertInterfaceLuidToName)GetProcAddress(iphlpapiHnd, L"ConvertInterfaceLuidToNameW"); #else + // since Windows Vista + ptrConvertInterfaceLuidToName = (PtrConvertInterfaceLuidToName)GetProcAddress(iphlpapiHnd, "ConvertInterfaceLuidToNameW"); #endif done = true; } @@ -176,7 +184,16 @@ static QList interfaceListingWinXP() if (ptr->IfType == IF_TYPE_PPP) iface->flags |= QNetworkInterface::IsPointToPoint; - iface->name = QString::fromLocal8Bit(ptr->AdapterName); + if (ptrConvertInterfaceLuidToName && ptr->Length >= offsetof(IP_ADAPTER_ADDRESSES, Luid)) { + // use ConvertInterfaceLuidToName because that returns a friendlier name, though not + // as friendly as FriendlyName below + WCHAR buf[IF_MAX_STRING_SIZE + 1]; + if (ptrConvertInterfaceLuidToName(&ptr->Luid, buf, sizeof(buf)/sizeof(buf[0])) == NO_ERROR) + iface->name = QString::fromWCharArray(buf); + } + if (iface->name.isEmpty()) + iface->name = QString::fromLocal8Bit(ptr->AdapterName); + iface->friendlyName = QString::fromWCharArray(ptr->FriendlyName); if (ptr->PhysicalAddressLength) iface->hardwareAddress = iface->makeHwAddress(ptr->PhysicalAddressLength, -- cgit v1.2.3 From 6de8c0aa09d4bb31ae927f7a98be47f5773acd70 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 2 Jun 2015 11:15:05 -0700 Subject: Add a qt_version_tag symbol to QtCore that uses ELF versions This symbol will exist with different ELF versions, allowing us to know which version of Qt a given library or application was linked against. When this symbol gets used, automatic packaging tools will extract the dependency. The trick here is that the application uses qt_version_tag without knowing which version is current, but the linker resolves it to the current version and records that. For example, if this were used with Qt 5.5, RPM's find-requires on an application using QtCore would print: libQt5Core.so.5()(64bit) libQt5Core.so.5(Qt_5.5)(64bit) libQt5Core.so.5(Qt_5)(64bit) Whereas find-provides on QtCore would print: libQt5Core.so.5()(64bit) libQt5Core.so.5(libQt5Core.so.5)(64bit) libQt5Core.so.5(Qt_5.0)(64bit) libQt5Core.so.5(Qt_5.1)(64bit) libQt5Core.so.5(Qt_5.2)(64bit) libQt5Core.so.5(Qt_5.3)(64bit) libQt5Core.so.5(Qt_5.4)(64bit) libQt5Core.so.5(Qt_5.5)(64bit) libQt5Core.so.5(Qt_5)(64bit) Therefore, automatic dependency resolution would have the information it needs to conclude that the application requires Qt >= 5.5. Change-Id: I049a653beeb5454c9539ffff13e3fec9aeb50197 Reviewed-by: Oswald Buddenhagen Reviewed-by: Thiago Macieira --- src/corelib/global/global.pri | 3 +- src/corelib/global/qversiontagging.cpp | 62 ++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 src/corelib/global/qversiontagging.cpp (limited to 'src') diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri index 43f3a86544..8ecde5a769 100644 --- a/src/corelib/global/global.pri +++ b/src/corelib/global/global.pri @@ -27,7 +27,8 @@ SOURCES += \ global/qmalloc.cpp \ global/qnumeric.cpp \ global/qlogging.cpp \ - global/qhooks.cpp + global/qhooks.cpp \ + global/qversiontagging.cpp # qlibraryinfo.cpp includes qconfig.cpp INCLUDEPATH += $$QT_BUILD_TREE/src/corelib/global diff --git a/src/corelib/global/qversiontagging.cpp b/src/corelib/global/qversiontagging.cpp new file mode 100644 index 0000000000..e3d9efa16b --- /dev/null +++ b/src/corelib/global/qversiontagging.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Intel Corporation. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qglobal.h" + +#if defined(Q_CC_GNU) && defined(Q_OS_LINUX) && defined(Q_PROCESSOR_X86) && !defined(QT_STATIC) +# define SYM QT_MANGLE_NAMESPACE(qt_version_tag) +# define SSYM QT_STRINGIFY(SYM) + +asm( +// ASM macro that makes one ELF versioned symbol qt_version_tag{sep}Qt_{major}.{minor} +// that is an alias to qt_version_tag_{major}_{minor}. +// The {sep} parameter must be @ for all old versions and @@ for the current version. +".macro make_one_tag major minor sep\n" +".globl " SSYM "_\\major\\()_\\minor\n" // make the symbol global +SSYM "_\\major\\()_\\minor:\n" // declare it +" .symver " SSYM "_\\major\\()_\\minor, " SSYM "\\sep\\()Qt_\\major\\().\\minor\n" +".endm\n" + +".altmacro\n" +".bss\n" +".set qt_version_major, " QT_STRINGIFY(QT_VERSION) " >> 16\n" // set qt_version_major +".set qt_version_minor, 0\n" // set qt_version_minor to 0 (it will grow to the current) +".rept (" QT_STRINGIFY(QT_VERSION) " >> 8) & 0xff\n" // repeat minor version times (0 to N-1) +" make_one_tag %qt_version_major, %qt_version_minor, @\n" +" .set qt_version_minor, (qt_version_minor + 1)\n" +".endr\n" +" make_one_tag %qt_version_major, %qt_version_minor, @@\n" // call the macro for the current version +" .space 1\n" // variable is 1 byte, value 0 +); + +#endif -- cgit v1.2.3 From b3b1722d1fbee8168264072cf867d8b47c1eac82 Mon Sep 17 00:00:00 2001 From: Samuel Nevala Date: Thu, 10 Sep 2015 12:17:44 +0300 Subject: winrt: Fix capabilities query. Windows Runtime port supports non-fullscreen and multiple windows. Change-Id: I6f4791a7c329ece88e5f6f9910f3635a7bfef3f8 Reviewed-by: Andrew Knight --- src/plugins/platforms/winrt/qwinrtintegration.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp index 7079d46523..fce77c56d1 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.cpp +++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp @@ -188,9 +188,9 @@ bool QWinRTIntegration::hasCapability(QPlatformIntegration::Capability cap) cons case ThreadedPixmaps: case OpenGL: case ApplicationState: - return true; case NonFullScreenWindows: - return false; + case MultipleWindows: + return true; default: return QPlatformIntegration::hasCapability(cap); } -- cgit v1.2.3 From 6272e8829656c3f13323b83ae1b315aaace783d5 Mon Sep 17 00:00:00 2001 From: Samuel Nevala Date: Thu, 10 Sep 2015 13:13:56 +0300 Subject: winrt: Remove unnecessary assert from window. Change-Id: I38593c63121e75e5d4a18e715d41c6ce5519e596 Reviewed-by: Andrew Knight --- src/plugins/platforms/winrt/qwinrtwindow.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/winrt/qwinrtwindow.cpp b/src/plugins/platforms/winrt/qwinrtwindow.cpp index cebc9e15c2..5ff1c8bd19 100644 --- a/src/plugins/platforms/winrt/qwinrtwindow.cpp +++ b/src/plugins/platforms/winrt/qwinrtwindow.cpp @@ -158,8 +158,6 @@ QWinRTWindow::~QWinRTWindow() Q_ASSERT_SUCCEEDED(hr); ComPtr> children; hr = panel->get_Children(&children); - Q_ASSERT_SUCCEEDED(hr); - Q_ASSERT_SUCCEEDED(hr); quint32 index; boolean found; -- cgit v1.2.3 From 65efeb6f9d0e447df4e0b5b2e4d64954ddd2fdfa Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 8 Sep 2015 16:53:16 +0200 Subject: QImage: Inline constScanLine call in pixel() Calling constScanLine() is an extra function call, just for doing "data + y * width". Also, we are checking d again, even though we already know it's there. The constScanLine() call is responsible for up to 15% of the total CPU time spent in pixel(). Change-Id: Ia7a8e0a6d62fb257d1b22d91f062b66e9cfd349a Reviewed-by: Allan Sandfeld Jensen --- src/gui/image/qimage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 6af1580641..7f2504ddd9 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -2214,7 +2214,7 @@ QRgb QImage::pixel(int x, int y) const return 12345; } - const uchar * s = constScanLine(y); + const uchar *s = d->data + y * d->bytes_per_line; switch(d->format) { case Format_Mono: return d->colortable.at((*(s + (x >> 3)) >> (~x & 7)) & 1); -- cgit v1.2.3 From a8bc96e9e5d18908d266e3dc614c00f25a0c2013 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Fri, 10 Jul 2015 16:10:44 +0200 Subject: QAbstractSocket: Consolidate error reporting Introduce the methods setError(), setErrorAndEmit() to consistently set the internal error state. Change-Id: I4ff951d100cf5e9f9a7e27135bb52188cde99853 Reviewed-by: Alex Trotsenko Reviewed-by: Thiago Macieira --- src/network/socket/qabstractsocket.cpp | 110 ++++++++++++++++----------------- src/network/socket/qabstractsocket_p.h | 3 + src/network/socket/qudpsocket.cpp | 11 +--- src/network/ssl/qsslsocket.cpp | 21 +++---- src/network/ssl/qsslsocket_mac.cpp | 70 +++++++++------------ src/network/ssl/qsslsocket_mac_p.h | 7 --- src/network/ssl/qsslsocket_openssl.cpp | 69 ++++++++------------- src/network/ssl/qsslsocket_winrt.cpp | 30 +++------ 8 files changed, 133 insertions(+), 188 deletions(-) (limited to 'src') diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index d1b13c1191..75da64468f 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -630,8 +630,8 @@ bool QAbstractSocketPrivate::initSocketLayer(QAbstractSocket::NetworkLayerProtoc resetSocketLayer(); socketEngine = QAbstractSocketEngine::createSocketEngine(q->socketType(), proxyInUse, q); if (!socketEngine) { - socketError = QAbstractSocket::UnsupportedSocketOperationError; - q->setErrorString(QAbstractSocket::tr("Operation on socket is not supported")); + setError(QAbstractSocket::UnsupportedSocketOperationError, + QAbstractSocket::tr("Operation on socket is not supported")); return false; } #ifndef QT_NO_BEARERMANAGEMENT @@ -644,8 +644,7 @@ bool QAbstractSocketPrivate::initSocketLayer(QAbstractSocket::NetworkLayerProtoc typeStr.toLatin1().constData(), protocolStr.toLatin1().constData(), socketEngine->errorString().toLatin1().constData()); #endif - socketError = socketEngine->error(); - q->setErrorString(socketEngine->errorString()); + setError(socketEngine->error(), socketEngine->errorString()); return false; } @@ -890,12 +889,10 @@ bool QAbstractSocketPrivate::flush() // Attempt to write it all in one chunk. qint64 written = socketEngine->write(ptr, nextSize); if (written < 0) { - socketError = socketEngine->error(); - q->setErrorString(socketEngine->errorString()); #if defined (QABSTRACTSOCKET_DEBUG) qDebug() << "QAbstractSocketPrivate::flush() write error, aborting." << socketEngine->errorString(); #endif - emit q->error(socketError); + setErrorAndEmit(socketEngine->error(), socketEngine->errorString()); // an unexpected error so close the socket. q->abort(); return false; @@ -997,8 +994,7 @@ void QAbstractSocketPrivate::startConnectingByName(const QString &host) } // failed to connect - socketError = socketEngine->error(); - q->setErrorString(socketEngine->errorString()); + setError(socketEngine->error(), socketEngine->errorString()); } state = QAbstractSocket::UnconnectedState; @@ -1057,8 +1053,7 @@ void QAbstractSocketPrivate::_q_startConnecting(const QHostInfo &hostInfo) qDebug("QAbstractSocketPrivate::_q_startConnecting(), host not found"); #endif state = QAbstractSocket::UnconnectedState; - socketError = QAbstractSocket::HostNotFoundError; - q->setErrorString(QAbstractSocket::tr("Host not found")); + setError(QAbstractSocket::HostNotFoundError, QAbstractSocket::tr("Host not found")); emit q->stateChanged(state); emit q->error(QAbstractSocket::HostNotFoundError); return; @@ -1107,11 +1102,10 @@ void QAbstractSocketPrivate::_q_connectToNextAddress() || socketEngine->error() == QAbstractSocket::UnsupportedSocketOperationError #endif ) && socketEngine->state() == QAbstractSocket::ConnectingState) { - socketError = QAbstractSocket::ConnectionRefusedError; - q->setErrorString(QAbstractSocket::tr("Connection refused")); + setError(QAbstractSocket::ConnectionRefusedError, + QAbstractSocket::tr("Connection refused")); } else { - socketError = socketEngine->error(); - q->setErrorString(socketEngine->errorString()); + setError(socketEngine->error(), socketEngine->errorString()); } } else { // socketError = QAbstractSocket::ConnectionRefusedError; @@ -1235,8 +1229,8 @@ void QAbstractSocketPrivate::_q_abortConnectionAttempt() if (addresses.isEmpty()) { state = QAbstractSocket::UnconnectedState; - socketError = QAbstractSocket::SocketTimeoutError; - q->setErrorString(QAbstractSocket::tr("Connection timed out")); + setError(QAbstractSocket::SocketTimeoutError, + QAbstractSocket::tr("Connection timed out")); emit q->stateChanged(state); emit q->error(socketError); } else { @@ -1260,7 +1254,6 @@ void QAbstractSocketPrivate::_q_forceDisconnect() */ bool QAbstractSocketPrivate::readFromSocket() { - Q_Q(QAbstractSocket); // Find how many bytes we can read from the socket layer. qint64 bytesToRead = socketEngine->bytesAvailable(); if (bytesToRead == 0) { @@ -1296,9 +1289,7 @@ bool QAbstractSocketPrivate::readFromSocket() #endif if (!socketEngine->isValid()) { - socketError = socketEngine->error(); - q->setErrorString(socketEngine->errorString()); - emit q->error(socketError); + setErrorAndEmit(socketEngine->error(), socketEngine->errorString()); #if defined(QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::readFromSocket() read failed: %s", q->errorString().toLatin1().constData()); @@ -1368,6 +1359,31 @@ QAbstractSocketEngine* QAbstractSocketPrivate::getSocketEngine(QAbstractSocket * return socket->d_func()->socketEngine; } +/*! + \internal + + Sets the socket error state to \c errorCode and \a errorString. +*/ +void QAbstractSocketPrivate::setError(QAbstractSocket::SocketError errorCode, + const QString &errStr) +{ + socketError = errorCode; + errorString = errStr; +} + +/*! + \internal + + Sets the socket error state to \c errorCode and \a errorString, + and emits the QAbstractSocket::error() signal. +*/ +void QAbstractSocketPrivate::setErrorAndEmit(QAbstractSocket::SocketError errorCode, + const QString &errorString) +{ + Q_Q(QAbstractSocket); + setError(errorCode, errorString); + emit q->error(errorCode); +} /*! \internal @@ -1532,9 +1548,7 @@ bool QAbstractSocketPrivate::bind(const QHostAddress &address, quint16 port, QAb cachedSocketDescriptor = socketEngine->socketDescriptor(); if (!result) { - socketError = socketEngine->error(); - q->setErrorString(socketEngine->errorString()); - emit q->error(socketError); + setErrorAndEmit(socketEngine->error(), socketEngine->errorString()); return false; } @@ -1611,9 +1625,7 @@ void QAbstractSocket::connectToHost(const QString &hostName, quint16 port, if (d->state == ConnectedState || d->state == ConnectingState || d->state == ClosingState || d->state == HostLookupState) { qWarning("QAbstractSocket::connectToHost() called when already looking up or connecting/connected to \"%s\"", qPrintable(hostName)); - d->socketError = QAbstractSocket::OperationError; - setErrorString(QAbstractSocket::tr("Trying to connect while connection is in progress")); - emit error(d->socketError); + d->setErrorAndEmit(OperationError, tr("Trying to connect while connection is in progress")); return; } @@ -1642,9 +1654,8 @@ void QAbstractSocket::connectToHost(const QString &hostName, quint16 port, d->resolveProxy(hostName, port); if (d->proxyInUse.type() == QNetworkProxy::DefaultProxy) { // failed to setup the proxy - d->socketError = QAbstractSocket::UnsupportedSocketOperationError; - setErrorString(QAbstractSocket::tr("Operation on socket is not supported")); - emit error(d->socketError); + d->setErrorAndEmit(UnsupportedSocketOperationError, + tr("Operation on socket is not supported")); return; } #endif @@ -1864,8 +1875,7 @@ bool QAbstractSocket::setSocketDescriptor(qintptr socketDescriptor, SocketState d->buffer.clear(); d->socketEngine = QAbstractSocketEngine::createSocketEngine(socketDescriptor, this); if (!d->socketEngine) { - d->socketError = UnsupportedSocketOperationError; - setErrorString(tr("Operation on socket is not supported")); + d->setError(UnsupportedSocketOperationError, tr("Operation on socket is not supported")); return false; } #ifndef QT_NO_BEARERMANAGEMENT @@ -1874,8 +1884,7 @@ bool QAbstractSocket::setSocketDescriptor(qintptr socketDescriptor, SocketState #endif bool result = d->socketEngine->initialize(socketDescriptor, socketState); if (!result) { - d->socketError = d->socketEngine->error(); - setErrorString(d->socketEngine->errorString()); + d->setError(d->socketEngine->error(), d->socketEngine->errorString()); return false; } @@ -2085,8 +2094,7 @@ bool QAbstractSocket::waitForConnected(int msecs) } if ((timedOut && state() != ConnectedState) || state() == ConnectingState) { - d->socketError = SocketTimeoutError; - setErrorString(tr("Socket operation timed out")); + d->setError(SocketTimeoutError, tr("Socket operation timed out")); d->state = UnconnectedState; emit stateChanged(d->state); d->resetSocketLayer(); @@ -2148,13 +2156,11 @@ bool QAbstractSocket::waitForReadyRead(int msecs) bool readyToWrite = false; if (!d->socketEngine->waitForReadOrWrite(&readyToRead, &readyToWrite, true, !d->writeBuffer.isEmpty(), qt_subtract_from_timeout(msecs, stopWatch.elapsed()))) { - d->socketError = d->socketEngine->error(); - setErrorString(d->socketEngine->errorString()); #if defined (QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocket::waitForReadyRead(%i) failed (%i, %s)", - msecs, d->socketError, errorString().toLatin1().constData()); + msecs, d->socketEngine->error(), d->socketEngine->errorString().toLatin1().constData()); #endif - emit error(d->socketError); + d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString()); if (d->socketError != SocketTimeoutError) close(); return false; @@ -2220,13 +2226,11 @@ bool QAbstractSocket::waitForBytesWritten(int msecs) bool readyToWrite = false; if (!d->socketEngine->waitForReadOrWrite(&readyToRead, &readyToWrite, true, !d->writeBuffer.isEmpty(), qt_subtract_from_timeout(msecs, stopWatch.elapsed()))) { - d->socketError = d->socketEngine->error(); - setErrorString(d->socketEngine->errorString()); #if defined (QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocket::waitForBytesWritten(%i) failed (%i, %s)", - msecs, d->socketError, errorString().toLatin1().constData()); + msecs, d->socketEngine->error(), d->socketEngine->errorString().toLatin1().constData()); #endif - emit error(d->socketError); + d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString()); if (d->socketError != SocketTimeoutError) close(); return false; @@ -2302,13 +2306,11 @@ bool QAbstractSocket::waitForDisconnected(int msecs) if (!d->socketEngine->waitForReadOrWrite(&readyToRead, &readyToWrite, state() == ConnectedState, !d->writeBuffer.isEmpty(), qt_subtract_from_timeout(msecs, stopWatch.elapsed()))) { - d->socketError = d->socketEngine->error(); - setErrorString(d->socketEngine->errorString()); #if defined (QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocket::waitForReadyRead(%i) failed (%i, %s)", - msecs, d->socketError, errorString().toLatin1().constData()); + msecs, d->socketEngine->error(), d->socketEngine->errorString().toLatin1().constData()); #endif - emit error(d->socketError); + d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString()); if (d->socketError != SocketTimeoutError) close(); return false; @@ -2439,8 +2441,7 @@ qint64 QAbstractSocket::readData(char *data, qint64 maxSize) // -2 from the engine means no bytes available (EAGAIN) so read more later return 0; } else if (readBytes < 0) { - d->socketError = d->socketEngine->error(); - setErrorString(d->socketEngine->errorString()); + d->setError(d->socketEngine->error(), d->socketEngine->errorString()); d->resetSocketLayer(); d->state = QAbstractSocket::UnconnectedState; } else if (!d->socketEngine->isReadNotificationEnabled()) { @@ -2470,8 +2471,7 @@ qint64 QAbstractSocket::writeData(const char *data, qint64 size) { Q_D(QAbstractSocket); if (d->state == QAbstractSocket::UnconnectedState) { - d->socketError = QAbstractSocket::UnknownSocketError; - setErrorString(tr("Socket is not connected")); + d->setError(UnknownSocketError, tr("Socket is not connected")); return -1; } @@ -2479,8 +2479,7 @@ qint64 QAbstractSocket::writeData(const char *data, qint64 size) // This code is for the new Unbuffered QTcpSocket use case qint64 written = d->socketEngine->write(data, size); if (written < 0) { - d->socketError = d->socketEngine->error(); - setErrorString(d->socketEngine->errorString()); + d->setError(d->socketEngine->error(), d->socketEngine->errorString()); return written; } else if (written < size) { // Buffer what was not written yet @@ -2494,8 +2493,7 @@ qint64 QAbstractSocket::writeData(const char *data, qint64 size) // This is for a QUdpSocket that was connect()ed qint64 written = d->socketEngine->write(data, size); if (written < 0) { - d->socketError = d->socketEngine->error(); - setErrorString(d->socketEngine->errorString()); + d->setError(d->socketEngine->error(), d->socketEngine->errorString()); } else if (!d->writeBuffer.isEmpty()) { d->socketEngine->setWriteNotificationEnabled(true); } diff --git a/src/network/socket/qabstractsocket_p.h b/src/network/socket/qabstractsocket_p.h index 85e82aef47..a905625b19 100644 --- a/src/network/socket/qabstractsocket_p.h +++ b/src/network/socket/qabstractsocket_p.h @@ -136,6 +136,9 @@ public: void setupSocketNotifiers(); bool readFromSocket(); + void setError(QAbstractSocket::SocketError errorCode, const QString &errorString); + void setErrorAndEmit(QAbstractSocket::SocketError errorCode, const QString &errorString); + qint64 readBufferMaxSize; QRingBuffer writeBuffer; diff --git a/src/network/socket/qudpsocket.cpp b/src/network/socket/qudpsocket.cpp index f4e7d20b03..a46e6ade04 100644 --- a/src/network/socket/qudpsocket.cpp +++ b/src/network/socket/qudpsocket.cpp @@ -339,9 +339,7 @@ qint64 QUdpSocket::writeDatagram(const char *data, qint64 size, const QHostAddre if (sent >= 0) { emit bytesWritten(sent); } else { - d->socketError = d->socketEngine->error(); - setErrorString(d->socketEngine->errorString()); - emit error(d->socketError); + d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString()); } return sent; } @@ -394,11 +392,8 @@ qint64 QUdpSocket::readDatagram(char *data, qint64 maxSize, QHostAddress *addres } d_func()->socketEngine->setReadNotificationEnabled(true); - if (readBytes < 0) { - d->socketError = d->socketEngine->error(); - setErrorString(d->socketEngine->errorString()); - emit error(d->socketError); - } + if (readBytes < 0) + d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString()); return readBytes; } #endif // QT_NO_UDPSOCKET diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index 092a414f99..b62cfd2fde 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -499,8 +499,7 @@ bool QSslSocket::setSocketDescriptor(qintptr socketDescriptor, SocketState state d->createPlainSocket(openMode); bool retVal = d->plainSocket->setSocketDescriptor(socketDescriptor, state, openMode); d->cachedSocketDescriptor = d->plainSocket->socketDescriptor(); - setSocketError(d->plainSocket->error()); - setErrorString(d->plainSocket->errorString()); + d->setError(d->plainSocket->error(), d->plainSocket->errorString()); setSocketState(state); setOpenMode(openMode); setLocalPort(d->plainSocket->localPort()); @@ -1532,8 +1531,7 @@ bool QSslSocket::waitForConnected(int msecs) bool retVal = d->plainSocket->waitForConnected(msecs); if (!retVal) { setSocketState(d->plainSocket->state()); - setSocketError(d->plainSocket->error()); - setErrorString(d->plainSocket->errorString()); + d->setError(d->plainSocket->error(), d->plainSocket->errorString()); } return retVal; } @@ -1688,8 +1686,7 @@ bool QSslSocket::waitForDisconnected(int msecs) bool retVal = d->plainSocket->waitForDisconnected(qt_subtract_from_timeout(msecs, stopWatch.elapsed())); if (!retVal) { setSocketState(d->plainSocket->state()); - setSocketError(d->plainSocket->error()); - setErrorString(d->plainSocket->errorString()); + d->setError(d->plainSocket->error(), d->plainSocket->errorString()); } return retVal; } @@ -2402,8 +2399,9 @@ void QSslSocketPrivate::_q_stateChangedSlot(QAbstractSocket::SocketState state) */ void QSslSocketPrivate::_q_errorSlot(QAbstractSocket::SocketError error) { - Q_Q(QSslSocket); + Q_UNUSED(error) #ifdef QSSLSOCKET_DEBUG + Q_Q(QSslSocket); qCDebug(lcSsl) << "QSslSocket::_q_errorSlot(" << error << ')'; qCDebug(lcSsl) << "\tstate =" << q->state(); qCDebug(lcSsl) << "\terrorString =" << q->errorString(); @@ -2416,9 +2414,7 @@ void QSslSocketPrivate::_q_errorSlot(QAbstractSocket::SocketError error) readBufferMaxSize = tmpReadBufferMaxSize; } - q->setSocketError(plainSocket->error()); - q->setErrorString(plainSocket->errorString()); - emit q->error(error); + setErrorAndEmit(plainSocket->error(), plainSocket->errorString()); } /*! @@ -2483,7 +2479,6 @@ void QSslSocketPrivate::_q_flushReadBuffer() */ void QSslSocketPrivate::_q_resumeImplementation() { - Q_Q(QSslSocket); if (plainSocket) plainSocket->resume(); paused = false; @@ -2491,9 +2486,7 @@ void QSslSocketPrivate::_q_resumeImplementation() if (verifyErrorsHaveBeenIgnored()) { continueHandshake(); } else { - q->setErrorString(sslErrors.first().errorString()); - q->setSocketError(QAbstractSocket::SslHandshakeFailedError); - emit q->error(QAbstractSocket::SslHandshakeFailedError); + setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, sslErrors.first().errorString()); plainSocket->disconnectFromHost(); return; } diff --git a/src/network/ssl/qsslsocket_mac.cpp b/src/network/ssl/qsslsocket_mac.cpp index b83e56c29e..759aee7485 100644 --- a/src/network/ssl/qsslsocket_mac.cpp +++ b/src/network/ssl/qsslsocket_mac.cpp @@ -318,7 +318,7 @@ void QSslSocketBackendPrivate::startClientEncryption() // Error description/code were set, 'error' emitted // by initSslContext, but OpenSSL socket also sets error // emits a signal twice, so ... - setError("Unable to init SSL Context", QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, "Unable to init SSL Context"); return; } @@ -331,7 +331,7 @@ void QSslSocketBackendPrivate::startServerEncryption() // Error description/code were set, 'error' emitted // by initSslContext, but OpenSSL socket also sets error // emits a signal twice, so ... - setError("Unable to init SSL Context", QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, "Unable to init SSL Context"); return; } @@ -360,8 +360,8 @@ void QSslSocketBackendPrivate::transmit() qCDebug(lcSsl) << plainSocket << "SSLWrite returned" << err; #endif if (err != noErr && err != errSSLWouldBlock) { - setError(QStringLiteral("SSLWrite failed: %1").arg(err), - QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QStringLiteral("SSLWrite failed: %1").arg(err)); break; } @@ -395,12 +395,12 @@ void QSslSocketBackendPrivate::transmit() #endif if (err == errSSLClosedGraceful) { shutdown = true; // the other side shut down, make sure we do not send shutdown ourselves - setError(QSslSocket::tr("The TLS/SSL connection has been closed"), - QAbstractSocket::RemoteHostClosedError); + setErrorAndEmit(QAbstractSocket::RemoteHostClosedError, + QSslSocket::tr("The TLS/SSL connection has been closed")); break; } else if (err != noErr && err != errSSLWouldBlock) { - setError(QStringLiteral("SSLRead failed: %1").arg(err), - QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QStringLiteral("SSLRead failed: %1").arg(err)); break; } @@ -658,7 +658,7 @@ bool QSslSocketBackendPrivate::initSslContext() context = SSLCreateContext(Q_NULLPTR, side, kSSLStreamType); if (!context) { - setError("SSLCreateContext failed", QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, "SSLCreateContext failed"); return false; } @@ -666,8 +666,8 @@ bool QSslSocketBackendPrivate::initSslContext() reinterpret_cast(&_q_SSLWrite)); if (err != noErr) { destroySslContext(); - setError(QStringLiteral("SSLSetIOFuncs failed: %1").arg(err), - QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QStringLiteral("SSLSetIOFuncs failed: %1").arg(err)); return false; } @@ -679,14 +679,14 @@ bool QSslSocketBackendPrivate::initSslContext() QAbstractSocket::SocketError errorCode = QAbstractSocket::UnknownSocketError; if (!setSessionCertificate(errorDescription, errorCode)) { destroySslContext(); - setError(errorDescription, errorCode); + setErrorAndEmit(errorCode, errorDescription); return false; } } if (!setSessionProtocol()) { destroySslContext(); - setError("Failed to set protocol version", QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, "Failed to set protocol version"); return false; } @@ -698,8 +698,8 @@ bool QSslSocketBackendPrivate::initSslContext() const OSStatus err = SSLSetEnableCertVerify(context, false); if (err != noErr) { destroySslContext(); - setError(QStringLiteral("SSLSetEnableCertVerify failed: %1").arg(err), - QSslSocket::SslInternalError); + setErrorAndEmit(QSslSocket::SslInternalError, + QStringLiteral("SSLSetEnableCertVerify failed: %1").arg(err)); return false; } } @@ -720,8 +720,8 @@ bool QSslSocketBackendPrivate::initSslContext() if (err != noErr) { destroySslContext(); - setError(QStringLiteral("SSLSetSessionOption failed: %1").arg(err), - QSslSocket::SslInternalError); + setErrorAndEmit(QSslSocket::SslInternalError, + QStringLiteral("SSLSetSessionOption failed: %1").arg(err)); return false; } // @@ -737,8 +737,8 @@ bool QSslSocketBackendPrivate::initSslContext() if (err != noErr) { destroySslContext(); - setError(QStringLiteral("failed to set SSL context option in server mode: %1").arg(err), - QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QStringLiteral("failed to set SSL context option in server mode: %1").arg(err)); return false; } } @@ -981,8 +981,8 @@ bool QSslSocketBackendPrivate::verifyPeerTrust() // !trust - SSLCopyPeerTrust can return noErr but null trust. if (err != noErr || !trust) { if (!canIgnoreVerify) { - setError(QStringLiteral("Failed to obtain peer trust: %1").arg(err), - QAbstractSocket::SslHandshakeFailedError); + setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, + QStringLiteral("Failed to obtain peer trust: %1").arg(err)); plainSocket->disconnectFromHost(); return false; } else { @@ -1005,8 +1005,8 @@ bool QSslSocketBackendPrivate::verifyPeerTrust() if (err != noErr) { // We can not ignore this, it's not even about trust verification // probably ... - setError(QStringLiteral("SecTrustEvaluate failed: %1").arg(err), - QAbstractSocket::SslHandshakeFailedError); + setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, + QStringLiteral("SecTrustEvaluate failed: %1").arg(err)); plainSocket->disconnectFromHost(); return false; } @@ -1124,8 +1124,8 @@ bool QSslSocketBackendPrivate::checkSslErrors() pauseSocketNotifiers(q); paused = true; } else { - setError(sslErrors.first().errorString(), - QAbstractSocket::SslHandshakeFailedError); + setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, + sslErrors.first().errorString()); plainSocket->disconnectFromHost(); } return false; @@ -1162,7 +1162,7 @@ bool QSslSocketBackendPrivate::startHandshake() // setSessionCertificate does not fail if we have no certificate. // Failure means a real error (invalid certificate, no private key, etc). if (!setSessionCertificate(errorDescription, errorCode)) { - setError(errorDescription, errorCode); + setErrorAndEmit(errorCode, errorDescription); return false; } else { // We try to resume a handshake, even if have no @@ -1177,8 +1177,8 @@ bool QSslSocketBackendPrivate::startHandshake() return startHandshake(); } - setError(QStringLiteral("SSLHandshake failed: %1").arg(err), - QAbstractSocket::SslHandshakeFailedError); + setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, + QStringLiteral("SSLHandshake failed: %1").arg(err)); plainSocket->disconnectFromHost(); return false; } @@ -1192,8 +1192,8 @@ bool QSslSocketBackendPrivate::startHandshake() // check protocol version ourselves, as Secure Transport does not enforce // the requested min / max versions. if (!verifySessionProtocol()) { - setError("Protocol version mismatch", - QAbstractSocket::SslHandshakeFailedError); + setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, + "Protocol version mismatch"); plainSocket->disconnectFromHost(); return false; } @@ -1206,16 +1206,6 @@ bool QSslSocketBackendPrivate::startHandshake() } } -void QSslSocketBackendPrivate::setError(const QString &errorString, - QAbstractSocket::SocketError errorCode) -{ - Q_Q(QSslSocket); - - q->setErrorString(errorString); - q->setSocketError(errorCode); - emit q->error(errorCode); -} - /* PKCS12 helpers. */ diff --git a/src/network/ssl/qsslsocket_mac_p.h b/src/network/ssl/qsslsocket_mac_p.h index 868b816957..414c155882 100644 --- a/src/network/ssl/qsslsocket_mac_p.h +++ b/src/network/ssl/qsslsocket_mac_p.h @@ -101,13 +101,6 @@ private: bool checkSslErrors(); bool startHandshake(); - // Aux. function, sets: - //1) socket error code, - //2) error string (description) - //3) emits a signal. - void setError(const QString &errorString, - QAbstractSocket::SocketError errorCode); - mutable QCFType context; Q_DISABLE_COPY(QSslSocketBackendPrivate); diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 8e1d0c13b1..0a4c68d7c0 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -364,9 +364,7 @@ bool QSslSocketBackendPrivate::initSslContext() } if (sslContextPointer->error() != QSslError::NoError) { - q->setErrorString(sslContextPointer->errorString()); - q->setSocketError(QAbstractSocket::SslInvalidUserDataError); - emit q->error(QAbstractSocket::SslInvalidUserDataError); + setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError, sslContextPointer->errorString()); sslContextPointer.clear(); // deletes the QSslContext return false; } @@ -374,9 +372,8 @@ bool QSslSocketBackendPrivate::initSslContext() // Create and initialize SSL session if (!(ssl = sslContextPointer->createSsl())) { // ### Bad error code - q->setErrorString(QSslSocket::tr("Error creating SSL session, %1").arg(getErrorsFromOpenSsl())); - q->setSocketError(QAbstractSocket::SslInternalError); - emit q->error(QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QSslSocket::tr("Error creating SSL session, %1").arg(getErrorsFromOpenSsl())); return false; } @@ -405,9 +402,8 @@ bool QSslSocketBackendPrivate::initSslContext() readBio = q_BIO_new(q_BIO_s_mem()); writeBio = q_BIO_new(q_BIO_s_mem()); if (!readBio || !writeBio) { - q->setErrorString(QSslSocket::tr("Error creating SSL session: %1").arg(getErrorsFromOpenSsl())); - q->setSocketError(QAbstractSocket::SslInternalError); - emit q->error(QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QSslSocket::tr("Error creating SSL session: %1").arg(getErrorsFromOpenSsl())); return false; } @@ -808,11 +804,9 @@ QList QSslSocketPrivate::systemCaCertificates() void QSslSocketBackendPrivate::startClientEncryption() { - Q_Q(QSslSocket); if (!initSslContext()) { - q->setErrorString(QSslSocket::tr("Unable to init SSL Context: %1").arg(getErrorsFromOpenSsl())); - q->setSocketError(QAbstractSocket::SslInternalError); - emit q->error(QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QSslSocket::tr("Unable to init SSL Context: %1").arg(getErrorsFromOpenSsl())); return; } @@ -824,11 +818,9 @@ void QSslSocketBackendPrivate::startClientEncryption() void QSslSocketBackendPrivate::startServerEncryption() { - Q_Q(QSslSocket); if (!initSslContext()) { - q->setErrorString(QSslSocket::tr("Unable to init SSL Context: %1").arg(getErrorsFromOpenSsl())); - q->setSocketError(QAbstractSocket::SslInternalError); - emit q->error(QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QSslSocket::tr("Unable to init SSL Context: %1").arg(getErrorsFromOpenSsl())); return; } @@ -874,9 +866,9 @@ void QSslSocketBackendPrivate::transmit() break; } else { // ### Better error handling. - q->setErrorString(QSslSocket::tr("Unable to write data: %1").arg(getErrorsFromOpenSsl())); - q->setSocketError(QAbstractSocket::SslInternalError); - emit q->error(QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QSslSocket::tr("Unable to write data: %1").arg( + getErrorsFromOpenSsl())); return; } } @@ -918,9 +910,7 @@ void QSslSocketBackendPrivate::transmit() #endif if (actualWritten < 0) { //plain socket write fails if it was in the pending close state. - q->setErrorString(plainSocket->errorString()); - q->setSocketError(plainSocket->error()); - emit q->error(plainSocket->error()); + setErrorAndEmit(plainSocket->error(), plainSocket->errorString()); return; } transmitting = true; @@ -946,9 +936,9 @@ void QSslSocketBackendPrivate::transmit() plainSocket->read(data.data(), writtenToBio); } else { // ### Better error handling. - q->setErrorString(QSslSocket::tr("Unable to decrypt data: %1").arg(getErrorsFromOpenSsl())); - q->setSocketError(QAbstractSocket::SslInternalError); - emit q->error(QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QSslSocket::tr("Unable to decrypt data: %1").arg( + getErrorsFromOpenSsl())); return; } @@ -1022,17 +1012,15 @@ void QSslSocketBackendPrivate::transmit() qCDebug(lcSsl) << "QSslSocketBackendPrivate::transmit: remote disconnect"; #endif shutdown = true; // the other side shut down, make sure we do not send shutdown ourselves - q->setErrorString(QSslSocket::tr("The TLS/SSL connection has been closed")); - q->setSocketError(QAbstractSocket::RemoteHostClosedError); - emit q->error(QAbstractSocket::RemoteHostClosedError); + setErrorAndEmit(QAbstractSocket::RemoteHostClosedError, + QSslSocket::tr("The TLS/SSL connection has been closed")); return; case SSL_ERROR_SYSCALL: // some IO error case SSL_ERROR_SSL: // error in the SSL library // we do not know exactly what the error is, nor whether we can recover from it, // so just return to prevent an endless loop in the outer "while" statement - q->setErrorString(QSslSocket::tr("Error while reading: %1").arg(getErrorsFromOpenSsl())); - q->setSocketError(QAbstractSocket::SslInternalError); - emit q->error(QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QSslSocket::tr("Error while reading: %1").arg(getErrorsFromOpenSsl())); return; default: // SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT: can only happen with a @@ -1040,9 +1028,8 @@ void QSslSocketBackendPrivate::transmit() // SSL_ERROR_WANT_X509_LOOKUP: can only happen with a // SSL_CTX_set_client_cert_cb(), which we do not call. // So this default case should never be triggered. - q->setErrorString(QSslSocket::tr("Error while reading: %1").arg(getErrorsFromOpenSsl())); - q->setSocketError(QAbstractSocket::SslInternalError); - emit q->error(QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QSslSocket::tr("Error while reading: %1").arg(getErrorsFromOpenSsl())); break; } } while (ssl && readBytes > 0); @@ -1134,12 +1121,12 @@ bool QSslSocketBackendPrivate::startHandshake() // The handshake is not yet complete. break; default: - q->setErrorString(QSslSocket::tr("Error during SSL handshake: %1").arg(getErrorsFromOpenSsl())); - q->setSocketError(QAbstractSocket::SslHandshakeFailedError); + QString errorString + = QSslSocket::tr("Error during SSL handshake: %1").arg(getErrorsFromOpenSsl()); #ifdef QSSLSOCKET_DEBUG - qCDebug(lcSsl) << "QSslSocketBackendPrivate::startHandshake: error!" << q->errorString(); + qCDebug(lcSsl) << "QSslSocketBackendPrivate::startHandshake: error!" << errorString; #endif - emit q->error(QAbstractSocket::SslHandshakeFailedError); + setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, errorString); q->abort(); } return false; @@ -1290,9 +1277,7 @@ bool QSslSocketBackendPrivate::checkSslErrors() pauseSocketNotifiers(q); paused = true; } else { - q->setErrorString(sslErrors.first().errorString()); - q->setSocketError(QAbstractSocket::SslHandshakeFailedError); - emit q->error(QAbstractSocket::SslHandshakeFailedError); + setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, sslErrors.first().errorString()); plainSocket->disconnectFromHost(); } return false; diff --git a/src/network/ssl/qsslsocket_winrt.cpp b/src/network/ssl/qsslsocket_winrt.cpp index aba3ea8170..b03f234d49 100644 --- a/src/network/ssl/qsslsocket_winrt.cpp +++ b/src/network/ssl/qsslsocket_winrt.cpp @@ -251,9 +251,8 @@ void QSslSocketBackendPrivate::startClientEncryption() case QSsl::TlsV1_2OrLater: // TlsV1_0OrLater, TlsV1_1OrLater and TlsV1_2OrLater are disabled on WinRT // because there is no good way to map them to the native API. - q->setErrorString(QStringLiteral("unsupported protocol")); - q->setSocketError(QAbstractSocket::SslInvalidUserDataError); - emit q->error(QAbstractSocket::SslInvalidUserDataError); + setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError, + QStringLiteral("unsupported protocol")); return; default: protectionLevel = SocketProtectionLevel_Tls12; // default to highest @@ -347,13 +346,10 @@ QSsl::SslProtocol QSslSocketBackendPrivate::sessionProtocol() const void QSslSocketBackendPrivate::continueHandshake() { - Q_Q(QSslSocket); - IStreamSocket *socket = reinterpret_cast(plainSocket->socketDescriptor()); if (qintptr(socket) == -1) { - q->setErrorString(QStringLiteral("At attempt was made to continue the handshake on an invalid socket.")); - q->setSocketError(QAbstractSocket::SslInternalError); - emit q->error(QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QStringLiteral("At attempt was made to continue the handshake on an invalid socket.")); return; } @@ -372,9 +368,7 @@ void QSslSocketBackendPrivate::continueHandshake() Q_ASSERT_SUCCEEDED(hr); } if (FAILED(hr)) { - q->setErrorString(qt_error_string(hr)); - q->setSocketError(QAbstractSocket::SslInvalidUserDataError); - emit q->error(QAbstractSocket::SslInvalidUserDataError); + setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError, qt_error_string(hr)); return; } @@ -440,10 +434,8 @@ void QSslSocketBackendPrivate::continueHandshake() ComPtr op; hr = socket->UpgradeToSslAsync(protectionLevel, hostName.Get(), &op); if (FAILED(hr)) { - q->setErrorString(QSslSocket::tr("Error creating SSL session: %1") - .arg(qt_error_string(hr))); - q->setSocketError(QAbstractSocket::SslInternalError); - emit q->error(QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QSslSocket::tr("Error creating SSL session: %1").arg(qt_error_string(hr))); return; } @@ -467,9 +459,7 @@ HRESULT QSslSocketBackendPrivate::onSslUpgrade(IAsyncAction *action, AsyncStatus QSet errors; switch (hr) { case SEC_E_INVALID_TOKEN: // Occurs when the server doesn't support the requested protocol - q->setErrorString(qt_error_string(hr)); - q->setSocketError(QAbstractSocket::SslHandshakeFailedError); - emit q->error(QAbstractSocket::SslHandshakeFailedError); + setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, qt_error_string(hr)); q->disconnectFromHost(); return S_OK; default: @@ -628,9 +618,7 @@ HRESULT QSslSocketBackendPrivate::onSslUpgrade(IAsyncAction *action, AsyncStatus if (!sslErrors.isEmpty()) { emit q->sslErrors(sslErrors); - q->setErrorString(sslErrors.first().errorString()); - q->setSocketError(QAbstractSocket::SslHandshakeFailedError); - emit q->error(QAbstractSocket::SslHandshakeFailedError); + setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, sslErrors.first().errorString()); // Disconnect if there are any non-ignorable errors foreach (const QSslError &error, sslErrors) { -- cgit v1.2.3 From f3fd7b3d961ffed480e5851e594f6981f558f486 Mon Sep 17 00:00:00 2001 From: Samuel Nevala Date: Thu, 10 Sep 2015 13:14:57 +0300 Subject: winrt: Move EGL surface to window. Fixes GPU memory leak when window is created/deleted dynamically and repeatedly. EGL context used to own EGL surface, but the context outlives the surface if window is created/deleted dynamically. The EGL surface is now owned by the window and destroyed with it. Change-Id: Ib949261ef6e77217018e60aad3e36e4a6d2eaba0 Reviewed-by: Andrew Knight --- src/plugins/platforms/winrt/qwinrteglcontext.cpp | 30 +++++++---------------- src/plugins/platforms/winrt/qwinrtwindow.cpp | 31 ++++++++++++++++++++++++ src/plugins/platforms/winrt/qwinrtwindow.h | 4 +++ 3 files changed, 44 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/winrt/qwinrteglcontext.cpp b/src/plugins/platforms/winrt/qwinrteglcontext.cpp index 44aab266ca..9cb45336d6 100644 --- a/src/plugins/platforms/winrt/qwinrteglcontext.cpp +++ b/src/plugins/platforms/winrt/qwinrteglcontext.cpp @@ -56,7 +56,6 @@ public: EGLDisplay eglDisplay; EGLConfig eglConfig; EGLContext eglContext; - QHash surfaceForWindow; }; QWinRTEGLContext::QWinRTEGLContext(QOpenGLContext *context) @@ -70,8 +69,6 @@ QWinRTEGLContext::QWinRTEGLContext(QOpenGLContext *context) QWinRTEGLContext::~QWinRTEGLContext() { Q_D(QWinRTEGLContext); - foreach (const EGLSurface &surface, d->surfaceForWindow) - eglDestroySurface(d->eglDisplay, surface); if (d->eglContext != EGL_NO_CONTEXT) eglDestroyContext(d->eglDisplay, d->eglContext); if (d->eglDisplay != EGL_NO_DISPLAY) @@ -112,23 +109,13 @@ bool QWinRTEGLContext::makeCurrent(QPlatformSurface *windowSurface) Q_D(QWinRTEGLContext); Q_ASSERT(windowSurface->surface()->surfaceType() == QSurface::OpenGLSurface); - EGLSurface surface = d->surfaceForWindow.value(windowSurface); - if (surface == EGL_NO_SURFACE) { - QWinRTWindow *window = static_cast(windowSurface); - HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([this, d, window, &surface]() { - surface = eglCreateWindowSurface(d->eglDisplay, d->eglConfig, - reinterpret_cast(window->winId()), - nullptr); - if (surface == EGL_NO_SURFACE) { - qCritical("Failed to create EGL window surface: 0x%x", eglGetError()); - return E_FAIL; - } - return S_OK; - }); - if (FAILED(hr)) - return false; - d->surfaceForWindow.insert(windowSurface, surface); - } + QWinRTWindow *window = static_cast(windowSurface); + if (window->eglSurface() == EGL_NO_SURFACE) + window->createEglSurface(d->eglDisplay, d->eglConfig); + + EGLSurface surface = window->eglSurface(); + if (surface == EGL_NO_SURFACE) + return false; const bool ok = eglMakeCurrent(d->eglDisplay, surface, surface, d->eglContext); if (!ok) { @@ -153,7 +140,8 @@ void QWinRTEGLContext::swapBuffers(QPlatformSurface *windowSurface) Q_D(QWinRTEGLContext); Q_ASSERT(windowSurface->surface()->surfaceType() == QSurface::OpenGLSurface); - eglSwapBuffers(d->eglDisplay, d->surfaceForWindow.value(windowSurface)); + const QWinRTWindow *window = static_cast(windowSurface); + eglSwapBuffers(d->eglDisplay, window->eglSurface()); } QSurfaceFormat QWinRTEGLContext::format() const diff --git a/src/plugins/platforms/winrt/qwinrtwindow.cpp b/src/plugins/platforms/winrt/qwinrtwindow.cpp index 5ff1c8bd19..c5b06a5d8a 100644 --- a/src/plugins/platforms/winrt/qwinrtwindow.cpp +++ b/src/plugins/platforms/winrt/qwinrtwindow.cpp @@ -88,6 +88,8 @@ public: QSurfaceFormat surfaceFormat; QString windowTitle; Qt::WindowState state; + EGLDisplay display; + EGLSurface surface; ComPtr swapChainPanel; ComPtr canvas; @@ -100,6 +102,8 @@ QWinRTWindow::QWinRTWindow(QWindow *window) { Q_D(QWinRTWindow); + d->surface = EGL_NO_SURFACE; + d->display = EGL_NO_DISPLAY; d->screen = static_cast(screen()); setWindowFlags(window->flags()); setWindowState(window->windowState()); @@ -170,6 +174,11 @@ QWinRTWindow::~QWinRTWindow() return S_OK; }); RETURN_VOID_IF_FAILED("Failed to completely destroy window resources, likely because the application is shutting down"); + + EGLBoolean value = eglDestroySurface(d->display, d->surface); + d->surface = EGL_NO_SURFACE; + if (value == EGL_FALSE) + qCritical("Failed to destroy EGL window surface: 0x%x", eglGetError()); } QSurfaceFormat QWinRTWindow::format() const @@ -293,4 +302,26 @@ void QWinRTWindow::setWindowState(Qt::WindowState state) d->state = state; } +EGLSurface QWinRTWindow::eglSurface() const +{ + Q_D(const QWinRTWindow); + return d->surface; +} + +void QWinRTWindow::createEglSurface(EGLDisplay display, EGLConfig config) +{ + Q_D(QWinRTWindow); + if (d->surface == EGL_NO_SURFACE) { + d->display = display; + QEventDispatcherWinRT::runOnXamlThread([this, d, display, config]() { + d->surface = eglCreateWindowSurface(display, config, + reinterpret_cast(winId()), + nullptr); + if (d->surface == EGL_NO_SURFACE) + qCritical("Failed to create EGL window surface: 0x%x", eglGetError()); + return S_OK; + }); + } +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtwindow.h b/src/plugins/platforms/winrt/qwinrtwindow.h index 2957a7498b..9ac7adbf4d 100644 --- a/src/plugins/platforms/winrt/qwinrtwindow.h +++ b/src/plugins/platforms/winrt/qwinrtwindow.h @@ -39,6 +39,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -63,6 +64,9 @@ public: qreal devicePixelRatio() const Q_DECL_OVERRIDE; void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE; + EGLSurface eglSurface() const; + void createEglSurface(EGLDisplay display, EGLConfig config); + private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(QWinRTWindow) -- cgit v1.2.3 From 2e12f6e63ddb1ea3c79660cd99ffb96d4cd0bd82 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 14 Apr 2015 17:02:48 -0700 Subject: Fix deadlock if the last reference is dropped during delivery We increase the reference count of the connection during delivery of an incoming message, so it's possible that the corresponding deref will drop the last reference to the connection: another thread may have called disconnectFromBus/Peer. However, during destruction we try to drain the incoming socket queue, so we need to acquire the dispatch lock again. The solution is to always use deleteLater(), which means the deleteYourself() function is unnecessary. Change-Id: I27eaacb532114dd188c4ffff13d507039fcf7b6a Reviewed-by: Albert Astals Cid Reviewed-by: Alex Blasche --- src/dbus/qdbusconnection.cpp | 6 +++--- src/dbus/qdbusconnection_p.h | 1 - src/dbus/qdbusintegrator.cpp | 14 -------------- 3 files changed, 3 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp index 0adb3dd748..fd8b34b27e 100644 --- a/src/dbus/qdbusconnection.cpp +++ b/src/dbus/qdbusconnection.cpp @@ -68,7 +68,7 @@ void QDBusConnectionManager::removeConnection(const QString &name) QDBusConnectionPrivate *d = 0; d = connectionHash.take(name); if (d && !d->ref.deref()) - d->deleteYourself(); + d->deleteLater(); // Static objects may be keeping the connection open. // However, it is harmless to have outstanding references to a connection that is @@ -268,7 +268,7 @@ QDBusConnection::QDBusConnection(QDBusConnectionPrivate *dd) QDBusConnection::~QDBusConnection() { if (d && !d->ref.deref()) - d->deleteYourself(); + d->deleteLater(); } /*! @@ -283,7 +283,7 @@ QDBusConnection &QDBusConnection::operator=(const QDBusConnection &other) if (other.d) other.d->ref.ref(); if (d && !d->ref.deref()) - d->deleteYourself(); + d->deleteLater(); d = other.d; return *this; } diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index 752ca9c37a..8195ec5b3a 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -187,7 +187,6 @@ public: // public methods are entry points from other objects explicit QDBusConnectionPrivate(QObject *parent = 0); ~QDBusConnectionPrivate(); - void deleteYourself(); void setBusService(const QDBusConnection &connection); void setPeer(DBusConnection *connection, const QDBusErrorInternal &error); diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 22c1a3e363..796f41bffc 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -1065,20 +1065,6 @@ QDBusConnectionPrivate::~QDBusConnectionPrivate() server = 0; } -void QDBusConnectionPrivate::deleteYourself() -{ - if (thread() && thread() != QThread::currentThread()) { - // last reference dropped while not in the correct thread - // ask the correct thread to delete - - // note: since we're posting an event to another thread, we - // must consider deleteLater() to take effect immediately - deleteLater(); - } else { - delete this; - } -} - void QDBusConnectionPrivate::closeConnection() { QDBusWriteLocker locker(CloseConnectionAction, this); -- cgit v1.2.3 From 2bcc913a7f302cc404efcba951565bdeab9e1de4 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 29 Dec 2014 23:37:11 -0200 Subject: Use QDBusServiceWatcher in QDBusAbstractInterface to track the owner Instead of connecting to the "NameOwnerChanged" signal. This has better performance, is simpler to implement and is future-proof: when we switch to kdbus, there won't be a "NameOwnerChanged" signal to connect to. On the drawback side, this will use slightly more memory. Change-Id: I5801b8027949f041309567a493000fe7de9bf227 Reviewed-by: Alex Blasche Reviewed-by: Albert Astals Cid --- src/dbus/qdbusabstractinterface.cpp | 45 ++++++++++++++----------------------- src/dbus/qdbusabstractinterface_p.h | 2 ++ 2 files changed, 19 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/dbus/qdbusabstractinterface.cpp b/src/dbus/qdbusabstractinterface.cpp index a7c70bce70..5ccd8c8d83 100644 --- a/src/dbus/qdbusabstractinterface.cpp +++ b/src/dbus/qdbusabstractinterface.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Intel Corporation. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtDBus module of the Qt Toolkit. @@ -41,6 +42,7 @@ #include "qdbusmessage_p.h" #include "qdbusmetaobject_p.h" #include "qdbusmetatype_p.h" +#include "qdbusservicewatcher.h" #include "qdbusutil_p.h" #include @@ -97,6 +99,17 @@ QDBusAbstractInterfacePrivate::QDBusAbstractInterfacePrivate(const QString &serv } } +void QDBusAbstractInterfacePrivate::initOwnerTracking() +{ + if (!isValid || !connection.isConnected() || connectionPrivate()->mode == QDBusConnectionPrivate::PeerMode) + return; + if (service.isEmpty() || service.startsWith(QLatin1Char(':'))) + return; + QObject::connect(new QDBusServiceWatcher(service, connection, QDBusServiceWatcher::WatchForOwnerChange, q_func()), + SIGNAL(serviceOwnerChanged(QString,QString,QString)), + q_func(), SLOT(_q_serviceOwnerChanged(QString,QString,QString))); +} + bool QDBusAbstractInterfacePrivate::canMakeCalls() const { // recheck only if we have a wildcard (i.e. empty) service or path @@ -218,9 +231,8 @@ void QDBusAbstractInterfacePrivate::_q_serviceOwnerChanged(const QString &name, Q_UNUSED(oldOwner); Q_UNUSED(name); //qDebug() << "QDBusAbstractInterfacePrivate serviceOwnerChanged" << name << oldOwner << newOwner; - if (name == service) { - currentOwner = newOwner; - } + Q_ASSERT(name == service); + currentOwner = newOwner; } QDBusAbstractInterfaceBase::QDBusAbstractInterfaceBase(QDBusAbstractInterfacePrivate &d, QObject *parent) @@ -285,19 +297,7 @@ int QDBusAbstractInterfaceBase::qt_metacall(QMetaObject::Call _c, int _id, void QDBusAbstractInterface::QDBusAbstractInterface(QDBusAbstractInterfacePrivate &d, QObject *parent) : QDBusAbstractInterfaceBase(d, parent) { - // keep track of the service owner - if (d.isValid && - d.connection.isConnected() - && !d.service.isEmpty() - && !d.service.startsWith(QLatin1Char(':')) - && d.connectionPrivate()->mode != QDBusConnectionPrivate::PeerMode) - d_func()->connection.connect(QDBusUtil::dbusService(), // service - QString(), // path - QDBusUtil::dbusInterface(), // interface - QDBusUtil::nameOwnerChanged(), - QStringList() << d.service, - QString(), // signature - this, SLOT(_q_serviceOwnerChanged(QString,QString,QString))); + d.initOwnerTracking(); } /*! @@ -312,18 +312,7 @@ QDBusAbstractInterface::QDBusAbstractInterface(const QString &service, const QSt con, false), parent) { // keep track of the service owner - if (d_func()->isValid && - d_func()->connection.isConnected() - && !service.isEmpty() - && !service.startsWith(QLatin1Char(':')) - && d_func()->connectionPrivate()->mode != QDBusConnectionPrivate::PeerMode) - d_func()->connection.connect(QDBusUtil::dbusService(), // service - QString(), // path - QDBusUtil::dbusInterface(), // interface - QDBusUtil::nameOwnerChanged(), - QStringList() << service, - QString(), //signature - this, SLOT(_q_serviceOwnerChanged(QString,QString,QString))); + d_func()->initOwnerTracking(); } /*! diff --git a/src/dbus/qdbusabstractinterface_p.h b/src/dbus/qdbusabstractinterface_p.h index ba2bcadfb0..1ce457d94b 100644 --- a/src/dbus/qdbusabstractinterface_p.h +++ b/src/dbus/qdbusabstractinterface_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Intel Corporation. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtDBus module of the Qt Toolkit. @@ -78,6 +79,7 @@ public: QDBusAbstractInterfacePrivate(const QString &serv, const QString &p, const QString &iface, const QDBusConnection& con, bool dynamic); virtual ~QDBusAbstractInterfacePrivate() { } + void initOwnerTracking(); bool canMakeCalls() const; // these functions do not check if the property is valid -- cgit v1.2.3 From 1996bd4a01748ae384242eb47d4ff2c679c4c5d0 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 29 Dec 2014 18:06:42 -0200 Subject: Use QDBusConnectionPrivate* when QDBusServer receives a new connection This is because the socket activity will move to a different thread; QDBusConnectionPrivate* can be queued, QDBusConnection can't easily. Change-Id: I82722016018b7fcfb246cda6043469fadbfd987d Reviewed-by: Albert Astals Cid Reviewed-by: Alex Blasche --- src/dbus/qdbusconnection.cpp | 2 +- src/dbus/qdbusconnection_p.h | 17 +++++++++++------ src/dbus/qdbusintegrator.cpp | 15 +++++++++++---- src/dbus/qdbusserver.cpp | 15 +++++++++------ src/dbus/qdbusserver.h | 2 ++ 5 files changed, 34 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp index fd8b34b27e..08a21c5d02 100644 --- a/src/dbus/qdbusconnection.cpp +++ b/src/dbus/qdbusconnection.cpp @@ -929,7 +929,7 @@ QObject *QDBusConnection::objectRegisteredAt(const QString &path) const */ QDBusConnectionInterface *QDBusConnection::interface() const { - if (!d) + if (!d || d->mode != QDBusConnectionPrivate::ClientMode) return 0; return d->busService; } diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index 8195ec5b3a..9e948bd684 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Intel Corporation. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtDBus module of the Qt Toolkit. @@ -79,6 +80,7 @@ struct QDBusMetaObject; class QDBusAbstractInterface; class QDBusConnectionInterface; class QDBusPendingCallPrivate; +class QDBusServer; #ifndef QT_BOOTSTRAPPED @@ -191,7 +193,7 @@ public: void setBusService(const QDBusConnection &connection); void setPeer(DBusConnection *connection, const QDBusErrorInternal &error); void setConnection(DBusConnection *connection, const QDBusErrorInternal &error); - void setServer(DBusServer *server, const QDBusErrorInternal &error); + void setServer(QDBusServer *object, DBusServer *server, const QDBusErrorInternal &error); void closeConnection(); QString getNameOwner(const QString &service); @@ -228,9 +230,6 @@ public: void postEventToThread(int action, QObject *target, QEvent *event); - inline void serverConnection(const QDBusConnection &connection) - { emit newServerConnection(connection); } - private: void checkThread(); bool handleError(const QDBusErrorInternal &error); @@ -252,6 +251,8 @@ private: QString getNameOwnerNoCache(const QString &service); + void _q_newConnection(QDBusConnectionPrivate *newConnection); + protected: void customEvent(QEvent *e) Q_DECL_OVERRIDE; void timerEvent(QTimerEvent *e) Q_DECL_OVERRIDE; @@ -272,7 +273,7 @@ private slots: signals: void serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner); void callWithCallbackFailed(const QDBusError &error, const QDBusMessage &message); - void newServerConnection(const QDBusConnection &connection); + void newServerConnection(QDBusConnectionPrivate *newConnection); public: QAtomicInt ref; @@ -282,7 +283,10 @@ public: QStringList serverConnectionNames; ConnectionMode mode; - QDBusConnectionInterface *busService; + union { + QDBusConnectionInterface *busService; + QDBusServer *serverObject; + }; // the dispatch lock protects everything related to the DBusConnection or DBusServer // including the timeouts and watches @@ -333,6 +337,7 @@ public: friend class QDBusActivateObjectEvent; friend class QDBusCallDeliveryEvent; + friend class QDBusServer; }; // in qdbusmisc.cpp diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 796f41bffc..04d2c93ffe 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Intel Corporation. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtDBus module of the Qt Toolkit. @@ -52,6 +53,7 @@ #include "qdbusmetatype_p.h" #include "qdbusabstractadaptor.h" #include "qdbusabstractadaptor_p.h" +#include "qdbusserver.h" #include "qdbusutil_p.h" #include "qdbusvirtualobject.h" #include "qdbusmessage_p.h" @@ -393,10 +395,14 @@ static void qDBusNewConnection(DBusServer *server, DBusConnection *connection, v QDBusErrorInternal error; newConnection->setPeer(connection, error); - QDBusConnection retval = QDBusConnectionPrivate::q(newConnection); + // this is a queued connection and will resume in the QDBusServer's thread + emit serverConnection->newServerConnection(newConnection); +} - // make QDBusServer emit the newConnection signal - serverConnection->serverConnection(retval); +void QDBusConnectionPrivate::_q_newConnection(QDBusConnectionPrivate *newConnection) +{ + Q_ASSERT(mode == ServerMode); + emit serverObject->newConnection(QDBusConnectionPrivate::q(newConnection)); } } // extern "C" @@ -1645,9 +1651,10 @@ void QDBusConnectionPrivate::handleSignal(const QDBusMessage& msg) handleSignal(key, msg); // third try } -void QDBusConnectionPrivate::setServer(DBusServer *s, const QDBusErrorInternal &error) +void QDBusConnectionPrivate::setServer(QDBusServer *object, DBusServer *s, const QDBusErrorInternal &error) { mode = ServerMode; + serverObject = object; if (!s) { handleError(error); return; diff --git a/src/dbus/qdbusserver.cpp b/src/dbus/qdbusserver.cpp index cf1b6e9665..05156c992f 100644 --- a/src/dbus/qdbusserver.cpp +++ b/src/dbus/qdbusserver.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Intel Corporation. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtDBus module of the Qt Toolkit. @@ -64,11 +65,11 @@ QDBusServer::QDBusServer(const QString &address, QObject *parent) } d = new QDBusConnectionPrivate(this); - QObject::connect(d, SIGNAL(newServerConnection(QDBusConnection)), - this, SIGNAL(newConnection(QDBusConnection))); + QObject::connect(d, SIGNAL(newServerConnection(QDBusConnectionPrivate*)), + this, SLOT(_q_newConnection(QDBusConnectionPrivate*)), Qt::QueuedConnection); QDBusErrorInternal error; - d->setServer(q_dbus_server_listen(address.toUtf8().constData(), error), error); + d->setServer(this, q_dbus_server_listen(address.toUtf8().constData(), error), error); } /*! @@ -92,11 +93,11 @@ QDBusServer::QDBusServer(QObject *parent) } d = new QDBusConnectionPrivate(this); - QObject::connect(d, SIGNAL(newServerConnection(QDBusConnection)), - this, SIGNAL(newConnection(QDBusConnection))); + QObject::connect(d, SIGNAL(newServerConnection(QDBusConnectionPrivate*)), + this, SLOT(_q_newConnection(QDBusConnectionPrivate*)), Qt::QueuedConnection); QDBusErrorInternal error; - d->setServer(q_dbus_server_listen(address, error), error); + d->setServer(this, q_dbus_server_listen(address, error), error); } /*! @@ -186,4 +187,6 @@ bool QDBusServer::isAnonymousAuthenticationAllowed() const QT_END_NAMESPACE +#include "moc_qdbusserver.cpp" + #endif // QT_NO_DBUS diff --git a/src/dbus/qdbusserver.h b/src/dbus/qdbusserver.h index db21f268b0..2c66472a4d 100644 --- a/src/dbus/qdbusserver.h +++ b/src/dbus/qdbusserver.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Intel Corporation. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtDBus module of the Qt Toolkit. @@ -66,6 +67,7 @@ Q_SIGNALS: private: Q_DISABLE_COPY(QDBusServer) + Q_PRIVATE_SLOT(d, void _q_newConnection(QDBusConnectionPrivate*)) QDBusConnectionPrivate *d; }; -- cgit v1.2.3 From 9af53bfc8115eab4a6f46e5b38527ed3b669f3f0 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 30 Dec 2014 11:51:30 -0200 Subject: Use a signal for updating the dispatch status The cost of connecting a signal may be a bit high, but it's comparable to looking up the invokable method. However, QMetaMethod::invoke has a higher cost than a signal-slot emission -- though in any case they're both dwarfed by the cost of allocating the QMetaCallEvent and the posting of it. This is much more readable, though. Change-Id: Iccecbecbe6288fb3b6d16578fdff3f203b6db29c Reviewed-by: Alex Blasche Reviewed-by: Albert Astals Cid --- src/dbus/qdbusconnection_p.h | 1 + src/dbus/qdbusintegrator.cpp | 14 +++----------- 2 files changed, 4 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index 9e948bd684..fde7edaa64 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -271,6 +271,7 @@ private slots: void unregisterServiceNoLock(const QString &serviceName); signals: + void dispatchStatusChanged(); void serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner); void callWithCallbackFailed(const QDBusError &error, const QDBusMessage &message); void newServerConnection(QDBusConnectionPrivate *newConnection); diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 04d2c93ffe..84d433f2e7 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -357,18 +357,8 @@ static void qDBusUpdateDispatchStatus(DBusConnection *connection, DBusDispatchSt Q_ASSERT(connection); Q_UNUSED(connection); QDBusConnectionPrivate *d = static_cast(data); - - static int slotId; // 0 is QObject::deleteLater() - if (!slotId) { - // it's ok to do this: there's no race condition because the store is atomic - // and we always set to the same value - slotId = QDBusConnectionPrivate::staticMetaObject.indexOfSlot("doDispatch()"); - } - - //qDBusDebug() << "Updating dispatcher status" << slotId; if (new_status == DBUS_DISPATCH_DATA_REMAINS) - QDBusConnectionPrivate::staticMetaObject.method(slotId). - invoke(d, Qt::QueuedConnection); + emit d->dispatchStatusChanged(); } static void qDBusNewConnection(DBusServer *server, DBusConnection *connection, void *data) @@ -1030,6 +1020,8 @@ QDBusConnectionPrivate::QDBusConnectionPrivate(QObject *p) #endif QDBusMetaTypeId::init(); + connect(this, &QDBusConnectionPrivate::dispatchStatusChanged, + this, &QDBusConnectionPrivate::doDispatch, Qt::QueuedConnection); rootNode.flags = 0; -- cgit v1.2.3 From edaf7c30d43e82e662129f55343930f54199ec60 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 29 Dec 2014 19:25:28 -0200 Subject: Make QDBusConnectionPrivate::send return bool It used to return the sent message's serial ID, but we never used that. So simply use boolean instead. Change-Id: Ic5d393bfd36e48a193fcffff13b73753ccf47759 Reviewed-by: Alex Blasche Reviewed-by: Albert Astals Cid --- src/dbus/qdbusconnection_p.h | 2 +- src/dbus/qdbusintegrator.cpp | 19 ++++++------------- 2 files changed, 7 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index fde7edaa64..048e255e88 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -198,7 +198,7 @@ public: QString getNameOwner(const QString &service); - int send(const QDBusMessage &message); + bool send(const QDBusMessage &message); QDBusMessage sendWithReply(const QDBusMessage &message, int mode, int timeout = -1); QDBusMessage sendWithReplyLocal(const QDBusMessage &message); QDBusPendingCallPrivate *sendWithReplyAsync(const QDBusMessage &message, QObject *receiver, diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 84d433f2e7..08a8877ad5 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -1873,10 +1873,10 @@ void QDBusConnectionPrivate::processFinishedCall(QDBusPendingCallPrivate *call) delete call; } -int QDBusConnectionPrivate::send(const QDBusMessage& message) +bool QDBusConnectionPrivate::send(const QDBusMessage& message) { if (QDBusMessagePrivate::isLocal(message)) - return -1; // don't send; the reply will be retrieved by the caller + return true; // don't send; the reply will be retrieved by the caller // through the d_ptr->localReply link QDBusError error; @@ -1900,24 +1900,17 @@ int QDBusConnectionPrivate::send(const QDBusMessage& message) "invalid", qPrintable(message.service()), qPrintable(error.message())); lastError = error; - return 0; + return false; } q_dbus_message_set_no_reply(msg, true); // the reply would not be delivered to anything qDBusDebug() << this << "sending message (no reply):" << message; checkThread(); - bool isOk; - { - QDBusDispatchLocker locker(SendMessageAction, this); - isOk = q_dbus_connection_send(connection, msg, 0); - } - int serial = 0; - if (isOk) - serial = q_dbus_message_get_serial(msg); - + QDBusDispatchLocker locker(SendMessageAction, this); + bool isOk = q_dbus_connection_send(connection, msg, 0); q_dbus_message_unref(msg); - return serial; + return isOk; } // small helper to note long running blocking dbus calls. -- cgit v1.2.3 From 939b7c630d3f51224eacb6596f0ea2267ca5bfe5 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 29 Dec 2014 17:14:18 -0200 Subject: Implement the blocking QtDBus call in terms of the non-blocking one This simplifies the code a little by having a single code path. More importantly, we no longer need to call the evil function dbus_connection_send_with_reply_and_block. That function acquires a lock on the socket transport inside libdbus-1, which means all threads need to wait until the one call gets unblocked before they can continue. To do that, this commit reimplements the QDBus::Block part of QDBusConnectionPrivate::sendWithReply by reusing the existing call to sendWithReplyAsync() and then doing a blocking-wait with QDBusPendingCallPrivate::waitForFinished(). By using (Q)DBusPendingCall and the threaded connection approach (next commit), now we never block on the socket. That also means the code to call dbus_pending_call_block() is no longer necessary and the waitForFinished() function itself can be considerably simplified. As a side-effect of no longer blocking, a number of pre-existing race conditions that used to be hidden showed up. Note: this commit deadlocks without the threading (next commits). Task-number: QTBUG-43585 Change-Id: Ic5d393bfd36e48a193fcffff13b73754954a3f7d Reviewed-by: Albert Astals Cid Reviewed-by: Alex Blasche --- src/dbus/qdbus_symbols_p.h | 6 +-- src/dbus/qdbusconnection_p.h | 1 - src/dbus/qdbusintegrator.cpp | 91 ++++++++----------------------------------- src/dbus/qdbuspendingcall.cpp | 3 +- src/dbus/qdbuspendingcall_p.h | 4 +- src/dbus/qdbusthreaddebug_p.h | 4 +- 6 files changed, 23 insertions(+), 86 deletions(-) (limited to 'src') diff --git a/src/dbus/qdbus_symbols_p.h b/src/dbus/qdbus_symbols_p.h index 32b76ee5bd..1991a462e9 100644 --- a/src/dbus/qdbus_symbols_p.h +++ b/src/dbus/qdbus_symbols_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Intel Corporation. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtDBus module of the Qt Toolkit. @@ -205,11 +206,6 @@ DEFINEFUNC(dbus_bool_t , dbus_connection_send_with_reply, (DBusConnection DBusPendingCall **pending_return, int timeout_milliseconds), (connection, message, pending_return, timeout_milliseconds), return) -DEFINEFUNC(DBusMessage * , dbus_connection_send_with_reply_and_block, (DBusConnection *connection, - DBusMessage *message, - int timeout_milliseconds, - DBusError *error), - (connection, message, timeout_milliseconds, error), return) DEFINEFUNC(void , dbus_connection_set_exit_on_disconnect, (DBusConnection *connection, dbus_bool_t exit_on_disconnect), (connection, exit_on_disconnect), ) diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index 048e255e88..2155bd634c 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -223,7 +223,6 @@ public: void unregisterService(const QString &serviceName); bool handleMessage(const QDBusMessage &msg); - void waitForFinished(QDBusPendingCallPrivate *pcall); QDBusMetaObject *findMetaObject(const QString &service, const QString &path, const QString &interface, QDBusError &error); diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 08a8877ad5..4ae6a7f351 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -1790,34 +1790,6 @@ static void qDBusResultReceived(DBusPendingCall *pending, void *user_data) } } -void QDBusConnectionPrivate::waitForFinished(QDBusPendingCallPrivate *pcall) -{ - Q_ASSERT(pcall->pending); - //Q_ASSERT(pcall->mutex.isLocked()); // there's no such function - - if (pcall->waitingForFinished) { - // another thread is already waiting - pcall->waitForFinishedCondition.wait(&pcall->mutex); - } else { - pcall->waitingForFinished = true; - pcall->mutex.unlock(); - - { - QDBusDispatchLocker locker(PendingCallBlockAction, this); - q_dbus_pending_call_block(pcall->pending); - // QDBusConnectionPrivate::processFinishedCall() is called automatically - } - pcall->mutex.lock(); - - if (pcall->pending) { - q_dbus_pending_call_unref(pcall->pending); - pcall->pending = 0; - } - - pcall->waitForFinishedCondition.wakeAll(); - } -} - void QDBusConnectionPrivate::processFinishedCall(QDBusPendingCallPrivate *call) { QDBusConnectionPrivate *connection = const_cast(call->connection); @@ -1833,7 +1805,7 @@ void QDBusConnectionPrivate::processFinishedCall(QDBusPendingCallPrivate *call) msg = QDBusMessagePrivate::fromDBusMessage(reply, connection->capabilities); q_dbus_message_unref(reply); } - qDBusDebug() << connection << "got message reply (async):" << msg; + qDBusDebug() << connection << "got message reply:" << msg; // Check if the reply has the expected signature call->checkReceivedSignature(); @@ -1855,7 +1827,8 @@ void QDBusConnectionPrivate::processFinishedCall(QDBusPendingCallPrivate *call) qDBusDebug() << "Deliver failed!"; } - if (call->pending && !call->waitingForFinished) { + if (call->pending) { + call->waitForFinishedCondition.wakeAll(); q_dbus_pending_call_unref(call->pending); call->pending = 0; } @@ -2008,43 +1981,12 @@ QDBusMessage QDBusConnectionPrivate::sendWithReply(const QDBusMessage &message, // special case for synchronous local calls return sendWithReplyLocal(message); - if (!QCoreApplication::instance() || sendMode == QDBus::Block) { - QDBusError err; - DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, capabilities, &err); - if (!msg) { - qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\": %s", - qPrintable(message.service()), qPrintable(message.path()), - qPrintable(message.interface()), qPrintable(message.member()), - qPrintable(err.message())); - lastError = err; - return QDBusMessage::createError(err); - } - - qDBusDebug() << this << "sending message (blocking):" << message; - QDBusErrorInternal error; - DBusMessage *reply; - { - QDBusDispatchLocker locker(SendWithReplyAndBlockAction, this); - reply = q_dbus_connection_send_with_reply_and_block(connection, msg, timeout, error); - } - - q_dbus_message_unref(msg); - - if (!!error) { - lastError = err = error; - return QDBusMessage::createError(err); - } - - QDBusMessage amsg = QDBusMessagePrivate::fromDBusMessage(reply, capabilities); - q_dbus_message_unref(reply); - qDBusDebug() << this << "got message reply (blocking):" << amsg; - - return amsg; - } else { // use the event loop - QDBusPendingCallPrivate *pcall = sendWithReplyAsync(message, 0, 0, 0, timeout); - Q_ASSERT(pcall); + QDBusPendingCallPrivate *pcall = sendWithReplyAsync(message, 0, 0, 0, timeout); + Q_ASSERT(pcall); - if (pcall->replyMessage.type() == QDBusMessage::InvalidMessage) { + if (pcall->replyMessage.type() == QDBusMessage::InvalidMessage) { + // need to wait for the reply + if (sendMode == QDBus::BlockWithGui) { pcall->watcherHelper = new QDBusPendingCallWatcherHelper; QEventLoop loop; loop.connect(pcall->watcherHelper, SIGNAL(reply(QDBusMessage)), SLOT(quit())); @@ -2052,18 +1994,17 @@ QDBusMessage QDBusConnectionPrivate::sendWithReply(const QDBusMessage &message, // enter the event loop and wait for a reply loop.exec(QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents); + } else { + pcall->waitForFinished(); } + } - QDBusMessage reply = pcall->replyMessage; - lastError = QDBusError(reply); // set or clear error - - bool r = pcall->ref.deref(); - Q_ASSERT(!r); - Q_UNUSED(r); + QDBusMessage reply = pcall->replyMessage; + lastError = QDBusError(reply); // set or clear error + if (!pcall->ref.deref()) delete pcall; - return reply; - } + return reply; } QDBusMessage QDBusConnectionPrivate::sendWithReplyLocal(const QDBusMessage &message) @@ -2163,7 +2104,7 @@ QDBusPendingCallPrivate *QDBusConnectionPrivate::sendWithReplyAsync(const QDBusM return pcall; } - qDBusDebug() << this << "sending message (async):" << message; + qDBusDebug() << this << "sending message:" << message; DBusPendingCall *pending = 0; QDBusDispatchLocker locker(SendWithReplyAsyncAction, this); diff --git a/src/dbus/qdbuspendingcall.cpp b/src/dbus/qdbuspendingcall.cpp index 09eff81107..ad5632be5a 100644 --- a/src/dbus/qdbuspendingcall.cpp +++ b/src/dbus/qdbuspendingcall.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Intel Corporation. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtDBus module of the Qt Toolkit. @@ -231,7 +232,7 @@ void QDBusPendingCallPrivate::waitForFinished() if (replyMessage.type() != QDBusMessage::InvalidMessage) return; // already finished - connection->waitForFinished(this); + waitForFinishedCondition.wait(&mutex); } /*! diff --git a/src/dbus/qdbuspendingcall_p.h b/src/dbus/qdbuspendingcall_p.h index ac39487fee..dcf733679c 100644 --- a/src/dbus/qdbuspendingcall_p.h +++ b/src/dbus/qdbuspendingcall_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Intel Corporation. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtDBus module of the Qt Toolkit. @@ -89,11 +90,10 @@ public: DBusPendingCall *pending; QString expectedReplySignature; int expectedReplyCount; - bool waitingForFinished; // } QDBusPendingCallPrivate(const QDBusMessage &sent, QDBusConnectionPrivate *connection) - : sentMessage(sent), connection(connection), watcherHelper(0), pending(0), waitingForFinished(false) + : sentMessage(sent), connection(connection), watcherHelper(0), pending(0) { } ~QDBusPendingCallPrivate(); bool setReplyCallback(QObject *target, const char *member); diff --git a/src/dbus/qdbusthreaddebug_p.h b/src/dbus/qdbusthreaddebug_p.h index a8e126cf73..60b6acd38d 100644 --- a/src/dbus/qdbusthreaddebug_p.h +++ b/src/dbus/qdbusthreaddebug_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Intel Corporation. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtDBus module of the Qt Toolkit. @@ -87,8 +88,7 @@ enum ThreadAction { ActivateSignalAction = 27, PendingCallBlockAction = 28, SendMessageAction = 29, - SendWithReplyAndBlockAction = 30, - HuntAndEmitAction = 31, + HuntAndEmitAction = 30, AddTimeoutAction = 50, RealAddTimeoutAction = 51, -- cgit v1.2.3 From c2049f67e4cfe5f09e1b033b910cb37d043a287e Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 29 Dec 2014 11:35:36 -0200 Subject: Use a dedicated thread for handling incoming libdbus-1 events Each application will have one thread dedicated for this, for all QDBusConnections. I wouldn't mind sharing such a thread with other uses in Qt, provided none of them ever block (the QProcessManager thread comes to mind, but it's going away soon). The cost associated with this change in this commit is so far rather minimal. All incoming D-Bus calls need to be handled after an event is posted anyway, to avoid deadlocking on reentering libdbus-1 functions that acquire locks still held. The cost is the one more thread running and the cost of synchronizing them when an event is posted. The benefits far outweigh that cost: no longer will we have problems of QtDBus failing to run if the main system or session connections are used before QCoreApplication is run. Moreover, events can be received and handled in aux threads even if the main thread is blocked on some operation. Note: this commit may not be testable (tst_qdbusconnection may fail) Task-number: QTBUG-43585 Change-Id: Ic5d393bfd36e48a193fcffff13b737556ccd11a8 Reviewed-by: Albert Astals Cid Reviewed-by: Alex Blasche --- src/dbus/qdbusconnection.cpp | 58 +++++++++++++++++++++---------------- src/dbus/qdbusconnectionmanager_p.h | 11 +++++-- src/dbus/qdbusintegrator.cpp | 12 ++------ src/dbus/qdbusserver.cpp | 6 ++-- 4 files changed, 49 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp index 08a21c5d02..47255992ae 100644 --- a/src/dbus/qdbusconnection.cpp +++ b/src/dbus/qdbusconnection.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Intel Corporation. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtDBus module of the Qt Toolkit. @@ -77,17 +78,16 @@ void QDBusConnectionManager::removeConnection(const QString &name) // ### Output a warning if connections are being used after they have been removed. } +QDBusConnectionManager::QDBusConnectionManager() +{ + moveToThread(Q_NULLPTR); // we don't handle events + start(); +} + QDBusConnectionManager::~QDBusConnectionManager() { - for (QHash::const_iterator it = connectionHash.constBegin(); - it != connectionHash.constEnd(); ++it) { - QDBusConnectionPrivate *d = it.value(); - if (!d->ref.deref()) - d->deleteYourself(); - else - d->closeConnection(); - } - connectionHash.clear(); + quit(); + wait(); } QDBusConnectionManager* QDBusConnectionManager::instance() @@ -106,6 +106,25 @@ void QDBusConnectionManager::setConnection(const QString &name, QDBusConnectionP c->name = name; } +void QDBusConnectionManager::run() +{ + exec(); + + // cleanup: + QMutexLocker locker(&mutex); + for (QHash::const_iterator it = connectionHash.constBegin(); + it != connectionHash.constEnd(); ++it) { + QDBusConnectionPrivate *d = it.value(); + if (!d->ref.deref()) { + delete d; + } else { + d->closeConnection(); + d->moveToThread(Q_NULLPTR); // allow it to be deleted in another thread + } + } + connectionHash.clear(); +} + /*! \class QDBusConnection \inmodule QtDBus @@ -295,8 +314,6 @@ QDBusConnection &QDBusConnection::operator=(const QDBusConnection &other) */ QDBusConnection QDBusConnection::connectToBus(BusType type, const QString &name) { -// Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection", -// "Cannot create connection without a Q[Core]Application instance"); if (!qdbus_loadLibDBus()) { QDBusConnectionPrivate *d = 0; return QDBusConnection(d); @@ -331,6 +348,7 @@ QDBusConnection QDBusConnection::connectToBus(BusType type, const QString &name) // create the bus service // will lock in QDBusConnectionPrivate::connectRelay() d->setBusService(retval); + d->moveToThread(_q_manager()); return retval; } @@ -342,8 +360,6 @@ QDBusConnection QDBusConnection::connectToBus(BusType type, const QString &name) QDBusConnection QDBusConnection::connectToBus(const QString &address, const QString &name) { -// Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection", -// "Cannot create connection without a Q[Core]Application instance"); if (!qdbus_loadLibDBus()) { QDBusConnectionPrivate *d = 0; return QDBusConnection(d); @@ -373,6 +389,7 @@ QDBusConnection QDBusConnection::connectToBus(const QString &address, // create the bus service // will lock in QDBusConnectionPrivate::connectRelay() d->setBusService(retval); + d->moveToThread(_q_manager()); return retval; } @@ -385,8 +402,6 @@ QDBusConnection QDBusConnection::connectToBus(const QString &address, QDBusConnection QDBusConnection::connectToPeer(const QString &address, const QString &name) { -// Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection", -// "Cannot create connection without a Q[Core]Application instance"); if (!qdbus_loadLibDBus()) { QDBusConnectionPrivate *d = 0; return QDBusConnection(d); @@ -405,6 +420,7 @@ QDBusConnection QDBusConnection::connectToPeer(const QString &address, d->setPeer(c, error); _q_manager()->setConnection(name, d); + d->moveToThread(_q_manager()); QDBusConnection retval(d); @@ -1061,16 +1077,7 @@ class QDBusDefaultConnection: public QDBusConnection public: inline QDBusDefaultConnection(BusType type, const char *name) : QDBusConnection(connectToBus(type, QString::fromLatin1(name))), ownName(name) - { - // make sure this connection is running on the main thread - QCoreApplication *instance = QCoreApplication::instance(); - if (!instance) { - qWarning("QDBusConnection: %s D-Bus connection created before QCoreApplication. Application may misbehave.", - type == SessionBus ? "session" : type == SystemBus ? "system" : "generic"); - } else if (QDBusConnectionPrivate::d(*this)) { - QDBusConnectionPrivate::d(*this)->moveToThread(instance->thread()); - } - } + { } inline ~QDBusDefaultConnection() { disconnectFromBus(QString::fromLatin1(ownName)); } @@ -1125,6 +1132,7 @@ QDBusConnection QDBusConnection::sender() */ void QDBusConnectionPrivate::setBusService(const QDBusConnection &connection) { + Q_ASSERT(mode == ClientMode); busService = new QDBusConnectionInterface(connection, this); ref.deref(); // busService has increased the refcounting to us // avoid cyclic refcounting diff --git a/src/dbus/qdbusconnectionmanager_p.h b/src/dbus/qdbusconnectionmanager_p.h index fc0bb515e5..c3c7999699 100644 --- a/src/dbus/qdbusconnectionmanager_p.h +++ b/src/dbus/qdbusconnectionmanager_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Intel Corporation. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtDBus module of the Qt Toolkit. @@ -47,15 +48,17 @@ #define QDBUSCONNECTIONMANAGER_P_H #include "qdbusconnection_p.h" +#include "private/qthread_p.h" #ifndef QT_NO_DBUS QT_BEGIN_NAMESPACE -class QDBusConnectionManager +class QDBusConnectionManager : public QDaemonThread { + Q_OBJECT public: - QDBusConnectionManager() {} + QDBusConnectionManager(); ~QDBusConnectionManager(); static QDBusConnectionManager* instance(); @@ -64,6 +67,10 @@ public: void setConnection(const QString &name, QDBusConnectionPrivate *c); mutable QMutex mutex; + +protected: + void run() Q_DECL_OVERRIDE; + private: QHash connectionHash; diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 4ae6a7f351..6e37ea6f7c 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -1091,13 +1091,7 @@ void QDBusConnectionPrivate::closeConnection() void QDBusConnectionPrivate::checkThread() { - if (!thread()) { - if (QCoreApplication::instance()) - moveToThread(QCoreApplication::instance()->thread()); - else - qWarning("The thread that had QDBusConnection('%s') has died and there is no main thread", - qPrintable(name)); - } + Q_ASSERT(thread() == QDBusConnectionManager::instance()); } bool QDBusConnectionPrivate::handleError(const QDBusErrorInternal &error) @@ -1833,12 +1827,12 @@ void QDBusConnectionPrivate::processFinishedCall(QDBusPendingCallPrivate *call) call->pending = 0; } - locker.unlock(); - // Are there any watchers? if (call->watcherHelper) call->watcherHelper->emitSignals(msg, call->sentMessage); + locker.unlock(); + if (msg.type() == QDBusMessage::ErrorMessage) emit connection->callWithCallbackFailed(QDBusError(msg), call->sentMessage); diff --git a/src/dbus/qdbusserver.cpp b/src/dbus/qdbusserver.cpp index 05156c992f..a0b2c8283c 100644 --- a/src/dbus/qdbusserver.cpp +++ b/src/dbus/qdbusserver.cpp @@ -63,13 +63,14 @@ QDBusServer::QDBusServer(const QString &address, QObject *parent) d = 0; return; } - d = new QDBusConnectionPrivate(this); + d = new QDBusConnectionPrivate; QObject::connect(d, SIGNAL(newServerConnection(QDBusConnectionPrivate*)), this, SLOT(_q_newConnection(QDBusConnectionPrivate*)), Qt::QueuedConnection); QDBusErrorInternal error; d->setServer(this, q_dbus_server_listen(address.toUtf8().constData(), error), error); + d->moveToThread(QDBusConnectionManager::instance()); } /*! @@ -91,13 +92,14 @@ QDBusServer::QDBusServer(QObject *parent) d = 0; return; } - d = new QDBusConnectionPrivate(this); + d = new QDBusConnectionPrivate; QObject::connect(d, SIGNAL(newServerConnection(QDBusConnectionPrivate*)), this, SLOT(_q_newConnection(QDBusConnectionPrivate*)), Qt::QueuedConnection); QDBusErrorInternal error; d->setServer(this, q_dbus_server_listen(address, error), error); + d->moveToThread(QDBusConnectionManager::instance()); } /*! -- cgit v1.2.3 From 42858a9e88db6006ab541f3077f033415386400d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 29 Dec 2014 18:01:39 -0200 Subject: Simplify some code in QDBusConnectionPrivate::sendWithReplyAsync They're pretty much the same, clearly a copy & paste. Instead, merge the two codepaths so that we don't run the risk of applying a change in one part and forgetting the other. Task-number: QTBUG-43585 Change-Id: Ic5d393bfd36e48a193fcffff13b737560f6753be Reviewed-by: Albert Astals Cid Reviewed-by: Alex Blasche --- src/dbus/qdbusintegrator.cpp | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 6e37ea6f7c..e87ae5b29d 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -2038,34 +2038,15 @@ QDBusPendingCallPrivate *QDBusConnectionPrivate::sendWithReplyAsync(const QDBusM QObject *receiver, const char *returnMethod, const char *errorMethod, int timeout) { - if (isServiceRegisteredByThread(message.service())) { + checkThread(); + + QDBusPendingCallPrivate *pcall = new QDBusPendingCallPrivate(message, this); + bool isLoopback; + if ((isLoopback = isServiceRegisteredByThread(message.service()))) { // special case for local calls - QDBusPendingCallPrivate *pcall = new QDBusPendingCallPrivate(message, this); pcall->replyMessage = sendWithReplyLocal(message); - if (receiver && returnMethod) - pcall->setReplyCallback(receiver, returnMethod); - - if (errorMethod) { - pcall->watcherHelper = new QDBusPendingCallWatcherHelper; - connect(pcall->watcherHelper, SIGNAL(error(QDBusError,QDBusMessage)), receiver, errorMethod, - Qt::QueuedConnection); - pcall->watcherHelper->moveToThread(thread()); - } - - if ((receiver && returnMethod) || errorMethod) { - // no one waiting, will delete pcall in processFinishedCall() - pcall->ref.store(1); - } else { - // set double ref to prevent race between processFinishedCall() and ref counting - // by QDBusPendingCall::QExplicitlySharedDataPointer - pcall->ref.store(2); - } - processFinishedCall(pcall); - return pcall; } - checkThread(); - QDBusPendingCallPrivate *pcall = new QDBusPendingCallPrivate(message, this); if (receiver && returnMethod) pcall->setReplyCallback(receiver, returnMethod); @@ -2085,6 +2066,12 @@ QDBusPendingCallPrivate *QDBusConnectionPrivate::sendWithReplyAsync(const QDBusM pcall->ref.store(2); } + if (isLoopback) { + // a loopback call + processFinishedCall(pcall); + return pcall; + } + QDBusError error; DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, capabilities, &error); if (!msg) { -- cgit v1.2.3 From 6734c50a9eefa51f693e3d799d7b18fba9b7da04 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 29 Dec 2014 18:12:51 -0200 Subject: Remove superfluous code in QDBusConnectionPrivate::sendWithReply No need to check for the local loop if that's the first thing QDBusConnectionPrivate::sendWithReplyAsync will do. The side effect is that this now allocates memory for the QDBusPendingCallPrivate object, but loopback messages aren't that common to be worth the special casing. Task-number: QTBUG-43585 Change-Id: Ic5d393bfd36e48a193fcffff13b73756ab802ba2 Reviewed-by: Albert Astals Cid Reviewed-by: Alex Blasche --- src/dbus/qdbusintegrator.cpp | 6 ------ 1 file changed, 6 deletions(-) (limited to 'src') diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index e87ae5b29d..8cffe4d706 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -1969,12 +1969,6 @@ QDBusMessage QDBusConnectionPrivate::sendWithReply(const QDBusMessage &message, { QDBusBlockingCallWatcher watcher(message); - checkThread(); - if ((sendMode == QDBus::BlockWithGui || sendMode == QDBus::Block) - && isServiceRegisteredByThread(message.service())) - // special case for synchronous local calls - return sendWithReplyLocal(message); - QDBusPendingCallPrivate *pcall = sendWithReplyAsync(message, 0, 0, 0, timeout); Q_ASSERT(pcall); -- cgit v1.2.3 From df7064c1514c66610c56487e0444036539aa8645 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 29 Dec 2014 19:16:53 -0200 Subject: Move the sending of the D-Bus messages with reply to the thread This is intended to simply the handling of the socket in the future. Now, we know that all calls to send_with_reply are placed only from the manager's thread. Task-number: QTBUG-43585 Change-Id: Ic5d393bfd36e48a193fcffff13b737575c231927 Reviewed-by: Albert Astals Cid Reviewed-by: Alex Blasche --- src/dbus/qdbusconnection.cpp | 2 +- src/dbus/qdbusconnection_p.h | 2 ++ src/dbus/qdbusintegrator.cpp | 22 +++++++++++++++------- 3 files changed, 18 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp index 47255992ae..8ebdf4c66e 100644 --- a/src/dbus/qdbusconnection.cpp +++ b/src/dbus/qdbusconnection.cpp @@ -483,7 +483,7 @@ bool QDBusConnection::send(const QDBusMessage &message) const d->lastError = err; return false; } - return d->send(message) != 0; + return d->send(message); } /*! diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index 2155bd634c..3becc7cbc3 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -242,6 +242,7 @@ private: bool activateInternalFilters(const ObjectTreeNode &node, const QDBusMessage &msg); bool activateCall(QObject *object, int flags, const QDBusMessage &msg); + void sendInternal(QDBusPendingCallPrivate *pcall, void *msg, int timeout); void sendError(const QDBusMessage &msg, QDBusError::ErrorType code); void deliverCall(QObject *object, int flags, const QDBusMessage &msg, const QVector &metaTypes, int slotIdx); @@ -271,6 +272,7 @@ private slots: signals: void dispatchStatusChanged(); + void messageNeedsSending(QDBusPendingCallPrivate *pcall, void *msg, int timeout); void serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner); void callWithCallbackFailed(const QDBusError &error, const QDBusMessage &message); void newServerConnection(QDBusConnectionPrivate *newConnection); diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 8cffe4d706..77f27e6fb1 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -1022,6 +1022,8 @@ QDBusConnectionPrivate::QDBusConnectionPrivate(QObject *p) QDBusMetaTypeId::init(); connect(this, &QDBusConnectionPrivate::dispatchStatusChanged, this, &QDBusConnectionPrivate::doDispatch, Qt::QueuedConnection); + connect(this, &QDBusConnectionPrivate::messageNeedsSending, + this, &QDBusConnectionPrivate::sendInternal); rootNode.flags = 0; @@ -1092,6 +1094,7 @@ void QDBusConnectionPrivate::closeConnection() void QDBusConnectionPrivate::checkThread() { Q_ASSERT(thread() == QDBusConnectionManager::instance()); + Q_ASSERT(QThread::currentThread() == thread()); } bool QDBusConnectionPrivate::handleError(const QDBusErrorInternal &error) @@ -1822,7 +1825,6 @@ void QDBusConnectionPrivate::processFinishedCall(QDBusPendingCallPrivate *call) } if (call->pending) { - call->waitForFinishedCondition.wakeAll(); q_dbus_pending_call_unref(call->pending); call->pending = 0; } @@ -1831,6 +1833,7 @@ void QDBusConnectionPrivate::processFinishedCall(QDBusPendingCallPrivate *call) if (call->watcherHelper) call->watcherHelper->emitSignals(msg, call->sentMessage); + call->waitForFinishedCondition.wakeAll(); locker.unlock(); if (msg.type() == QDBusMessage::ErrorMessage) @@ -2032,8 +2035,6 @@ QDBusPendingCallPrivate *QDBusConnectionPrivate::sendWithReplyAsync(const QDBusM QObject *receiver, const char *returnMethod, const char *errorMethod, int timeout) { - checkThread(); - QDBusPendingCallPrivate *pcall = new QDBusPendingCallPrivate(message, this); bool isLoopback; if ((isLoopback = isServiceRegisteredByThread(message.service()))) { @@ -2076,11 +2077,19 @@ QDBusPendingCallPrivate *QDBusConnectionPrivate::sendWithReplyAsync(const QDBusM pcall->replyMessage = QDBusMessage::createError(error); lastError = error; processFinishedCall(pcall); - return pcall; + } else { + qDBusDebug() << this << "sending message:" << message; + emit messageNeedsSending(pcall, msg, timeout); } + return pcall; +} - qDBusDebug() << this << "sending message:" << message; +void QDBusConnectionPrivate::sendInternal(QDBusPendingCallPrivate *pcall, void *message, int timeout) +{ + QDBusError error; DBusPendingCall *pending = 0; + DBusMessage *msg = static_cast(message); + checkThread(); QDBusDispatchLocker locker(SendWithReplyAsyncAction, this); if (q_dbus_connection_send_with_reply(connection, msg, &pending, timeout)) { @@ -2094,7 +2103,7 @@ QDBusPendingCallPrivate *QDBusConnectionPrivate::sendWithReplyAsync(const QDBusM if (mode == QDBusConnectionPrivate::PeerMode) pendingCalls.append(pcall); - return pcall; + return; } else { // we're probably disconnected at this point lastError = error = QDBusError(QDBusError::Disconnected, QDBusUtil::disconnectedErrorMessage()); @@ -2106,7 +2115,6 @@ QDBusPendingCallPrivate *QDBusConnectionPrivate::sendWithReplyAsync(const QDBusM q_dbus_message_unref(msg); pcall->replyMessage = QDBusMessage::createError(error); processFinishedCall(pcall); - return pcall; } bool QDBusConnectionPrivate::connectSignal(const QString &service, -- cgit v1.2.3 From 5d41a4aa5a3324a2326142300da3b853bb14b070 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 29 Dec 2014 19:47:54 -0200 Subject: And move the sending of other types of D-Bus messages to the thread With this, we now know that all messages sent are sent from the same thread. This simplifies greatly the handling of the socket. Task-number: QTBUG-43585 Change-Id: Ic5d393bfd36e48a193fcffff13b73758087344ed Reviewed-by: Albert Astals Cid Reviewed-by: Alex Blasche --- src/dbus/qdbusconnection_p.h | 2 +- src/dbus/qdbusintegrator.cpp | 23 +++++++++++++---------- src/dbus/qdbusthreaddebug_p.h | 2 +- 3 files changed, 15 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index 3becc7cbc3..f653c427e7 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -272,7 +272,7 @@ private slots: signals: void dispatchStatusChanged(); - void messageNeedsSending(QDBusPendingCallPrivate *pcall, void *msg, int timeout); + void messageNeedsSending(QDBusPendingCallPrivate *pcall, void *msg, int timeout = -1); void serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner); void callWithCallbackFailed(const QDBusError &error, const QDBusMessage &message); void newServerConnection(QDBusConnectionPrivate *newConnection); diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 77f27e6fb1..d5eaf39021 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -1874,13 +1874,9 @@ bool QDBusConnectionPrivate::send(const QDBusMessage& message) } q_dbus_message_set_no_reply(msg, true); // the reply would not be delivered to anything - qDBusDebug() << this << "sending message (no reply):" << message; - checkThread(); - QDBusDispatchLocker locker(SendMessageAction, this); - bool isOk = q_dbus_connection_send(connection, msg, 0); - q_dbus_message_unref(msg); - return isOk; + emit messageNeedsSending(Q_NULLPTR, msg); + return true; } // small helper to note long running blocking dbus calls. @@ -2089,10 +2085,15 @@ void QDBusConnectionPrivate::sendInternal(QDBusPendingCallPrivate *pcall, void * QDBusError error; DBusPendingCall *pending = 0; DBusMessage *msg = static_cast(message); + bool isNoReply = !pcall; + Q_ASSERT(isNoReply == !!q_dbus_message_get_no_reply(msg)); + checkThread(); + QDBusDispatchLocker locker(SendMessageAction, this); - QDBusDispatchLocker locker(SendWithReplyAsyncAction, this); - if (q_dbus_connection_send_with_reply(connection, msg, &pending, timeout)) { + if (isNoReply && q_dbus_connection_send(connection, msg, Q_NULLPTR)) { + // success + } else if (!isNoReply && q_dbus_connection_send_with_reply(connection, msg, &pending, timeout)) { if (pending) { q_dbus_message_unref(msg); @@ -2113,8 +2114,10 @@ void QDBusConnectionPrivate::sendInternal(QDBusPendingCallPrivate *pcall, void * } q_dbus_message_unref(msg); - pcall->replyMessage = QDBusMessage::createError(error); - processFinishedCall(pcall); + if (pcall) { + pcall->replyMessage = QDBusMessage::createError(error); + processFinishedCall(pcall); + } } bool QDBusConnectionPrivate::connectSignal(const QString &service, diff --git a/src/dbus/qdbusthreaddebug_p.h b/src/dbus/qdbusthreaddebug_p.h index 60b6acd38d..eace25478d 100644 --- a/src/dbus/qdbusthreaddebug_p.h +++ b/src/dbus/qdbusthreaddebug_p.h @@ -83,7 +83,7 @@ enum ThreadAction { HandleObjectCallPostEventAction = 22, HandleObjectCallSemaphoreAction = 23, DoDispatchAction = 24, - SendWithReplyAsyncAction = 25, + // unused: 25, MessageResultReceivedAction = 26, ActivateSignalAction = 27, PendingCallBlockAction = 28, -- cgit v1.2.3 From ea01d7784ad3ab34061f43aa51ee91ce2339e003 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 14 Apr 2015 17:09:02 -0700 Subject: And move the creation of connections to the thread Now we know that all timers and socket notifiers get created only in the QDBusConnectionManager thread. Incidentally, this reduced code duplication. Change-Id: I27eaacb532114dd188c4ffff13d5075a8d2efb0b Reviewed-by: Alex Blasche --- src/dbus/qdbusconnection.cpp | 206 ++++++++++++++++++++++-------------- src/dbus/qdbusconnection_p.h | 2 +- src/dbus/qdbusconnectionmanager_p.h | 11 ++ src/dbus/qdbusintegrator.cpp | 1 + src/dbus/qdbusserver.cpp | 16 +-- src/dbus/qdbusserver.h | 1 + 6 files changed, 142 insertions(+), 95 deletions(-) (limited to 'src') diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp index 8ebdf4c66e..a5d674bb5a 100644 --- a/src/dbus/qdbusconnection.cpp +++ b/src/dbus/qdbusconnection.cpp @@ -59,6 +59,23 @@ QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC(QDBusConnectionManager, _q_manager) +struct QDBusConnectionManager::ConnectionRequestData +{ + enum RequestType { + ConnectToStandardBus, + ConnectToBusByAddress, + ConnectToPeerByAddress + } type; + + union { + QDBusConnection::BusType busType; + const QString *busAddress; + }; + const QString *name; + + QDBusConnectionPrivate *result; +}; + QDBusConnectionPrivate *QDBusConnectionManager::connection(const QString &name) const { return connectionHash.value(name, 0); @@ -80,7 +97,11 @@ void QDBusConnectionManager::removeConnection(const QString &name) QDBusConnectionManager::QDBusConnectionManager() { - moveToThread(Q_NULLPTR); // we don't handle events + connect(this, &QDBusConnectionManager::connectionRequested, + this, &QDBusConnectionManager::executeConnectionRequest, Qt::BlockingQueuedConnection); + connect(this, &QDBusConnectionManager::serverRequested, + this, &QDBusConnectionManager::createServer, Qt::BlockingQueuedConnection); + moveToThread(this); // ugly, don't do this in other projects start(); } @@ -123,6 +144,103 @@ void QDBusConnectionManager::run() } } connectionHash.clear(); + + // allow deletion from any thread without warning + moveToThread(Q_NULLPTR); +} + +QDBusConnectionPrivate *QDBusConnectionManager::connectToBus(QDBusConnection::BusType type, const QString &name) +{ + ConnectionRequestData data; + data.type = ConnectionRequestData::ConnectToStandardBus; + data.busType = type; + data.name = &name; + + emit connectionRequested(&data); + return data.result; +} + +QDBusConnectionPrivate *QDBusConnectionManager::connectToBus(const QString &address, const QString &name) +{ + ConnectionRequestData data; + data.type = ConnectionRequestData::ConnectToBusByAddress; + data.busAddress = &address; + data.name = &name; + + emit connectionRequested(&data); + return data.result; +} + +QDBusConnectionPrivate *QDBusConnectionManager::connectToPeer(const QString &address, const QString &name) +{ + ConnectionRequestData data; + data.type = ConnectionRequestData::ConnectToPeerByAddress; + data.busAddress = &address; + data.name = &name; + + emit connectionRequested(&data); + return data.result; +} + +void QDBusConnectionManager::executeConnectionRequest(QDBusConnectionManager::ConnectionRequestData *data) +{ + QMutexLocker locker(&mutex); + const QString &name = *data->name; + QDBusConnectionPrivate *&d = data->result; + + // check if the connection exists by name + d = connection(name); + if (d || name.isEmpty()) + return; + + d = new QDBusConnectionPrivate; + DBusConnection *c = 0; + QDBusErrorInternal error; + switch (data->type) { + case ConnectionRequestData::ConnectToStandardBus: + switch (data->busType) { + case QDBusConnection::SystemBus: + c = q_dbus_bus_get_private(DBUS_BUS_SYSTEM, error); + break; + case QDBusConnection::SessionBus: + c = q_dbus_bus_get_private(DBUS_BUS_SESSION, error); + break; + case QDBusConnection::ActivationBus: + c = q_dbus_bus_get_private(DBUS_BUS_STARTER, error); + break; + } + break; + + case ConnectionRequestData::ConnectToBusByAddress: + case ConnectionRequestData::ConnectToPeerByAddress: + c = q_dbus_connection_open_private(data->busAddress->toUtf8().constData(), error); + if (c && data->type == ConnectionRequestData::ConnectToBusByAddress) { + // register on the bus + if (!q_dbus_bus_register(c, error)) { + q_dbus_connection_unref(c); + c = 0; + } + } + break; + } + + setConnection(name, d); + if (data->type == ConnectionRequestData::ConnectToPeerByAddress) { + d->setPeer(c, error); + } else { + // create the bus service + // will lock in QDBusConnectionPrivate::connectRelay() + d->setConnection(c, error); + d->createBusService(); + } +} + +void QDBusConnectionManager::createServer(const QString &address, void *server) +{ + QDBusErrorInternal error; + QDBusConnectionPrivate *d = new QDBusConnectionPrivate; + d->setServer(static_cast(server), + q_dbus_server_listen(address.toUtf8().constData(), error), error); } /*! @@ -318,39 +436,7 @@ QDBusConnection QDBusConnection::connectToBus(BusType type, const QString &name) QDBusConnectionPrivate *d = 0; return QDBusConnection(d); } - - QMutexLocker locker(&_q_manager()->mutex); - - QDBusConnectionPrivate *d = _q_manager()->connection(name); - if (d || name.isEmpty()) - return QDBusConnection(d); - - d = new QDBusConnectionPrivate; - DBusConnection *c = 0; - QDBusErrorInternal error; - switch (type) { - case SystemBus: - c = q_dbus_bus_get_private(DBUS_BUS_SYSTEM, error); - break; - case SessionBus: - c = q_dbus_bus_get_private(DBUS_BUS_SESSION, error); - break; - case ActivationBus: - c = q_dbus_bus_get_private(DBUS_BUS_STARTER, error); - break; - } - d->setConnection(c, error); //setConnection does the error handling for us - - _q_manager()->setConnection(name, d); - - QDBusConnection retval(d); - - // create the bus service - // will lock in QDBusConnectionPrivate::connectRelay() - d->setBusService(retval); - d->moveToThread(_q_manager()); - - return retval; + return QDBusConnection(_q_manager()->connectToBus(type, name)); } /*! @@ -364,34 +450,7 @@ QDBusConnection QDBusConnection::connectToBus(const QString &address, QDBusConnectionPrivate *d = 0; return QDBusConnection(d); } - - QMutexLocker locker(&_q_manager()->mutex); - - QDBusConnectionPrivate *d = _q_manager()->connection(name); - if (d || name.isEmpty()) - return QDBusConnection(d); - - d = new QDBusConnectionPrivate; - // setConnection does the error handling for us - QDBusErrorInternal error; - DBusConnection *c = q_dbus_connection_open_private(address.toUtf8().constData(), error); - if (c) { - if (!q_dbus_bus_register(c, error)) { - q_dbus_connection_unref(c); - c = 0; - } - } - d->setConnection(c, error); - _q_manager()->setConnection(name, d); - - QDBusConnection retval(d); - - // create the bus service - // will lock in QDBusConnectionPrivate::connectRelay() - d->setBusService(retval); - d->moveToThread(_q_manager()); - - return retval; + return QDBusConnection(_q_manager()->connectToBus(address, name)); } /*! \since 4.8 @@ -406,25 +465,7 @@ QDBusConnection QDBusConnection::connectToPeer(const QString &address, QDBusConnectionPrivate *d = 0; return QDBusConnection(d); } - - QMutexLocker locker(&_q_manager()->mutex); - - QDBusConnectionPrivate *d = _q_manager()->connection(name); - if (d || name.isEmpty()) - return QDBusConnection(d); - - d = new QDBusConnectionPrivate; - // setPeer does the error handling for us - QDBusErrorInternal error; - DBusConnection *c = q_dbus_connection_open_private(address.toUtf8().constData(), error); - - d->setPeer(c, error); - _q_manager()->setConnection(name, d); - d->moveToThread(_q_manager()); - - QDBusConnection retval(d); - - return retval; + return QDBusConnection(_q_manager()->connectToPeer(address, name)); } /*! @@ -1130,9 +1171,10 @@ QDBusConnection QDBusConnection::sender() /*! \internal */ -void QDBusConnectionPrivate::setBusService(const QDBusConnection &connection) +void QDBusConnectionPrivate::createBusService() { Q_ASSERT(mode == ClientMode); + QDBusConnection connection(this); busService = new QDBusConnectionInterface(connection, this); ref.deref(); // busService has increased the refcounting to us // avoid cyclic refcounting diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index f653c427e7..765e4281fd 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -190,7 +190,7 @@ public: explicit QDBusConnectionPrivate(QObject *parent = 0); ~QDBusConnectionPrivate(); - void setBusService(const QDBusConnection &connection); + void createBusService(); void setPeer(DBusConnection *connection, const QDBusErrorInternal &error); void setConnection(DBusConnection *connection, const QDBusErrorInternal &error); void setServer(QDBusServer *object, DBusServer *server, const QDBusErrorInternal &error); diff --git a/src/dbus/qdbusconnectionmanager_p.h b/src/dbus/qdbusconnectionmanager_p.h index c3c7999699..4527c562f8 100644 --- a/src/dbus/qdbusconnectionmanager_p.h +++ b/src/dbus/qdbusconnectionmanager_p.h @@ -57,6 +57,7 @@ QT_BEGIN_NAMESPACE class QDBusConnectionManager : public QDaemonThread { Q_OBJECT + struct ConnectionRequestData; public: QDBusConnectionManager(); ~QDBusConnectionManager(); @@ -65,13 +66,23 @@ public: QDBusConnectionPrivate *connection(const QString &name) const; void removeConnection(const QString &name); void setConnection(const QString &name, QDBusConnectionPrivate *c); + QDBusConnectionPrivate *connectToBus(QDBusConnection::BusType type, const QString &name); + QDBusConnectionPrivate *connectToBus(const QString &address, const QString &name); + QDBusConnectionPrivate *connectToPeer(const QString &address, const QString &name); mutable QMutex mutex; +signals: + void connectionRequested(ConnectionRequestData *); + void serverRequested(const QString &address, void *server); + protected: void run() Q_DECL_OVERRIDE; private: + void executeConnectionRequest(ConnectionRequestData *data); + void createServer(const QString &address, void *server); + QHash connectionHash; mutable QMutex senderMutex; diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index d5eaf39021..9b0a51107a 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -1644,6 +1644,7 @@ void QDBusConnectionPrivate::setServer(QDBusServer *object, DBusServer *s, const { mode = ServerMode; serverObject = object; + object->d = this; if (!s) { handleError(error); return; diff --git a/src/dbus/qdbusserver.cpp b/src/dbus/qdbusserver.cpp index a0b2c8283c..6c1b4c10ef 100644 --- a/src/dbus/qdbusserver.cpp +++ b/src/dbus/qdbusserver.cpp @@ -63,14 +63,10 @@ QDBusServer::QDBusServer(const QString &address, QObject *parent) d = 0; return; } - d = new QDBusConnectionPrivate; + emit QDBusConnectionManager::instance()->serverRequested(address, this); QObject::connect(d, SIGNAL(newServerConnection(QDBusConnectionPrivate*)), this, SLOT(_q_newConnection(QDBusConnectionPrivate*)), Qt::QueuedConnection); - - QDBusErrorInternal error; - d->setServer(this, q_dbus_server_listen(address.toUtf8().constData(), error), error); - d->moveToThread(QDBusConnectionManager::instance()); } /*! @@ -83,23 +79,19 @@ QDBusServer::QDBusServer(QObject *parent) { #ifdef Q_OS_UNIX // Use Unix sockets on Unix systems only - static const char address[] = "unix:tmpdir=/tmp"; + const QString address = QStringLiteral("unix:tmpdir=/tmp"); #else - static const char address[] = "tcp:"; + const QString address = QStringLiteral("tcp:"); #endif if (!qdbus_loadLibDBus()) { d = 0; return; } - d = new QDBusConnectionPrivate; + emit QDBusConnectionManager::instance()->serverRequested(address, this); QObject::connect(d, SIGNAL(newServerConnection(QDBusConnectionPrivate*)), this, SLOT(_q_newConnection(QDBusConnectionPrivate*)), Qt::QueuedConnection); - - QDBusErrorInternal error; - d->setServer(this, q_dbus_server_listen(address, error), error); - d->moveToThread(QDBusConnectionManager::instance()); } /*! diff --git a/src/dbus/qdbusserver.h b/src/dbus/qdbusserver.h index 2c66472a4d..3cb2ec8c50 100644 --- a/src/dbus/qdbusserver.h +++ b/src/dbus/qdbusserver.h @@ -69,6 +69,7 @@ private: Q_DISABLE_COPY(QDBusServer) Q_PRIVATE_SLOT(d, void _q_newConnection(QDBusConnectionPrivate*)) QDBusConnectionPrivate *d; + friend class QDBusConnectionPrivate; }; QT_END_NAMESPACE -- cgit v1.2.3 From 68964b1023afa0eadee4ead5be8365b687eeec79 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 3 Apr 2015 22:46:52 -0700 Subject: Merge two Q_GLOBAL_STATICS into another and solve memory leak The two global statics for the session and system buses aren't necessary if they can't outlive the global static for QDBusConnectionManager anyway. So merge them there. The extra mutex is necessary because the QDBusConnection::connectToBus function will lock the regular mutex. This solves a potential memory leak at exit as a side-effect. Before this change, the session and system QDBusConnection object got destroyed in the main thread during global destruction, so it had to post an event to the QDBusConnectionManager thread to finish the destruction of the private. However, QCoreApplication is already gone by this point, so the QEvent::DeferredDelete event never got delivered. After this commit, there's no global static to destroy the QDBusConnection (there is no QDBusConnection holding a reference), so the object gets destroyed in QDBusConnectionManager::run()'s cleanup code. Change-Id: I9a75ad8521ae4e5cbbe5ffff13d1b967ee1a7a7e Reviewed-by: Albert Astals Cid Reviewed-by: Alex Blasche --- src/dbus/qdbusconnection.cpp | 44 ++++++++++++++++++------------------- src/dbus/qdbusconnectionmanager_p.h | 4 ++++ src/dbus/qdbusintegrator.cpp | 8 +++---- 3 files changed, 30 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp index a5d674bb5a..6f0473d9e4 100644 --- a/src/dbus/qdbusconnection.cpp +++ b/src/dbus/qdbusconnection.cpp @@ -76,6 +76,24 @@ struct QDBusConnectionManager::ConnectionRequestData QDBusConnectionPrivate *result; }; +QDBusConnectionPrivate *QDBusConnectionManager::busConnection(QDBusConnection::BusType type) +{ + Q_STATIC_ASSERT(int(QDBusConnection::SessionBus) + int(QDBusConnection::SystemBus) == 1); + Q_ASSERT(type == QDBusConnection::SessionBus || type == QDBusConnection::SystemBus); + + if (!qdbus_loadLibDBus()) + return 0; + + QMutexLocker lock(&defaultBusMutex); + if (defaultBuses[type]) + return defaultBuses[type]; + + QString name = QStringLiteral("qt_default_session_bus"); + if (type == QDBusConnection::SystemBus) + name = QStringLiteral("qt_default_system_bus"); + return defaultBuses[type] = connectToBus(type, name); +} + QDBusConnectionPrivate *QDBusConnectionManager::connection(const QString &name) const { return connectionHash.value(name, 0); @@ -102,6 +120,8 @@ QDBusConnectionManager::QDBusConnectionManager() connect(this, &QDBusConnectionManager::serverRequested, this, &QDBusConnectionManager::createServer, Qt::BlockingQueuedConnection); moveToThread(this); // ugly, don't do this in other projects + + defaultBuses[0] = defaultBuses[1] = Q_NULLPTR; start(); } @@ -1109,26 +1129,6 @@ bool QDBusConnection::unregisterService(const QString &serviceName) return false; } -static const char _q_sessionBusName[] = "qt_default_session_bus"; -static const char _q_systemBusName[] = "qt_default_system_bus"; - -class QDBusDefaultConnection: public QDBusConnection -{ - const char *ownName; -public: - inline QDBusDefaultConnection(BusType type, const char *name) - : QDBusConnection(connectToBus(type, QString::fromLatin1(name))), ownName(name) - { } - - inline ~QDBusDefaultConnection() - { disconnectFromBus(QString::fromLatin1(ownName)); } -}; - -Q_GLOBAL_STATIC_WITH_ARGS(QDBusDefaultConnection, _q_sessionBus, - (QDBusConnection::SessionBus, _q_sessionBusName)) -Q_GLOBAL_STATIC_WITH_ARGS(QDBusDefaultConnection, _q_systemBus, - (QDBusConnection::SystemBus, _q_systemBusName)) - /*! \fn QDBusConnection QDBusConnection::sessionBus() @@ -1138,7 +1138,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(QDBusDefaultConnection, _q_systemBus, */ QDBusConnection QDBusConnection::sessionBus() { - return *_q_sessionBus(); + return QDBusConnection(_q_manager()->busConnection(SessionBus)); } /*! @@ -1150,7 +1150,7 @@ QDBusConnection QDBusConnection::sessionBus() */ QDBusConnection QDBusConnection::systemBus() { - return *_q_systemBus(); + return QDBusConnection(_q_manager()->busConnection(SystemBus)); } #if QT_DEPRECATED_SINCE(5,5) diff --git a/src/dbus/qdbusconnectionmanager_p.h b/src/dbus/qdbusconnectionmanager_p.h index 4527c562f8..3f815fdcd7 100644 --- a/src/dbus/qdbusconnectionmanager_p.h +++ b/src/dbus/qdbusconnectionmanager_p.h @@ -63,6 +63,7 @@ public: ~QDBusConnectionManager(); static QDBusConnectionManager* instance(); + QDBusConnectionPrivate *busConnection(QDBusConnection::BusType type); QDBusConnectionPrivate *connection(const QString &name) const; void removeConnection(const QString &name); void setConnection(const QString &name, QDBusConnectionPrivate *c); @@ -85,6 +86,9 @@ private: QHash connectionHash; + QMutex defaultBusMutex; + QDBusConnectionPrivate *defaultBuses[2]; + mutable QMutex senderMutex; QString senderName; // internal; will probably change }; diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 9b0a51107a..22598a2f2d 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -1043,6 +1043,10 @@ QDBusConnectionPrivate::~QDBusConnectionPrivate() "Timer and socket errors will follow and the program will probably crash", qPrintable(name)); + closeConnection(); + rootNode.children.clear(); // free resources + qDeleteAll(cachedMetaObjects); + if (mode == ClientMode) { // the bus service object holds a reference back to us; // we need to destroy it before we finish destroying ourselves @@ -1052,10 +1056,6 @@ QDBusConnectionPrivate::~QDBusConnectionPrivate() delete obj; } - closeConnection(); - rootNode.children.clear(); // free resources - qDeleteAll(cachedMetaObjects); - if (server) q_dbus_server_unref(server); if (connection) -- cgit v1.2.3 From 186d8814407ccb3e221537d9797172c37127bc51 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 30 Dec 2014 11:46:52 -0200 Subject: Remove the event callbacks in QDBusConnectionPrivate They were used when we called the libdbus-1 message-sending functions from any thread, which meant that the callbacks could be triggered on any thread. Since we moved the message-sending to one thread only (the manager's thread), there's no need for the event fallback anymore. Since they're also always[*] running on an aux thread, there's no point in checking for the presence of a QCoreApplication instance anymore. I don't think there has been a need for this for many years, as the event dispatcher has been decoupled from QCoreApplication for a long time. [*] exception: the callbacks are first called in the thread that invoked QDBusConnection::connectTo{Bus,Peer}, before we've done the moveToThread. Task-number: QTBUG-43585 Change-Id: Ic5d393bfd36e48a193fcffff13b73758c798d6b0 Reviewed-by: Albert Astals Cid Reviewed-by: Alex Blasche --- src/dbus/qdbusconnection_p.h | 1 - src/dbus/qdbusintegrator.cpp | 144 ++++++------------------------------------- src/dbus/qdbusintegrator_p.h | 23 ------- 3 files changed, 19 insertions(+), 149 deletions(-) (limited to 'src') diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index 765e4281fd..1cd7669770 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -254,7 +254,6 @@ private: void _q_newConnection(QDBusConnectionPrivate *newConnection); protected: - void customEvent(QEvent *e) Q_DECL_OVERRIDE; void timerEvent(QTimerEvent *e) Q_DECL_OVERRIDE; public slots: diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 22598a2f2d..cfcf587423 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -133,7 +133,6 @@ extern "C" { // libdbus-1 callbacks -static bool qDBusRealAddTimeout(QDBusConnectionPrivate *d, DBusTimeout *timeout, int ms); static dbus_bool_t qDBusAddTimeout(DBusTimeout *timeout, void *data) { Q_ASSERT(timeout); @@ -142,29 +141,17 @@ static dbus_bool_t qDBusAddTimeout(DBusTimeout *timeout, void *data) // qDebug("addTimeout %d", q_dbus_timeout_get_interval(timeout)); QDBusConnectionPrivate *d = static_cast(data); + Q_ASSERT(QThread::currentThread() == d->thread()); - if (!q_dbus_timeout_get_enabled(timeout)) - return true; + // we may get called from qDBusToggleTimeout + if (Q_UNLIKELY(!q_dbus_timeout_get_enabled(timeout))) + return false; QDBusDispatchLocker locker(AddTimeoutAction, d); - if (QCoreApplication::instance() && QThread::currentThread() == d->thread()) { - // correct thread - return qDBusRealAddTimeout(d, timeout, q_dbus_timeout_get_interval(timeout)); - } else { - // wrong thread: sync back - QDBusConnectionCallbackEvent *ev = new QDBusConnectionCallbackEvent; - ev->subtype = QDBusConnectionCallbackEvent::AddTimeout; - d->timeoutsPendingAdd.append(qMakePair(timeout, q_dbus_timeout_get_interval(timeout))); - d->postEventToThread(AddTimeoutAction, d, ev); - return true; - } -} - -static bool qDBusRealAddTimeout(QDBusConnectionPrivate *d, DBusTimeout *timeout, int ms) -{ Q_ASSERT(d->timeouts.key(timeout, 0) == 0); - int timerId = d->startTimer(ms); + int timerId = d->startTimer(q_dbus_timeout_get_interval(timeout)); + Q_ASSERT_X(timerId, "QDBusConnection", "Failed to start a timer"); if (!timerId) return false; @@ -180,33 +167,14 @@ static void qDBusRemoveTimeout(DBusTimeout *timeout, void *data) // qDebug("removeTimeout"); QDBusConnectionPrivate *d = static_cast(data); + Q_ASSERT(QThread::currentThread() == d->thread()); QDBusDispatchLocker locker(RemoveTimeoutAction, d); - // is it pending addition? - QDBusConnectionPrivate::PendingTimeoutList::iterator pit = d->timeoutsPendingAdd.begin(); - while (pit != d->timeoutsPendingAdd.end()) { - if (pit->first == timeout) - pit = d->timeoutsPendingAdd.erase(pit); - else - ++pit; - } - - // is it a running timer? - bool correctThread = QCoreApplication::instance() && QThread::currentThread() == d->thread(); QDBusConnectionPrivate::TimeoutHash::iterator it = d->timeouts.begin(); while (it != d->timeouts.end()) { if (it.value() == timeout) { - if (correctThread) { - // correct thread - d->killTimer(it.key()); - } else { - // incorrect thread or no application, post an event for later - QDBusConnectionCallbackEvent *ev = new QDBusConnectionCallbackEvent; - ev->subtype = QDBusConnectionCallbackEvent::KillTimer; - ev->timerId = it.key(); - d->postEventToThread(KillTimerAction, d, ev); - } + d->killTimer(it.key()); it = d->timeouts.erase(it); break; } else { @@ -226,52 +194,33 @@ static void qDBusToggleTimeout(DBusTimeout *timeout, void *data) qDBusAddTimeout(timeout, data); } -static bool qDBusRealAddWatch(QDBusConnectionPrivate *d, DBusWatch *watch, int flags, int fd); static dbus_bool_t qDBusAddWatch(DBusWatch *watch, void *data) { Q_ASSERT(watch); Q_ASSERT(data); QDBusConnectionPrivate *d = static_cast(data); + Q_ASSERT(QThread::currentThread() == d->thread()); int flags = q_dbus_watch_get_flags(watch); int fd = q_dbus_watch_get_unix_fd(watch); - if (QCoreApplication::instance() && QThread::currentThread() == d->thread()) { - return qDBusRealAddWatch(d, watch, flags, fd); - } else { - QDBusConnectionCallbackEvent *ev = new QDBusConnectionCallbackEvent; - ev->subtype = QDBusConnectionCallbackEvent::AddWatch; - ev->watch = watch; - ev->fd = fd; - ev->extra = flags; - d->postEventToThread(AddWatchAction, d, ev); - return true; - } -} - -static bool qDBusRealAddWatch(QDBusConnectionPrivate *d, DBusWatch *watch, int flags, int fd) -{ QDBusConnectionPrivate::Watcher watcher; QDBusDispatchLocker locker(AddWatchAction, d); if (flags & DBUS_WATCH_READABLE) { //qDebug("addReadWatch %d", fd); watcher.watch = watch; - if (QCoreApplication::instance()) { - watcher.read = new QSocketNotifier(fd, QSocketNotifier::Read, d); - watcher.read->setEnabled(q_dbus_watch_get_enabled(watch)); - d->connect(watcher.read, SIGNAL(activated(int)), SLOT(socketRead(int))); - } + watcher.read = new QSocketNotifier(fd, QSocketNotifier::Read, d); + watcher.read->setEnabled(q_dbus_watch_get_enabled(watch)); + d->connect(watcher.read, SIGNAL(activated(int)), SLOT(socketRead(int))); } if (flags & DBUS_WATCH_WRITABLE) { //qDebug("addWriteWatch %d", fd); watcher.watch = watch; - if (QCoreApplication::instance()) { - watcher.write = new QSocketNotifier(fd, QSocketNotifier::Write, d); - watcher.write->setEnabled(q_dbus_watch_get_enabled(watch)); - d->connect(watcher.write, SIGNAL(activated(int)), SLOT(socketWrite(int))); - } + watcher.write = new QSocketNotifier(fd, QSocketNotifier::Write, d); + watcher.write->setEnabled(q_dbus_watch_get_enabled(watch)); + d->connect(watcher.write, SIGNAL(activated(int)), SLOT(socketWrite(int))); } d->watchers.insertMulti(fd, watcher); @@ -286,23 +235,15 @@ static void qDBusRemoveWatch(DBusWatch *watch, void *data) //qDebug("remove watch"); QDBusConnectionPrivate *d = static_cast(data); + Q_ASSERT(QThread::currentThread() == d->thread()); int fd = q_dbus_watch_get_unix_fd(watch); QDBusDispatchLocker locker(RemoveWatchAction, d); QDBusConnectionPrivate::WatcherHash::iterator i = d->watchers.find(fd); while (i != d->watchers.end() && i.key() == fd) { if (i.value().watch == watch) { - if (QCoreApplication::instance() && QThread::currentThread() == d->thread()) { - // correct thread, delete the socket notifiers - delete i.value().read; - delete i.value().write; - } else { - // incorrect thread or no application, use delete later - if (i->read) - i->read->deleteLater(); - if (i->write) - i->write->deleteLater(); - } + delete i.value().read; + delete i.value().write; i = d->watchers.erase(i); } else { ++i; @@ -310,28 +251,15 @@ static void qDBusRemoveWatch(DBusWatch *watch, void *data) } } -static void qDBusRealToggleWatch(QDBusConnectionPrivate *d, DBusWatch *watch, int fd); static void qDBusToggleWatch(DBusWatch *watch, void *data) { Q_ASSERT(watch); Q_ASSERT(data); QDBusConnectionPrivate *d = static_cast(data); + Q_ASSERT(QThread::currentThread() == d->thread()); int fd = q_dbus_watch_get_unix_fd(watch); - if (QCoreApplication::instance() && QThread::currentThread() == d->thread()) { - qDBusRealToggleWatch(d, watch, fd); - } else { - QDBusConnectionCallbackEvent *ev = new QDBusConnectionCallbackEvent; - ev->subtype = QDBusConnectionCallbackEvent::ToggleWatch; - ev->watch = watch; - ev->fd = fd; - d->postEventToThread(ToggleWatchAction, d, ev); - } -} - -static void qDBusRealToggleWatch(QDBusConnectionPrivate *d, DBusWatch *watch, int fd) -{ QDBusDispatchLocker locker(ToggleWatchAction, d); QDBusConnectionPrivate::WatcherHash::iterator i = d->watchers.find(fd); @@ -1120,40 +1048,6 @@ void QDBusConnectionPrivate::timerEvent(QTimerEvent *e) doDispatch(); } -void QDBusConnectionPrivate::customEvent(QEvent *e) -{ - Q_ASSERT(e->type() == QEvent::User); - - QDBusConnectionCallbackEvent *ev = static_cast(e); - QDBusLockerBase::reportThreadAction(int(AddTimeoutAction) + int(ev->subtype), - QDBusLockerBase::BeforeDeliver, this); - switch (ev->subtype) - { - case QDBusConnectionCallbackEvent::AddTimeout: { - QDBusDispatchLocker locker(RealAddTimeoutAction, this); - while (!timeoutsPendingAdd.isEmpty()) { - QPair entry = timeoutsPendingAdd.takeFirst(); - qDBusRealAddTimeout(this, entry.first, entry.second); - } - break; - } - - case QDBusConnectionCallbackEvent::KillTimer: - killTimer(ev->timerId); - break; - - case QDBusConnectionCallbackEvent::AddWatch: - qDBusRealAddWatch(this, ev->watch, ev->extra, ev->fd); - break; - - case QDBusConnectionCallbackEvent::ToggleWatch: - qDBusRealToggleWatch(this, ev->watch, ev->fd); - break; - } - QDBusLockerBase::reportThreadAction(int(AddTimeoutAction) + int(ev->subtype), - QDBusLockerBase::AfterDeliver, this); -} - void QDBusConnectionPrivate::doDispatch() { QDBusDispatchLocker locker(DoDispatchAction, this); diff --git a/src/dbus/qdbusintegrator_p.h b/src/dbus/qdbusintegrator_p.h index 95eeed3fff..62106e4c0b 100644 --- a/src/dbus/qdbusintegrator_p.h +++ b/src/dbus/qdbusintegrator_p.h @@ -133,29 +133,6 @@ private: bool handled; }; -class QDBusConnectionCallbackEvent : public QEvent -{ -public: - QDBusConnectionCallbackEvent() - : QEvent(User), subtype(Subtype(0)) - { } - - DBusWatch *watch; - union { - int timerId; - int fd; - }; - int extra; - - enum Subtype { - AddTimeout = 0, - KillTimer, - AddWatch, - //RemoveWatch, - ToggleWatch - } subtype; -}; - QT_END_NAMESPACE Q_DECLARE_METATYPE(QDBusSlotCache) -- cgit v1.2.3 From f744aece9df792fdc63593b5bd749ad69dfbd9c1 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 30 Mar 2015 17:53:06 -0700 Subject: QDBusServiceWatcher: Move the logic to QDBusConnectionPrivate With kdbus, we won't have a regular signal, but instead a special message. So keep the logic of what to do in QDBusConnectionPrivate. The #ifdef is to make sure the bootstrapped qdbuscpp2xml continues to build in cross-compilation environments. Change-Id: Iee8cbc07c4434ce9b560ffff13d06f0d9904cb6d Reviewed-by: Alex Blasche --- src/dbus/qdbusconnection_p.h | 7 ++++ src/dbus/qdbusintegrator.cpp | 70 ++++++++++++++++++++++++++++++++++++---- src/dbus/qdbusservicewatcher.cpp | 36 ++++----------------- src/dbus/qdbusservicewatcher.h | 4 +-- 4 files changed, 80 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index 1cd7669770..5f7f58e549 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -63,6 +63,7 @@ #include "qdbus_symbols_p.h" #include +#include // for the WatchMode enum #ifndef QT_NO_DBUS @@ -198,6 +199,12 @@ public: QString getNameOwner(const QString &service); + bool shouldWatchService(const QString &service); + void watchService(const QString &service, QDBusServiceWatcher::WatchMode mode, + QObject *obj, const char *member); + void unwatchService(const QString &service, QDBusServiceWatcher::WatchMode mode, + QObject *obj, const char *member); + bool send(const QDBusMessage &message); QDBusMessage sendWithReply(const QDBusMessage &message, int mode, int timeout = -1); QDBusMessage sendWithReplyLocal(const QDBusMessage &message); diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index cfcf587423..0a95a8e781 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -445,11 +445,27 @@ static QObject *findChildObject(const QDBusConnectionPrivate::ObjectTreeNode *ro return 0; } -static bool shouldWatchService(const QString &service) +static QStringList matchArgsForService(const QString &service, QDBusServiceWatcher::WatchMode mode) { - return !service.isEmpty() && !service.startsWith(QLatin1Char(':')); + QStringList matchArgs; + matchArgs << service; + + switch (mode) { + case QDBusServiceWatcher::WatchForOwnerChange: + break; + + case QDBusServiceWatcher::WatchForRegistration: + matchArgs << QString::fromLatin1("", 0); + break; + + case QDBusServiceWatcher::WatchForUnregistration: + matchArgs << QString() << QString::fromLatin1("", 0); + break; + } + return matchArgs; } + extern Q_DBUS_EXPORT void qDBusAddSpyHook(QDBusSpyHook); void qDBusAddSpyHook(QDBusSpyHook hook) { @@ -1473,10 +1489,7 @@ void QDBusConnectionPrivate::handleSignal(const QString &key, const QDBusMessage for ( ; it != end && it.key() == key; ++it) { const SignalHook &hook = it.value(); if (!hook.service.isEmpty()) { - const QString owner = - shouldWatchService(hook.service) ? - watchedServices.value(hook.service).owner : - hook.service; + QString owner = watchedServices.value(hook.service, WatchedServiceData(hook.service)).owner; if (owner != msg.service()) continue; } @@ -2278,6 +2291,51 @@ void QDBusConnectionPrivate::disconnectRelay(const QString &service, } } +bool QDBusConnectionPrivate::shouldWatchService(const QString &service) +{ + // we don't have to watch anything in peer mode + if (mode != ClientMode) + return false; + // we don't have to watch wildcard services (empty strings) + if (service.isEmpty()) + return false; + // we don't have to watch the bus driver + if (service == QDBusUtil::dbusService()) + return false; + return true; +} + +/*! + Sets up a watch rule for service \a service for the change described by + mode \a mode. When the change happens, slot \a member in object \a obj will + be called. + + The caller should call QDBusConnectionPrivate::shouldWatchService() before + calling this function to check whether the service needs to be watched at + all. Failing to do so may add rules that are never activated. +*/ +void QDBusConnectionPrivate::watchService(const QString &service, QDBusServiceWatcher::WatchMode mode, QObject *obj, const char *member) +{ + QStringList matchArgs = matchArgsForService(service, mode); + connectSignal(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), QDBusUtil::nameOwnerChanged(), + matchArgs, QString(), obj, member); +} + +/*! + Removes a watch rule set up by QDBusConnectionPrivate::watchService(). The + arguments to this function must be the same as the ones for that function. + + Sets up a watch rule for service \a service for the change described by + mode \a mode. When the change happens, slot \a member in object \a obj will + be called. +*/ +void QDBusConnectionPrivate::unwatchService(const QString &service, QDBusServiceWatcher::WatchMode mode, QObject *obj, const char *member) +{ + QStringList matchArgs = matchArgsForService(service, mode); + disconnectSignal(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), QDBusUtil::nameOwnerChanged(), + matchArgs, QString(), obj, member); +} + QString QDBusConnectionPrivate::getNameOwner(const QString& serviceName) { if (QDBusUtil::isValidUniqueConnectionName(serviceName)) diff --git a/src/dbus/qdbusservicewatcher.cpp b/src/dbus/qdbusservicewatcher.cpp index 4adf049d17..72c1a12f2c 100644 --- a/src/dbus/qdbusservicewatcher.cpp +++ b/src/dbus/qdbusservicewatcher.cpp @@ -38,6 +38,7 @@ #include #include +#include #ifndef QT_NO_DBUS @@ -59,7 +60,6 @@ public: void _q_serviceOwnerChanged(const QString &, const QString &, const QString &); void setConnection(const QStringList &services, const QDBusConnection &c, QDBusServiceWatcher::WatchMode watchMode); - QStringList matchArgsForService(const QString &service); void addService(const QString &service); void removeService(const QString &service); }; @@ -93,40 +93,18 @@ void QDBusServiceWatcherPrivate::setConnection(const QStringList &s, const QDBus } } -QStringList QDBusServiceWatcherPrivate::matchArgsForService(const QString &service) -{ - QStringList matchArgs; - matchArgs << service; - - switch (watchMode) { - case QDBusServiceWatcher::WatchForOwnerChange: - break; - - case QDBusServiceWatcher::WatchForRegistration: - matchArgs << QString::fromLatin1("", 0); - break; - - case QDBusServiceWatcher::WatchForUnregistration: - matchArgs << QString() << QString::fromLatin1("", 0); - break; - } - return matchArgs; -} - void QDBusServiceWatcherPrivate::addService(const QString &service) { - QStringList matchArgs = matchArgsForService(service); - connection.connect(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), QDBusUtil::nameOwnerChanged(), - matchArgs, QString(), q_func(), - SLOT(_q_serviceOwnerChanged(QString,QString,QString))); + QDBusConnectionPrivate *d = QDBusConnectionPrivate::d(connection); + if (d && d->shouldWatchService(service)) + d->watchService(service, watchMode, q_func(), SLOT(_q_serviceOwnerChanged(QString,QString,QString))); } void QDBusServiceWatcherPrivate::removeService(const QString &service) { - QStringList matchArgs = matchArgsForService(service); - connection.disconnect(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), QDBusUtil::nameOwnerChanged(), - matchArgs, QString(), q_func(), - SLOT(_q_serviceOwnerChanged(QString,QString,QString))); + QDBusConnectionPrivate *d = QDBusConnectionPrivate::d(connection); + if (d && d->shouldWatchService(service)) + d->unwatchService(service, watchMode, q_func(), SLOT(_q_serviceOwnerChanged(QString,QString,QString))); } /*! diff --git a/src/dbus/qdbusservicewatcher.h b/src/dbus/qdbusservicewatcher.h index 6f6ce917af..71c0f0af68 100644 --- a/src/dbus/qdbusservicewatcher.h +++ b/src/dbus/qdbusservicewatcher.h @@ -37,7 +37,7 @@ #include #include -#ifndef QT_NO_DBUS +#if !defined(QT_NO_DBUS) && !defined(QT_NO_QOBJECT) QT_BEGIN_NAMESPACE @@ -89,5 +89,5 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QDBusServiceWatcher::WatchMode) QT_END_NAMESPACE -#endif // QT_NO_DBUS +#endif // QT_NO_DBUS || QT_NO_QOBJECT #endif // QDBUSSERVICEWATCHER_H -- cgit v1.2.3 From d8148edb2318a0cd57ac704c105960728461a19a Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 30 Mar 2015 17:54:14 -0700 Subject: Use the new QDBusConnectionPrivate::shouldWatchService function That function was added in the previous commit, so deduplicate the code from QDBusAbstractInterfacePrivate::initOwnerTracking(). Change-Id: Iee8cbc07c4434ce9b560ffff13d06f1d9fb0cde5 Reviewed-by: Albert Astals Cid Reviewed-by: Alex Blasche --- src/dbus/qdbusabstractinterface.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src') diff --git a/src/dbus/qdbusabstractinterface.cpp b/src/dbus/qdbusabstractinterface.cpp index 5ccd8c8d83..0f097517b7 100644 --- a/src/dbus/qdbusabstractinterface.cpp +++ b/src/dbus/qdbusabstractinterface.cpp @@ -101,9 +101,7 @@ QDBusAbstractInterfacePrivate::QDBusAbstractInterfacePrivate(const QString &serv void QDBusAbstractInterfacePrivate::initOwnerTracking() { - if (!isValid || !connection.isConnected() || connectionPrivate()->mode == QDBusConnectionPrivate::PeerMode) - return; - if (service.isEmpty() || service.startsWith(QLatin1Char(':'))) + if (!isValid || !connection.isConnected() || !connectionPrivate()->shouldWatchService(service)) return; QObject::connect(new QDBusServiceWatcher(service, connection, QDBusServiceWatcher::WatchForOwnerChange, q_func()), SIGNAL(serviceOwnerChanged(QString,QString,QString)), -- cgit v1.2.3 From cc5ab92cd9e06511f7a65cc3195f01a730591768 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 30 Mar 2015 19:34:03 -0700 Subject: Make QDBusConnectionPrivate::getNameOwnerNoCache work in our thread In two commits, we will attempt to call this function from the manager thread, so we need to be sure this function works from there. Right now, it would deadlock in QDBusPendingCallPrivate::waitForFinished(), inside QDBusConnectionPrivate::sendWithReply(). The solution is simple: expand sendWithReply to the sendWithReplyAsync function it calls anyway, but tell the internal DBusPendingCall to finish before we call waitForFinished(). Change-Id: Iee8cbc07c4434ce9b560ffff13d0749013d771ab Reviewed-by: Albert Astals Cid Reviewed-by: Alex Blasche --- src/dbus/qdbusintegrator.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 0a95a8e781..7370d0bbfc 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -2362,9 +2362,21 @@ QString QDBusConnectionPrivate::getNameOwnerNoCache(const QString &serviceName) QStringLiteral("GetNameOwner")); QDBusMessagePrivate::setParametersValidated(msg, true); msg << serviceName; - QDBusMessage reply = sendWithReply(msg, QDBus::Block); - if (reply.type() == QDBusMessage::ReplyMessage) - return reply.arguments().at(0).toString(); + + QDBusPendingCallPrivate *pcall = sendWithReplyAsync(msg, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR); + if (thread() == QThread::currentThread()) { + // this function may be called in our own thread and + // QDBusPendingCallPrivate::waitForFinished() would deadlock there + q_dbus_pending_call_block(pcall->pending); + } + pcall->waitForFinished(); + msg = pcall->replyMessage; + + if (!pcall->ref.deref()) + delete pcall; + + if (msg.type() == QDBusMessage::ReplyMessage) + return msg.arguments().at(0).toString(); return QString(); } -- cgit v1.2.3 From e15e5b1d37de1903d9c19c239d15440a783dc051 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 30 Mar 2015 19:38:32 -0700 Subject: Bypass connectSignal() for receiving the NameOwnerChanged signal This is an optimization but is required. Instead of going through the entire (dis)connectSignal() stack to add/remove matching rules for the NameOwnerChanged bus signal and call into our serviceOwnerChangedNoLock slot, create a static hook that will match the signal and simply add/ remove the rules as needed. The required part is that this avoids a recursion into connectSignal(). The next commit will move this code to the QtDBus manager thread and we won't be able to call connectSignal() from there (it would create a deadlock). Change-Id: Iee8cbc07c4434ce9b560ffff13d074ce90ad02d4 Reviewed-by: Albert Astals Cid Reviewed-by: Alex Blasche --- src/dbus/qdbusintegrator.cpp | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 7370d0bbfc..c86d9f1eba 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -1679,6 +1679,15 @@ void QDBusConnectionPrivate::setConnection(DBusConnection *dbc, const QDBusError Q_ASSERT(hook.midx != -1); signalHooks.insert(QLatin1String("NameLost:" DBUS_INTERFACE_DBUS), hook); + // And initialize the hook for the NameOwnerChanged signal; + // we don't use connectSignal here because the rules are added by connectSignal on a per-need basis + hook.params.clear(); + hook.params.reserve(4); + hook.params << QMetaType::Void << QVariant::String << QVariant::String << QVariant::String; + hook.midx = staticMetaObject.indexOfSlot("serviceOwnerChangedNoLock(QString,QString,QString)"); + Q_ASSERT(hook.midx != -1); + signalHooks.insert(QLatin1String("NameOwnerChanged:" DBUS_INTERFACE_DBUS), hook); + qDBusDebug() << this << ": connected successfully"; // schedule a dispatch: @@ -2090,9 +2099,10 @@ void QDBusConnectionPrivate::connectSignal(const QString &key, const SignalHook WatchedServicesHash::mapped_type &data = watchedServices[hook.service]; if (++data.refcount == 1) { // we need to watch for this service changing - connectSignal(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), - QStringLiteral("NameOwnerChanged"), QStringList() << hook.service, QString(), - this, SLOT(serviceOwnerChangedNoLock(QString,QString,QString))); + q_dbus_bus_add_match(connection, + buildMatchRule(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), + QDBusUtil::nameOwnerChanged(), QStringList() << hook.service, QString()), + NULL); data.owner = getNameOwnerNoCache(hook.service); qDBusDebug() << this << "Watching service" << hook.service << "for owner changes (current owner:" << data.owner << ")"; @@ -2170,9 +2180,10 @@ QDBusConnectionPrivate::disconnectSignal(SignalHookHash::Iterator &it) if (sit != watchedServices.end()) { if (--sit.value().refcount == 0) { watchedServices.erase(sit); - disconnectSignal(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), - QStringLiteral("NameOwnerChanged"), QStringList() << hook.service, QString(), - this, SLOT(serviceOwnerChangedNoLock(QString,QString,QString))); + q_dbus_bus_remove_match(connection, + buildMatchRule(QDBusUtil::dbusService(), QString(), QDBusUtil::dbusInterface(), + QDBusUtil::nameOwnerChanged(), QStringList() << hook.service, QString()), + NULL); } } } -- cgit v1.2.3 From e94f512b1e4ef0da310dce6ec75b28e748183cc8 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 30 Mar 2015 09:02:40 -0700 Subject: Make sure we don't deadlock when connecting signals This commit moves the code that finishes the signal-slot connection into the QtDBus auxiliary thread. That is necessary because we're holding the lock for writing while making blocking calls. The auxiliary thread might be waiting for us to release that lock while processing some previous message. Change-Id: Iee8cbc07c4434ce9b560ffff13d0521b94a51833 Reviewed-by: Albert Astals Cid Reviewed-by: Alex Blasche --- src/dbus/qdbusconnection.cpp | 2 -- src/dbus/qdbusconnection_p.h | 8 +++-- src/dbus/qdbusintegrator.cpp | 81 +++++++++++++++++++------------------------- 3 files changed, 40 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp index 6f0473d9e4..e9196173ad 100644 --- a/src/dbus/qdbusconnection.cpp +++ b/src/dbus/qdbusconnection.cpp @@ -765,7 +765,6 @@ bool QDBusConnection::connect(const QString &service, const QString &path, const return false; } - QDBusWriteLocker locker(ConnectAction, d); return d->connectSignal(service, path, interface, name, argumentMatch, signature, receiver, slot); } @@ -821,7 +820,6 @@ bool QDBusConnection::disconnect(const QString &service, const QString &path, co if (interface.isEmpty() && name.isEmpty()) return false; - QDBusWriteLocker locker(DisconnectAction, d); return d->disconnectSignal(service, path, interface, name, argumentMatch, signature, receiver, slot); } diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index 5f7f58e549..e12b77837e 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -213,8 +213,6 @@ public: bool connectSignal(const QString &service, const QString &path, const QString& interface, const QString &name, const QStringList &argumentMatch, const QString &signature, QObject *receiver, const char *slot); - void connectSignal(const QString &key, const SignalHook &hook); - SignalHookHash::Iterator disconnectSignal(SignalHookHash::Iterator &it); bool disconnectSignal(const QString &service, const QString &path, const QString& interface, const QString &name, const QStringList &argumentMatch, const QString &signature, QObject *receiver, const char *slot); @@ -254,6 +252,8 @@ private: void deliverCall(QObject *object, int flags, const QDBusMessage &msg, const QVector &metaTypes, int slotIdx); + SignalHookHash::Iterator removeSignalHookNoLock(SignalHookHash::Iterator it); + bool isServiceRegisteredByThread(const QString &serviceName); QString getNameOwnerNoCache(const QString &service); @@ -270,6 +270,8 @@ public slots: void socketWrite(int); void objectDestroyed(QObject *o); void relaySignal(QObject *obj, const QMetaObject *, int signalId, const QVariantList &args); + void addSignalHook(const QString &key, const SignalHook &hook); + bool removeSignalHook(const QString &key, const SignalHook &hook); private slots: void serviceOwnerChangedNoLock(const QString &name, const QString &oldOwner, const QString &newOwner); @@ -279,6 +281,8 @@ private slots: signals: void dispatchStatusChanged(); void messageNeedsSending(QDBusPendingCallPrivate *pcall, void *msg, int timeout = -1); + void signalNeedsConnecting(const QString &key, const QDBusConnectionPrivate::SignalHook &hook); + bool signalNeedsDisconnecting(const QString &key, const QDBusConnectionPrivate::SignalHook &hook); void serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner); void callWithCallbackFailed(const QDBusError &error, const QDBusMessage &message); void newServerConnection(QDBusConnectionPrivate *newConnection); diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index c86d9f1eba..6fccccabd3 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -968,6 +968,10 @@ QDBusConnectionPrivate::QDBusConnectionPrivate(QObject *p) this, &QDBusConnectionPrivate::doDispatch, Qt::QueuedConnection); connect(this, &QDBusConnectionPrivate::messageNeedsSending, this, &QDBusConnectionPrivate::sendInternal); + connect(this, &QDBusConnectionPrivate::signalNeedsConnecting, + this, &QDBusConnectionPrivate::addSignalHook, Qt::BlockingQueuedConnection); + connect(this, &QDBusConnectionPrivate::signalNeedsDisconnecting, + this, &QDBusConnectionPrivate::removeSignalHook, Qt::BlockingQueuedConnection); rootNode.flags = 0; @@ -1108,7 +1112,7 @@ void QDBusConnectionPrivate::objectDestroyed(QObject *obj) SignalHookHash::iterator sit = signalHooks.begin(); while (sit != signalHooks.end()) { if (static_cast(sit.value().obj) == obj) - sit = disconnectSignal(sit); + sit = removeSignalHookNoLock(sit); else ++sit; } @@ -2053,6 +2057,15 @@ bool QDBusConnectionPrivate::connectSignal(const QString &service, if (!prepareHook(hook, key, service, path, interface, name, argumentMatch, receiver, slot, 0, false)) return false; // don't connect + Q_ASSERT(thread() != QThread::currentThread()); + emit signalNeedsConnecting(key, hook); + return true; +} + +void QDBusConnectionPrivate::addSignalHook(const QString &key, const SignalHook &hook) +{ + QDBusWriteLocker locker(ConnectAction, this); + // avoid duplicating: QDBusConnectionPrivate::SignalHookHash::ConstIterator it = signalHooks.constFind(key); QDBusConnectionPrivate::SignalHookHash::ConstIterator end = signalHooks.constEnd(); @@ -2065,24 +2078,18 @@ bool QDBusConnectionPrivate::connectSignal(const QString &service, entry.midx == hook.midx && entry.argumentMatch == hook.argumentMatch) { // no need to compare the parameters if it's the same slot - return true; // already there + return; // already there } } - connectSignal(key, hook); - return true; -} - -void QDBusConnectionPrivate::connectSignal(const QString &key, const SignalHook &hook) -{ signalHooks.insertMulti(key, hook); connect(hook.obj, SIGNAL(destroyed(QObject*)), SLOT(objectDestroyed(QObject*)), - Qt::ConnectionType(Qt::DirectConnection | Qt::UniqueConnection)); + Qt::ConnectionType(Qt::BlockingQueuedConnection | Qt::UniqueConnection)); - MatchRefCountHash::iterator it = matchRefCounts.find(hook.matchRule); + MatchRefCountHash::iterator mit = matchRefCounts.find(hook.matchRule); - if (it != matchRefCounts.end()) { // Match already present - it.value() = it.value() + 1; + if (mit != matchRefCounts.end()) { // Match already present + mit.value() = mit.value() + 1; return; } @@ -2128,7 +2135,14 @@ bool QDBusConnectionPrivate::disconnectSignal(const QString &service, if (!prepareHook(hook, key, service, path, interface, name, argumentMatch, receiver, slot, 0, false)) return false; // don't disconnect - // avoid duplicating: + Q_ASSERT(thread() != QThread::currentThread()); + return emit signalNeedsDisconnecting(key, hook); +} + +bool QDBusConnectionPrivate::removeSignalHook(const QString &key, const SignalHook &hook) +{ + // remove it from our list: + QDBusWriteLocker locker(ConnectAction, this); QDBusConnectionPrivate::SignalHookHash::Iterator it = signalHooks.find(key); QDBusConnectionPrivate::SignalHookHash::Iterator end = signalHooks.end(); for ( ; it != end && it.key() == key; ++it) { @@ -2140,7 +2154,7 @@ bool QDBusConnectionPrivate::disconnectSignal(const QString &service, entry.midx == hook.midx && entry.argumentMatch == hook.argumentMatch) { // no need to compare the parameters if it's the same slot - disconnectSignal(it); + removeSignalHookNoLock(it); return true; // it was there } } @@ -2150,7 +2164,7 @@ bool QDBusConnectionPrivate::disconnectSignal(const QString &service, } QDBusConnectionPrivate::SignalHookHash::Iterator -QDBusConnectionPrivate::disconnectSignal(SignalHookHash::Iterator &it) +QDBusConnectionPrivate::removeSignalHookNoLock(SignalHookHash::Iterator it) { const SignalHook &hook = it.value(); @@ -2196,7 +2210,7 @@ QDBusConnectionPrivate::disconnectSignal(SignalHookHash::Iterator &it) void QDBusConnectionPrivate::registerObject(const ObjectTreeNode *node) { connect(node->obj, SIGNAL(destroyed(QObject*)), SLOT(objectDestroyed(QObject*)), - Qt::DirectConnection); + Qt::ConnectionType(Qt::BlockingQueuedConnection | Qt::UniqueConnection)); if (node->flags & (QDBusConnection::ExportAdaptors | QDBusConnection::ExportScriptableSignals @@ -2250,21 +2264,8 @@ void QDBusConnectionPrivate::connectRelay(const QString &service, QDBusAbstractInterface::staticMetaObject.methodCount(), true)) return; // don't connect - // add it to our list: - QDBusWriteLocker locker(ConnectRelayAction, this); - SignalHookHash::ConstIterator it = signalHooks.constFind(key); - SignalHookHash::ConstIterator end = signalHooks.constEnd(); - for ( ; it != end && it.key() == key; ++it) { - const SignalHook &entry = it.value(); - if (entry.service == hook.service && - entry.path == hook.path && - entry.signature == hook.signature && - entry.obj == hook.obj && - entry.midx == hook.midx) - return; // already there, no need to re-add - } - - connectSignal(key, hook); + Q_ASSERT(thread() != QThread::currentThread()); + emit signalNeedsConnecting(key, hook); } void QDBusConnectionPrivate::disconnectRelay(const QString &service, @@ -2284,22 +2285,8 @@ void QDBusConnectionPrivate::disconnectRelay(const QString &service, QDBusAbstractInterface::staticMetaObject.methodCount(), true)) return; // don't connect - // remove it from our list: - QDBusWriteLocker locker(DisconnectRelayAction, this); - SignalHookHash::Iterator it = signalHooks.find(key); - SignalHookHash::Iterator end = signalHooks.end(); - for ( ; it != end && it.key() == key; ++it) { - const SignalHook &entry = it.value(); - if (entry.service == hook.service && - entry.path == hook.path && - entry.signature == hook.signature && - entry.obj == hook.obj && - entry.midx == hook.midx) { - // found it - disconnectSignal(it); - return; - } - } + Q_ASSERT(thread() != QThread::currentThread()); + emit signalNeedsDisconnecting(key, hook); } bool QDBusConnectionPrivate::shouldWatchService(const QString &service) -- cgit v1.2.3 From 8888eae0d3da23f233ce49cd3457885998444db4 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 3 Apr 2015 23:09:50 -0700 Subject: Merge two more QDBusConnectionPrivate members into a union QDBusConnectionPrivate can only be a client or a server, not both, so the DBusServer and DBusConnection pointers can be shared, like the QDBusConnectionInterface and QDBusServer pointers in the other anonymous union. Change-Id: I9a75ad8521ae4e5cbbe5ffff13d1baa8ab83c42f Reviewed-by: Albert Astals Cid Reviewed-by: Alex Blasche --- src/dbus/qdbusconnection_p.h | 6 ++++-- src/dbus/qdbusintegrator.cpp | 27 ++++++++++++++------------- 2 files changed, 18 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index e12b77837e..49c7564566 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -303,8 +303,10 @@ public: // the dispatch lock protects everything related to the DBusConnection or DBusServer // including the timeouts and watches QMutex dispatchLock; - DBusConnection *connection; - DBusServer *server; + union { + DBusConnection *connection; + DBusServer *server; + }; WatcherHash watchers; TimeoutHash timeouts; PendingTimeoutList timeoutsPendingAdd; diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 6fccccabd3..ec9a88a210 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -949,7 +949,7 @@ extern bool qDBusInitThreads(); QDBusConnectionPrivate::QDBusConnectionPrivate(QObject *p) : QObject(p), ref(1), capabilities(0), mode(InvalidMode), busService(0), - dispatchLock(QMutex::Recursive), connection(0), server(0), + dispatchLock(QMutex::Recursive), connection(0), rootNode(QString(QLatin1Char('/'))), anonymousAuthenticationAllowed(false) { @@ -995,22 +995,23 @@ QDBusConnectionPrivate::~QDBusConnectionPrivate() rootNode.children.clear(); // free resources qDeleteAll(cachedMetaObjects); - if (mode == ClientMode) { + if (mode == ClientMode || mode == PeerMode) { // the bus service object holds a reference back to us; // we need to destroy it before we finish destroying ourselves Q_ASSERT(ref.load() == 0); QObject *obj = (QObject *)busService; - disconnect(obj, Q_NULLPTR, this, Q_NULLPTR); - delete obj; + if (obj) { + disconnect(obj, Q_NULLPTR, this, Q_NULLPTR); + delete obj; + } + if (connection) + q_dbus_connection_unref(connection); + connection = 0; + } else if (mode == ServerMode) { + if (server) + q_dbus_server_unref(server); + server = 0; } - - if (server) - q_dbus_server_unref(server); - if (connection) - q_dbus_connection_unref(connection); - - connection = 0; - server = 0; } void QDBusConnectionPrivate::closeConnection() @@ -1020,7 +1021,7 @@ void QDBusConnectionPrivate::closeConnection() mode = InvalidMode; // prevent reentrancy baseService.clear(); - if (server) { + if (oldMode == ServerMode && server) { q_dbus_server_disconnect(server); q_dbus_server_free_data_slot(&server_slot); } -- cgit v1.2.3 From 0e342fce4c665d72a50147c4f4b30ea08cc6c87b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 4 Sep 2015 17:56:24 +0200 Subject: Replace direct QPA access in tst_qguiappliction with testlib wrapper Change-Id: I698aa9d7633992d257296759f5e04307ff0d8331 Reviewed-by: Lars Knoll --- src/testlib/qtestkeyboard.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/testlib/qtestkeyboard.h b/src/testlib/qtestkeyboard.h index 82dd6fa098..d73658d8fc 100644 --- a/src/testlib/qtestkeyboard.h +++ b/src/testlib/qtestkeyboard.h @@ -61,7 +61,7 @@ Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int namespace QTest { - enum KeyAction { Press, Release, Click }; + enum KeyAction { Press, Release, Click, Shortcut }; static void simulateEvent(QWindow *window, bool press, int code, Qt::KeyboardModifiers modifier, QString text, bool repeat, int delay=-1) @@ -95,6 +95,12 @@ namespace QTest bool repeat = false; + if (action == Shortcut) { + int timestamp = 0; + qt_sendShortcutOverrideEvent(window, timestamp, code, modifier, text, repeat); + return; + } + if (action == Press) { if (modifier & Qt::ShiftModifier) simulateEvent(window, true, Qt::Key_Shift, Qt::KeyboardModifiers(), QString(), false, delay); -- cgit v1.2.3 From be55ecac61d88beb250ae6deedef405c031bcdac Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Tue, 8 Sep 2015 15:17:50 +0200 Subject: Add a method to detect when the state-machine can exit. According to the SCXML specification, the state-machine can exit the interpreter loop when a final state has been reached. This happens after finishing a macro-step or when it ends up in a final state right after startup (e.g. when the only state is a final state). This patch adds a virtual method which can be used to detect this reliably. Change-Id: I594e952a4972dd70d4089a2c4ce1c86880568eb9 Reviewed-by: Simon Hausmann --- src/corelib/statemachine/qstatemachine.cpp | 8 ++++++++ src/corelib/statemachine/qstatemachine_p.h | 1 + 2 files changed, 9 insertions(+) (limited to 'src') diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 687f676819..c5e251b37b 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -1834,6 +1834,7 @@ void QStateMachinePrivate::_q_start() unregisterAllTransitions(); emitFinished(); emit q->runningChanged(false); + exitInterpreter(); } else { _q_process(); } @@ -1928,6 +1929,8 @@ void QStateMachinePrivate::_q_process() break; } endMacrostep(didChange); + if (stopProcessingReason == Finished) + exitInterpreter(); } void QStateMachinePrivate::_q_startDelayedEventTimer(int id, int delay) @@ -2057,6 +2060,8 @@ void QStateMachinePrivate::noMicrostep() 4) the state machine either enters an infinite loop, or stops (runningChanged(false), and either finished or stopped are emitted), or processedPendingEvents() is called. 5) if the machine is not in an infinite loop endMacrostep is called + 6) when the machine is finished and all processing (like signal emission) is done, + exitInterpreter() is called. (This is the same name as the SCXML specification uses.) didChange is set to true if at least one microstep was performed, it is possible that the machine returned to exactly the same state as before, but some transitions @@ -2077,6 +2082,9 @@ void QStateMachinePrivate::endMacrostep(bool didChange) Q_UNUSED(didChange); } +void QStateMachinePrivate::exitInterpreter() +{ +} void QStateMachinePrivate::emitStateFinished(QState *forState, QFinalState *guiltyState) { diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index 4419ebc7f3..fe7a06d16b 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -133,6 +133,7 @@ public: virtual void processedPendingEvents(bool didChange); virtual void beginMacrostep(); virtual void endMacrostep(bool didChange); + virtual void exitInterpreter(); void exitStates(QEvent *event, const QList &statesToExit_sorted, const QHash > &assignmentsForEnteredStates); QList computeExitSet(const QList &enabledTransitions, CalculationCache *cache); -- cgit v1.2.3 From cebd5e2755d1a3b6177f9006a0f73c3c2f42a8de Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Tue, 15 Sep 2015 14:58:12 +0200 Subject: Fix QT_NO_ACCESSIBILITY build on windows Change-Id: I30b9477596696e3f4b5b51f2d5b201fe4efbdef4 Reviewed-by: Friedemann Kleint --- src/widgets/styles/qwindowsvistastyle.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp index b8ed82fee3..ab4b4245c6 100644 --- a/src/widgets/styles/qwindowsvistastyle.cpp +++ b/src/widgets/styles/qwindowsvistastyle.cpp @@ -657,8 +657,10 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt newStyle = !qobject_cast(view); selectionBehavior = view->selectionBehavior(); selectionMode = view->selectionMode(); +#ifndef QT_NO_ACCESSIBILITY } else if (!widget) { newStyle = !QStyleHelper::hasAncestor(option->styleObject, QAccessible::MenuItem) ; +#endif } if (newStyle && (vopt = qstyleoption_cast(option))) { -- cgit v1.2.3 From 499f9b2abfabacd254e1b23566343ac20322eb48 Mon Sep 17 00:00:00 2001 From: Aleix Pol Date: Sat, 12 Sep 2015 10:28:55 +0200 Subject: Use the proper macro to detect the compiler as part of the NDK The correct macros can be easily checked by running: .../arm-linux-androideabi-gcc -E -dM - < /dev/null | grep -i ANDR Otherwise we're just relying on the user to set up explicitly the toolchain to target Android Change-Id: I7b68521f43031c13da99b07626360d0702bff4ca Reviewed-by: BogDan Vatra --- src/corelib/global/qsystemdetection.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/global/qsystemdetection.h b/src/corelib/global/qsystemdetection.h index 562427e4b9..d19784163a 100644 --- a/src/corelib/global/qsystemdetection.h +++ b/src/corelib/global/qsystemdetection.h @@ -94,7 +94,7 @@ # else # define Q_OS_DARWIN32 # endif -#elif defined(ANDROID) +#elif defined(__ANDROID__) || defined(ANDROID) # define Q_OS_ANDROID # define Q_OS_LINUX #elif defined(__CYGWIN__) -- cgit v1.2.3 From 3601d6d7e3b029dbbfafe2c991537905241016d7 Mon Sep 17 00:00:00 2001 From: Aleix Pol Date: Fri, 4 Sep 2015 17:20:19 +0200 Subject: Document QGuiApplication::primaryScreen property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was just documented as a method and signal so far, even though it already was a property. This patch merges both documentations into one. Change-Id: I3fb4090b773ba8762ad9e830303812887b75add3 Reviewed-by: Frederik Gladhorn Reviewed-by: Topi Reiniö --- src/gui/kernel/qguiapplication.cpp | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 87bd7ea5de..fc87759227 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -875,16 +875,6 @@ QWindowList QGuiApplication::topLevelWindows() return topLevelWindows; } -/*! - Returns the primary (or default) screen of the application, or null if there is none - - This will be the screen where QWindows are initially shown, unless otherwise specified. - - On some platforms, it may be null when there are actually no screens connected. - It is not possible to start a new QGuiApplication while there are no screens. - Applications which were running at the time the primary screen was removed - will stop rendering graphics until one or more screens are restored. -*/ QScreen *QGuiApplication::primaryScreen() { if (QGuiApplicationPrivate::screen_list.isEmpty()) @@ -906,7 +896,7 @@ QList QGuiApplication::screens() This signal is emitted whenever a new screen \a screen has been added to the system. - \sa screens(), primaryScreen(), screenRemoved() + \sa screens(), primaryScreen, screenRemoved() */ /*! @@ -921,18 +911,23 @@ QList QGuiApplication::screens() \since 5.4 */ + /*! - \fn void QGuiApplication::primaryScreenChanged(QScreen *screen) + \property QGuiApplication::primaryScreen - This signal is emitted whenever the primary \a screen changes. This way - applications can keep track of the primaryScreen and react if there is a - new primary screen. + \brief the primary (or default) screen of the application, or null if there is none. - \sa primaryScreen + This will be the screen where QWindows are initially shown, unless otherwise specified. - \since 5.6 -*/ + On some platforms, it may be null when there are actually no screens connected. + It is not possible to start a new QGuiApplication while there are no screens. + Applications which were running at the time the primary screen was removed + will stop rendering graphics until one or more screens are restored. + The primaryScreenChanged signal was introduced in Qt 5.6. + + \sa screens() +*/ /*! Returns the highest screen device pixel ratio found on -- cgit v1.2.3 From f8cc0164db29084eb048dde194d9a18a0e7d03ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Mon, 15 Jun 2015 13:47:35 +0200 Subject: Android: Always queue calls from Qt to Android. Calling runOnUiThread() only queues calls that comes from a different thread then the UI thread. The problem with the current solution is that we can't promise or rely on the calls being delivered in the same order they were called. Another consequence of the old behavior is that we potentially cause long lasting synchronization points, which can cause the application to become unresponsive or in worst case result in a deadlock. With this change all calls to runAction() will be queued on Android's main message queue (aka the UI thread) and return immediately. Change-Id: I50a4273ae9ba8ad17fb2c50ccd57449e4fbc12f9 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/android/jar/src/org/qtproject/qt5/android/QtNative.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java index a1e7dac4d4..0c01e67637 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java @@ -42,6 +42,8 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; import android.net.Uri; +import android.os.Handler; +import android.os.Looper; import android.text.ClipboardManager; import android.os.Build; import android.util.Log; @@ -173,14 +175,14 @@ public class QtNative m_lostActions.clear(); } - private static boolean runAction(Runnable action) + private static void runAction(Runnable action) { synchronized (m_mainActivityMutex) { - if (m_activity == null) + final Looper mainLooper = Looper.getMainLooper(); + final Handler handler = new Handler(mainLooper); + final boolean actionIsQueued = m_activity != null && mainLooper != null && handler.post(action); + if (!actionIsQueued) m_lostActions.add(action); - else - m_activity.runOnUiThread(action); - return m_activity != null; } } -- cgit v1.2.3 From d36a1dfb51af3f981262bc8e8fcd22b91aa890a6 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Tue, 1 Sep 2015 03:03:28 +0200 Subject: Serialize the capitalization value of QFont By serializing the capitalization value of QFont, it ensures that it is correctly preserved when QPicture streams it and later plays it back. Subsequently the QDataStream version has been bumped up to account for the change of the data format for serializing QFont. [ChangeLog][QtGui][QFont] QFont now serializes the capitalization setting. [ChangeLog][Important Behavior Changes] QDataStream version bumped up to 17 to account for changes in the serialization of QFont. Task-number: QTBUG-15214 Change-Id: I042680760e5a69d18d41e786b7500a3eebbe562f Reviewed-by: Mitch Curtis --- src/corelib/io/qdatastream.cpp | 2 +- src/corelib/io/qdatastream.h | 2 +- src/gui/text/qfont.cpp | 8 +++++++- 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp index 713b5a2f55..675178ea80 100644 --- a/src/corelib/io/qdatastream.cpp +++ b/src/corelib/io/qdatastream.cpp @@ -526,7 +526,7 @@ void QDataStream::setByteOrder(ByteOrder bo) \value Qt_5_3 Same as Qt_5_2 \value Qt_5_4 Version 16 (Qt 5.4) \value Qt_5_5 Same as Qt_5_4 - \value Qt_5_6 Same as Qt_5_4 + \value Qt_5_6 Version 17 (Qt 5.6) \omitvalue Qt_DefaultCompiledVersion \sa setVersion(), version() diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h index b87dbe4784..5730c12907 100644 --- a/src/corelib/io/qdatastream.h +++ b/src/corelib/io/qdatastream.h @@ -83,7 +83,7 @@ public: Qt_5_3 = Qt_5_2, Qt_5_4 = 16, Qt_5_5 = Qt_5_4, - Qt_5_6 = Qt_5_5, + Qt_5_6 = 17, #if QT_VERSION >= 0x050700 #error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion #endif diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index 796f223797..7d9d00713c 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -2218,6 +2218,8 @@ QDataStream &operator<<(QDataStream &s, const QFont &font) } if (s.version() >= QDataStream::Qt_5_4) s << (quint8)font.d->request.hintingPreference; + if (s.version() >= QDataStream::Qt_5_6) + s << (quint8)font.d->capital; return s; } @@ -2308,7 +2310,11 @@ QDataStream &operator>>(QDataStream &s, QFont &font) s >> value; font.d->request.hintingPreference = QFont::HintingPreference(value); } - + if (s.version() >= QDataStream::Qt_5_6) { + quint8 value; + s >> value; + font.d->capital = QFont::Capitalization(value); + } return s; } -- cgit v1.2.3 From f807a6de2c14714ffe0fdddac54ef41325613764 Mon Sep 17 00:00:00 2001 From: Serge Lysenko Date: Mon, 31 Aug 2015 19:43:45 +0300 Subject: Fix QImageReader::size() to return correct size for .ico files. According to MSDN, the zero value of ICONDIRENTRY bHeight and bWidth fields mean a maximum icon size 256 pixels. So QtIcoHandler::option() should return 256 instead of 0 pixels for such icons. Also there is fixed wrong seek offset at the second call on this method. http://blogs.msdn.com/b/oldnewthing/archive/2010/10/18/10077133.aspx Task-number: QTBUG-48103 Change-Id: I99f0c9720fd58889045b0c73c51498f2065b0b91 Reviewed-by: Friedemann Kleint Reviewed-by: aavit --- src/plugins/imageformats/ico/qicohandler.cpp | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp index 2ddbc4519b..6d2c06c9c8 100644 --- a/src/plugins/imageformats/ico/qicohandler.cpp +++ b/src/plugins/imageformats/ico/qicohandler.cpp @@ -100,9 +100,10 @@ public: static bool write(QIODevice *device, const QVector &images); + bool readIconEntry(int index, ICONDIRENTRY * iconEntry); + private: bool readHeader(); - bool readIconEntry(int index, ICONDIRENTRY * iconEntry); bool readBMPHeader(quint32 imageOffset, BMP_INFOHDR * header); void findColorInfo(QImage & image); @@ -341,7 +342,7 @@ bool ICOReader::readHeader() bool ICOReader::readIconEntry(int index, ICONDIRENTRY *iconEntry) { - if (iod) { + if (readHeader()) { if (iod->seek(startpos + ICONDIR_SIZE + (index * ICONDIRENTRY_SIZE))) { return readIconDirEntry(iod, iconEntry); } @@ -558,10 +559,10 @@ QImage ICOReader::iconAt(int index) if (icoAttrib.ncolors > 256) //color table can't be more than 256 return img; icoAttrib.w = iconEntry.bWidth; - if (icoAttrib.w == 0) + if (icoAttrib.w == 0) // means 256 pixels icoAttrib.w = header.biWidth; icoAttrib.h = iconEntry.bHeight; - if (icoAttrib.h == 0) + if (icoAttrib.h == 0) // means 256 pixels icoAttrib.h = header.biHeight/2; QImage::Format format = QImage::Format_ARGB32; @@ -779,17 +780,11 @@ QtIcoHandler::~QtIcoHandler() QVariant QtIcoHandler::option(ImageOption option) const { if (option == Size) { - QIODevice *device = QImageIOHandler::device(); - qint64 oldPos = device->pos(); ICONDIRENTRY iconEntry; - if (device->seek(oldPos + ICONDIR_SIZE + (m_currentIconIndex * ICONDIRENTRY_SIZE))) { - if (readIconDirEntry(device, &iconEntry)) { - device->seek(oldPos); - return QSize(iconEntry.bWidth, iconEntry.bHeight); - } + if (m_pICOReader->readIconEntry(m_currentIconIndex, &iconEntry)) { + return QSize(iconEntry.bWidth ? iconEntry.bWidth : 256, + iconEntry.bHeight ? iconEntry.bHeight : 256); } - if (!device->isSequential()) - device->seek(oldPos); } return QVariant(); } -- cgit v1.2.3 From 67d4052be5f9b04bcb40d419370859fe71657d62 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Mon, 21 Sep 2015 09:55:37 +0200 Subject: Fix evdevtouch coordinates when high DPI scaling is in use MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Report coordinates in the native coordinate system. Change-Id: I1bfc495dd02e9a6033707bccb11066732d6cc0da Reviewed-by: Laszlo Agocs Reviewed-by: Morten Johan Sørvig --- src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp b/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp index 1ca95074b9..5560d910ac 100644 --- a/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp +++ b/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -604,9 +605,10 @@ void QEvdevTouchScreenData::reportPoints() QWindow *win = QGuiApplication::focusWindow(); if (!win) return; - winRect = win->geometry(); + winRect = QHighDpi::toNativePixels(win->geometry(), win); } else { - winRect = QGuiApplication::primaryScreen()->geometry(); + QScreen *primary = QGuiApplication::primaryScreen(); + winRect = QHighDpi::toNativePixels(primary->geometry(), primary); } const int hw_w = hw_range_x_max - hw_range_x_min; -- cgit v1.2.3 From 05d401104ee6b10699b7288ead044d6765b19c4d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 17 Sep 2015 11:35:36 -0700 Subject: Fix QtCore compilation with clang The .altmacro is not supported with Clang's integrated assembly. The worst part is that I had this fixed, but apparently I never pushed the update to Gerrit and then we staged the old version. This commit brings back the fixes. Incidentally, it also makes things work with freebsd-clang. Change-Id: Id2a5d90d07d7ee470fcb9ad9696a9a0f9ced7ea7 Reviewed-by: Lars Knoll Reviewed-by: Simon Hausmann --- src/corelib/global/global.pri | 28 ++++++++++++++++++++++++++-- src/corelib/global/qversiontagging.cpp | 15 +++++++++++---- 2 files changed, 37 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri index 8ecde5a769..eb8600f796 100644 --- a/src/corelib/global/global.pri +++ b/src/corelib/global/global.pri @@ -27,8 +27,7 @@ SOURCES += \ global/qmalloc.cpp \ global/qnumeric.cpp \ global/qlogging.cpp \ - global/qhooks.cpp \ - global/qversiontagging.cpp + global/qhooks.cpp # qlibraryinfo.cpp includes qconfig.cpp INCLUDEPATH += $$QT_BUILD_TREE/src/corelib/global @@ -59,3 +58,28 @@ journald { syslog { DEFINES += QT_USE_SYSLOG } + +linux|freebsd { + VERSIONTAGGING_SOURCES = global/qversiontagging.cpp + ltcg|clang { + versiontagging_compiler.commands = $$QMAKE_CXX -c $(CXXFLAGS) $(INCPATH) + + # Disable LTO, as the global inline assembly may not get processed + versiontagging_compiler.commands += -fno-lto + + # Disable the integrated assembler for Clang, since it can't parse with + # the alternate macro syntax in use in qversiontagging.cpp + clang: versiontagging_compiler.commands += -no-integrated-as + + versiontagging_compiler.commands += -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN} + versiontagging_compiler.dependency_type = TYPE_C + versiontagging_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} + versiontagging_compiler.input = VERSIONTAGGING_SOURCES + versiontagging_compiler.variable_out = OBJECTS + versiontagging_compiler.name = compiling[versiontagging] ${QMAKE_FILE_IN} + silent: versiontagging_compiler.commands = @echo compiling[versiontagging] ${QMAKE_FILE_IN} && $$versiontagging_compiler.commands + QMAKE_EXTRA_COMPILERS += versiontagging_compiler + } else { + SOURCES += $$VERSIONTAGGING_SOURCES + } +} diff --git a/src/corelib/global/qversiontagging.cpp b/src/corelib/global/qversiontagging.cpp index e3d9efa16b..66d3f8d00f 100644 --- a/src/corelib/global/qversiontagging.cpp +++ b/src/corelib/global/qversiontagging.cpp @@ -33,18 +33,25 @@ #include "qglobal.h" -#if defined(Q_CC_GNU) && defined(Q_OS_LINUX) && defined(Q_PROCESSOR_X86) && !defined(QT_STATIC) +#if defined(Q_CC_GNU) && (defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)) && defined(Q_PROCESSOR_X86) && !defined(QT_STATIC) # define SYM QT_MANGLE_NAMESPACE(qt_version_tag) # define SSYM QT_STRINGIFY(SYM) asm( +// ASM macro that makes one ELF versioned symbol +".macro make_versioned_symbol plainsym versionedsym\n" +".globl plainsym\n" +".type plainsym, @object\n" +".size plainsym, 1\n" +".symver plainsym, versionedsym\n" +"plainsym :\n" +".endm\n" + // ASM macro that makes one ELF versioned symbol qt_version_tag{sep}Qt_{major}.{minor} // that is an alias to qt_version_tag_{major}_{minor}. // The {sep} parameter must be @ for all old versions and @@ for the current version. ".macro make_one_tag major minor sep\n" -".globl " SSYM "_\\major\\()_\\minor\n" // make the symbol global -SSYM "_\\major\\()_\\minor:\n" // declare it -" .symver " SSYM "_\\major\\()_\\minor, " SSYM "\\sep\\()Qt_\\major\\().\\minor\n" +" make_versioned_symbol " SSYM "_\\major\\()_\\minor, " SSYM "\\sep\\()Qt_\\major\\().\\minor\n" ".endm\n" ".altmacro\n" -- cgit v1.2.3 From c0a3515d8daeda18e93a282a38a11583e27d32be Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 20 Sep 2015 10:44:23 -0700 Subject: Pretend the X11 "compose" platform input context plugin to be "xim" too This is for compatibility with old Qt versions that had this. Task-number: QTBUG-48360 Change-Id: I42e7ef1a481840699a8dffff1405c0a348e32e27 Reviewed-by: Gatis Paeglis --- src/plugins/platforminputcontexts/compose/compose.json | 2 +- .../platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/plugins/platforminputcontexts/compose/compose.json b/src/plugins/platforminputcontexts/compose/compose.json index 2daf89ed30..fb95f1bfb0 100644 --- a/src/plugins/platforminputcontexts/compose/compose.json +++ b/src/plugins/platforminputcontexts/compose/compose.json @@ -1,3 +1,3 @@ { - "Keys": [ "compose" ] + "Keys": [ "compose", "xim" ] } diff --git a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp index 96f6424ba2..15c98ed006 100644 --- a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp +++ b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontextmain.cpp @@ -52,7 +52,8 @@ QComposeInputContext *QComposePlatformInputContextPlugin::create(const QString & { Q_UNUSED(paramList); - if (system.compare(system, QLatin1String("compose"), Qt::CaseInsensitive) == 0) + if (system.compare(system, QLatin1String("compose"), Qt::CaseInsensitive) == 0 + || system.compare(system, QLatin1String("xim"), Qt::CaseInsensitive) == 0) return new QComposeInputContext; return 0; } -- cgit v1.2.3 From ae880beb7d02141c5097ef61409fa66b2c910dd3 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 1 Sep 2015 18:52:30 -0700 Subject: Fix build error with ICC 16 on Windows This is a repeat of acf80b9a2b913e898ed4c4ed14d4ea79401484fe, but this time it appears ICC 15 works and ICC 16 doesn't. ICC doesn't like polymorphic, exported classes with inline constructors. qsvgiconengine.obj : error LNK2001: unresolved external symbol "const QIconEngine::`vftable'" (??_7QIconEngine@@6B@) Task-number: QTBUG-48062 Change-Id: I82493c0f52084e0588352cd0c26e1293b0727242 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/gui/image/qiconengine.cpp | 7 +++++++ src/gui/image/qiconengine.h | 1 + 2 files changed, 8 insertions(+) (limited to 'src') diff --git a/src/gui/image/qiconengine.cpp b/src/gui/image/qiconengine.cpp index a25b216432..c09933d45f 100644 --- a/src/gui/image/qiconengine.cpp +++ b/src/gui/image/qiconengine.cpp @@ -77,6 +77,13 @@ QSize QIconEngine::actualSize(const QSize &size, QIcon::Mode /*mode*/, QIcon::St return size; } +/*! + \since 5.6 + Constructs the icon engine. + */ +QIconEngine::QIconEngine() +{ +} /*! Destroys the icon engine. diff --git a/src/gui/image/qiconengine.h b/src/gui/image/qiconengine.h index 735da863fd..9977113054 100644 --- a/src/gui/image/qiconengine.h +++ b/src/gui/image/qiconengine.h @@ -44,6 +44,7 @@ QT_BEGIN_NAMESPACE class Q_GUI_EXPORT QIconEngine { public: + QIconEngine(); virtual ~QIconEngine(); virtual void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) = 0; virtual QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state); -- cgit v1.2.3 From 42c6ea4f6c29845d68e865b19a73a09cc6d0bdbe Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 15 Sep 2015 12:12:51 +0200 Subject: QPlatformWindow: Extract static method for closestAcceptableGeometry(). On Windows, some messages occur before a QPlatformWindow is actually created, for example WM_WINDOWPOSCHANGING, which is handled in QWindowsWindow::handleGeometryChangingMessage(). Extract a static function QPlatformWindow::closestAcceptableGeometry() from QPlatformWindow::windowClosestAcceptableGeometry() and use that in QWindowsWindow::handleGeometryChangingMessage(). This fixes a regression crash occurring in Qt 5.6 when running the example from QTBUG-48201. Task-number: QTBUG-36220 Task-number: QTBUG-48201 Task-number: QTBUG-46615 Change-Id: I86b8f923447c8e447382427cf5795628ef1c9717 Reviewed-by: Joerg Bornemann --- src/gui/kernel/qplatformwindow.cpp | 11 ++++++++--- src/gui/kernel/qplatformwindow.h | 1 + src/plugins/platforms/windows/qwindowswindow.cpp | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp index 0430d5a4c6..ea3b75c81c 100644 --- a/src/gui/kernel/qplatformwindow.cpp +++ b/src/gui/kernel/qplatformwindow.cpp @@ -702,15 +702,20 @@ QRect QPlatformWindow::windowFrameGeometry() const a resize/move event for platforms that support it, for example to implement heightForWidth(). */ -QRectF QPlatformWindow::windowClosestAcceptableGeometry(const QRectF &nativeRect) const + +QRectF QPlatformWindow::closestAcceptableGeometry(const QWindow *qWindow, const QRectF &nativeRect) { - QWindow *qWindow = window(); const QRectF rectF = QHighDpi::fromNativePixels(nativeRect, qWindow); - const QRectF correctedGeometryF = qt_window_private(qWindow)->closestAcceptableGeometry(rectF); + const QRectF correctedGeometryF = qt_window_private(const_cast(qWindow))->closestAcceptableGeometry(rectF); return !correctedGeometryF.isEmpty() && rectF != correctedGeometryF ? QHighDpi::toNativePixels(correctedGeometryF, qWindow) : nativeRect; } +QRectF QPlatformWindow::windowClosestAcceptableGeometry(const QRectF &nativeRect) const +{ + return QPlatformWindow::closestAcceptableGeometry(window(), nativeRect); +} + /*! \class QPlatformWindow \since 4.8 diff --git a/src/gui/kernel/qplatformwindow.h b/src/gui/kernel/qplatformwindow.h index 1b283dbb4f..9c2817906f 100644 --- a/src/gui/kernel/qplatformwindow.h +++ b/src/gui/kernel/qplatformwindow.h @@ -140,6 +140,7 @@ public: QRect windowGeometry() const; QRect windowFrameGeometry() const; QRectF windowClosestAcceptableGeometry(const QRectF &nativeRect) const; + static QRectF closestAcceptableGeometry(const QWindow *w, const QRectF &nativeRect); protected: static QString formatWindowTitle(const QString &title, const QString &separator); diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index f9b34334df..531836015c 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1825,7 +1825,7 @@ bool QWindowsWindow::handleGeometryChangingMessage(MSG *message, const QWindow * const QRect suggestedFrameGeometry(windowPos->x, windowPos->y, windowPos->cx, windowPos->cy); const QRect suggestedGeometry = suggestedFrameGeometry - margins; - const QRectF correctedGeometryF = qWindow->handle()->windowClosestAcceptableGeometry(suggestedGeometry); + const QRectF correctedGeometryF = QPlatformWindow::closestAcceptableGeometry(qWindow, suggestedGeometry); if (!correctedGeometryF.isValid()) return false; const QRect correctedFrameGeometry = correctedGeometryF.toRect() + margins; -- cgit v1.2.3 From 72bd5d1db9921c30b932eacbce1d58a205d286a8 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 16 Sep 2015 11:14:21 +0200 Subject: QtNetwork documentation: Emphasize QTcpServer::addPendingConnection(). Add note mentioning it to QTcpSocket::incomingConnection() and update SSL socket server code snippet accordingly. Change-Id: I9d228dabde76f9e9cd5140edf08be09a588066c8 Reviewed-by: Thiago Macieira --- src/network/doc/snippets/code/src_network_ssl_qsslsocket.cpp | 3 ++- src/network/socket/qtcpserver.cpp | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/network/doc/snippets/code/src_network_ssl_qsslsocket.cpp b/src/network/doc/snippets/code/src_network_ssl_qsslsocket.cpp index a7ab8c0977..3bd57f1d44 100644 --- a/src/network/doc/snippets/code/src_network_ssl_qsslsocket.cpp +++ b/src/network/doc/snippets/code/src_network_ssl_qsslsocket.cpp @@ -51,7 +51,8 @@ void SslServer::incomingConnection(qintptr socketDescriptor) { QSslSocket *serverSocket = new QSslSocket; if (serverSocket->setSocketDescriptor(socketDescriptor)) { - connect(serverSocket, SIGNAL(encrypted()), this, SLOT(ready())); + addPendingConnection(serverSocket); + connect(serverSocket, &QSslSocket::encrypted, this, &SslServer::ready); serverSocket->startServerEncryption(); } else { delete serverSocket; diff --git a/src/network/socket/qtcpserver.cpp b/src/network/socket/qtcpserver.cpp index 914c14877e..bf75666548 100644 --- a/src/network/socket/qtcpserver.cpp +++ b/src/network/socket/qtcpserver.cpp @@ -559,6 +559,10 @@ QTcpSocket *QTcpServer::nextPendingConnection() may not be usable with native socket functions, and should only be used with QTcpSocket::setSocketDescriptor(). + \note If another socket is created in the reimplementation + of this method, it needs to be added to the Pending Connections mechanism + by calling addPendingConnection(). + \note If you want to handle an incoming connection as a new QTcpSocket object in another thread you have to pass the socketDescriptor to the other thread and create the QTcpSocket object there and -- cgit v1.2.3 From 30c8e845be91bcd3e903ec44f17ad686a7c285a7 Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Tue, 5 May 2015 12:27:51 +0300 Subject: xcb: Use the correct property type when requesting virtual roots Virtual roots are windows, so we should request XCB_ATOM_WINDOW instead of XCB_ATOM_ATOM. Change-Id: I59558b1a3c37cb9bcad42bc0695d420f59088eb9 Reviewed-by: Uli Schlachter Reviewed-by: Lars Knoll --- src/plugins/platforms/xcb/qxcbwmsupport.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbwmsupport.cpp b/src/plugins/platforms/xcb/qxcbwmsupport.cpp index 7d31ac7118..82c1c1de77 100644 --- a/src/plugins/platforms/xcb/qxcbwmsupport.cpp +++ b/src/plugins/platforms/xcb/qxcbwmsupport.cpp @@ -94,14 +94,14 @@ void QXcbWMSupport::updateVirtualRoots() int offset = 0; int remaining = 0; do { - xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, root, atom(QXcbAtom::_NET_VIRTUAL_ROOTS), XCB_ATOM_ATOM, offset, 1024); + xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, root, atom(QXcbAtom::_NET_VIRTUAL_ROOTS), XCB_ATOM_WINDOW, offset, 1024); xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, NULL); if (!reply) break; remaining = 0; - if (reply->type == XCB_ATOM_ATOM && reply->format == 32) { + if (reply->type == XCB_ATOM_WINDOW && reply->format == 32) { int len = xcb_get_property_value_length(reply)/sizeof(xcb_window_t); xcb_window_t *roots = (xcb_window_t *)xcb_get_property_value(reply); int s = net_virtual_roots.size(); -- cgit v1.2.3 From a0aad95f5ad1ff044f5e46cf2d3302c42d058f6a Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Tue, 8 Sep 2015 17:59:17 +0300 Subject: Set the source for a detached mouse button event If a mouse event from the window system changes both position and buttons at the same time, then it's split by QGuiApplication into a mouse move event followed by a mouse button event. Propagate the source of the original mouse event to the mouse button event. Change-Id: I075fb4ad9e4338bf8ec170630ce270b38d8682d9 Reviewed-by: Friedemann Kleint --- src/gui/kernel/qguiapplication.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index fc87759227..94c831e18c 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1713,7 +1713,7 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo // should first send a move event followed by a button changed event. Since this is not the case // with the current event, we split it in two. QWindowSystemInterfacePrivate::MouseEvent mouseButtonEvent( - e->window.data(), e->timestamp, e->type, e->localPos, e->globalPos, e->buttons, e->modifiers); + e->window.data(), e->timestamp, e->type, e->localPos, e->globalPos, e->buttons, e->modifiers, e->source); if (e->flags & QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic) mouseButtonEvent.flags |= QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic; e->buttons = buttons; -- cgit v1.2.3 From 827d0c023222c58443bd825c6287949a2cc07de7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 10 Sep 2015 14:02:52 +0200 Subject: QLineEdit: Don't include left and right minimum bearing when drawing text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The naturalTextWidth() of the QTextLayout already includes the left and right bearing of the actual text in the line edit, there's no need to shift the text based on the minimum left and right bearings as well. This may result in text that is closer to the edges of the line edit on platforms that relied on this flawed logic, but that should be adjusted back using the corresponding style hints. Change-Id: I1d5edbeda7afe3e69b972841d280eb9e573675f5 Reviewed-by: Lars Knoll Reviewed-by: Tor Arne Vestbø Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/widgets/widgets/qlineedit.cpp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp index 0500907b3d..32502fca09 100644 --- a/src/widgets/widgets/qlineedit.cpp +++ b/src/widgets/widgets/qlineedit.cpp @@ -1897,18 +1897,14 @@ void QLineEdit::paintEvent(QPaintEvent *) } QRect lineRect(r.x() + d->horizontalMargin, d->vscroll, r.width() - 2*d->horizontalMargin, fm.height()); - int minLB = qMax(0, -fm.minLeftBearing()); - int minRB = qMax(0, -fm.minRightBearing()); - if (d->shouldShowPlaceholderText()) { if (!d->placeholderText.isEmpty()) { QColor col = pal.text().color(); col.setAlpha(128); QPen oldpen = p.pen(); p.setPen(col); - QRect ph = lineRect.adjusted(minLB, 0, 0, 0); - QString elidedText = fm.elidedText(d->placeholderText, Qt::ElideRight, ph.width()); - p.drawText(ph, va, elidedText); + QString elidedText = fm.elidedText(d->placeholderText, Qt::ElideRight, lineRect.width()); + p.drawText(lineRect, va, elidedText); p.setPen(oldpen); } } @@ -1918,11 +1914,10 @@ void QLineEdit::paintEvent(QPaintEvent *) // horizontal scrolling. d->hscroll is the left indent from the beginning // of the text line to the left edge of lineRect. we update this value // depending on the delta from the last paint event; in effect this means - // the below code handles all scrolling based on the textline (widthUsed, - // minLB, minRB), the line edit rect (lineRect) and the cursor position - // (cix). - int widthUsed = qRound(d->control->naturalTextWidth()) + 1 + minRB; - if ((minLB + widthUsed) <= lineRect.width()) { + // the below code handles all scrolling based on the textline (widthUsed), + // the line edit rect (lineRect) and the cursor position (cix). + int widthUsed = qRound(d->control->naturalTextWidth()) + 1; + if (widthUsed <= lineRect.width()) { // text fits in lineRect; use hscroll for alignment switch (va & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) { case Qt::AlignRight: @@ -1936,7 +1931,6 @@ void QLineEdit::paintEvent(QPaintEvent *) d->hscroll = 0; break; } - d->hscroll -= minLB; } else if (cix - d->hscroll >= lineRect.width()) { // text doesn't fit, cursor is to the right of lineRect (scroll right) d->hscroll = cix - lineRect.width() + 1; -- cgit v1.2.3 From 46a372e1a115fb05b746339c790a7f3e5d6d01fc Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Mon, 13 Jul 2015 20:16:44 -0700 Subject: Modernize and unify filesystem code on Apple platforms. Replace deprecated File Manager APIs with modern equivalents. Change some Q_OS_MACX to Q_OS_DARWIN in file system related code. All of these apply to iOS as well as OS X, and were ifdef'ed for OS X only primarily due to legacy reasons - carryovers from Qt 4 or Carbon APIs which have since been refactored into using CoreFoundation. This also makes the code consistent with the documentation. Change-Id: I414e9bdfffff731413ddf16171b1317027d87caf Reviewed-by: Richard Moe Gustavsen --- src/corelib/io/io.pri | 1 + src/corelib/io/qfilesystemengine.cpp | 2 +- src/corelib/io/qfilesystemengine_p.h | 2 +- src/corelib/io/qfilesystemengine_unix.cpp | 161 ++++++++++++++---------------- src/corelib/io/qfilesystemmetadata_p.h | 4 +- src/corelib/io/qstorageinfo_mac.cpp | 40 +++----- 6 files changed, 94 insertions(+), 116 deletions(-) (limited to 'src') diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index f496d037d8..b2bcbdf727 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -160,6 +160,7 @@ win32 { } else:ios { OBJECTIVE_SOURCES += io/qstandardpaths_ios.mm SOURCES += io/qstorageinfo_mac.cpp + LIBS += -framework MobileCoreServices } else { SOURCES += io/qstandardpaths_unix.cpp } diff --git a/src/corelib/io/qfilesystemengine.cpp b/src/corelib/io/qfilesystemengine.cpp index df41457a18..e4dec2b7fb 100644 --- a/src/corelib/io/qfilesystemengine.cpp +++ b/src/corelib/io/qfilesystemengine.cpp @@ -264,7 +264,7 @@ void QFileSystemMetaData::fillFromStatBuf(const QT_STATBUF &statBuffer) // Attributes entryFlags |= QFileSystemMetaData::ExistsAttribute; size_ = statBuffer.st_size; -#if defined(Q_OS_MACX) +#if defined(Q_OS_DARWIN) if (statBuffer.st_flags & UF_HIDDEN) { entryFlags |= QFileSystemMetaData::HiddenAttribute; knownFlagsMask |= QFileSystemMetaData::HiddenAttribute; diff --git a/src/corelib/io/qfilesystemengine_p.h b/src/corelib/io/qfilesystemengine_p.h index 06d5db637a..6db9319836 100644 --- a/src/corelib/io/qfilesystemengine_p.h +++ b/src/corelib/io/qfilesystemengine_p.h @@ -76,7 +76,7 @@ public: static QString resolveGroupName(uint groupId); #endif -#if defined(Q_OS_MACX) +#if defined(Q_OS_DARWIN) static QString bundleName(const QFileSystemEntry &entry); #else static QString bundleName(const QFileSystemEntry &entry) { Q_UNUSED(entry) return QString(); } diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index 2c9fed530b..7bc2293b0d 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -51,26 +51,38 @@ # include #endif +#ifdef Q_OS_OSX +#include +#endif + +#ifdef Q_OS_IOS +#include +#endif + QT_BEGIN_NAMESPACE -#if defined(Q_OS_MACX) -static inline bool _q_isMacHidden(const char *nativePath) +#if defined(Q_OS_DARWIN) +static inline bool hasResourcePropertyFlag(const QFileSystemMetaData &data, + const QFileSystemEntry &entry, + CFStringRef key) { - OSErr err; - - FSRef fsRef; - err = FSPathMakeRefWithOptions(reinterpret_cast(nativePath), - kFSPathMakeRefDoNotFollowLeafSymlink, &fsRef, 0); - if (err != noErr) + QCFString path = CFStringCreateWithFileSystemRepresentation(0, + entry.nativeFilePath().constData()); + if (!path) return false; - FSCatalogInfo catInfo; - err = FSGetCatalogInfo(&fsRef, kFSCatInfoFinderInfo, &catInfo, NULL, NULL, NULL); - if (err != noErr) + QCFType url = CFURLCreateWithFileSystemPath(0, path, kCFURLPOSIXPathStyle, + data.hasFlags(QFileSystemMetaData::DirectoryType)); + if (!url) return false; - FileInfo * const fileInfo = reinterpret_cast(&catInfo.finderInfo); - return (fileInfo->finderFlags & kIsInvisible); + CFBooleanRef value; + if (CFURLCopyResourcePropertyForKey(url, key, &value, NULL)) { + if (value == kCFBooleanTrue) + return true; + } + + return false; } static bool isPackage(const QFileSystemMetaData &data, const QFileSystemEntry &entry) @@ -97,6 +109,7 @@ static bool isPackage(const QFileSystemMetaData &data, const QFileSystemEntry &e if (CFBundleGetPackageInfoInDirectory(url, &type, &creator)) return true; +#ifdef Q_OS_OSX // Find if an application other than Finder claims to know how to handle the package QCFType application; LSGetApplicationForURL(url, @@ -111,30 +124,11 @@ static bool isPackage(const QFileSystemMetaData &data, const QFileSystemEntry &e if (applicationId != QLatin1String("com.apple.finder")) return true; } +#endif } // Third step: check if the directory has the package bit set - FSRef packageRef; - FSPathMakeRef((UInt8 *)entry.nativeFilePath().constData(), &packageRef, NULL); - - FSCatalogInfo catalogInfo; - FSGetCatalogInfo(&packageRef, - kFSCatInfoFinderInfo, - &catalogInfo, - NULL, - NULL, - NULL); - - FolderInfo *folderInfo = reinterpret_cast(catalogInfo.finderInfo); - return folderInfo->finderFlags & kHasBundle; -} - -#else -static inline bool _q_isMacHidden(const char *nativePath) -{ - Q_UNUSED(nativePath); - // no-op - return false; + return hasResourcePropertyFlag(data, entry, kCFURLIsPackageKey); } #endif @@ -194,21 +188,34 @@ QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link, ret.chop(1); return QFileSystemEntry(ret); } -#if defined(Q_OS_MACX) +#if defined(Q_OS_DARWIN) { - FSRef fref; - if (FSPathMakeRef((const UInt8 *)QFile::encodeName(QDir::cleanPath(link.filePath())).data(), &fref, 0) == noErr) { - // TODO get the meta data info from the QFileSystemMetaData object - Boolean isAlias, isFolder; - if (FSResolveAliasFile(&fref, true, &isFolder, &isAlias) == noErr && isAlias) { - AliasHandle alias; - if (FSNewAlias(0, &fref, &alias) == noErr && alias) { - QCFString cfstr; - if (FSCopyAliasInfo(alias, 0, 0, &cfstr, 0, 0) == noErr) - return QFileSystemEntry(QCFString::toQString(cfstr)); - } - } - } + QCFString path = CFStringCreateWithFileSystemRepresentation(0, + QFile::encodeName(QDir::cleanPath(link.filePath())).data()); + if (!path) + return QFileSystemEntry(); + + QCFType url = CFURLCreateWithFileSystemPath(0, path, kCFURLPOSIXPathStyle, + data.hasFlags(QFileSystemMetaData::DirectoryType)); + if (!url) + return QFileSystemEntry(); + + QCFType bookmarkData = CFURLCreateBookmarkDataFromFile(0, url, NULL); + if (!bookmarkData) + return QFileSystemEntry(); + + QCFType resolvedUrl = CFURLCreateByResolvingBookmarkData(0, + bookmarkData, + (CFURLBookmarkResolutionOptions)(kCFBookmarkResolutionWithoutUIMask + | kCFBookmarkResolutionWithoutMountingMask), NULL, NULL, NULL, NULL); + if (!resolvedUrl) + return QFileSystemEntry(); + + QCFString cfstr(CFURLCopyFileSystemPath(resolvedUrl, kCFURLPOSIXPathStyle)); + if (!cfstr) + return QFileSystemEntry(); + + return QFileSystemEntry(QCFString::toQString(cfstr)); } #endif return QFileSystemEntry(); @@ -226,31 +233,14 @@ QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, return QFileSystemEntry(slowCanonicalized(absoluteName(entry).filePath())); #else char *ret = 0; -# if defined(Q_OS_MACX) - // When using -mmacosx-version-min=10.4, we get the legacy realpath implementation, - // which does not work properly with the realpath(X,0) form. See QTBUG-28282. - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) { - ret = (char*)malloc(PATH_MAX + 1); - if (ret && realpath(entry.nativeFilePath().constData(), (char*)ret) == 0) { - const int savedErrno = errno; // errno is checked below, and free() might change it - free(ret); - errno = savedErrno; - ret = 0; - } - } else { - // on 10.5 we can use FSRef to resolve the file path. - QString path = QDir::cleanPath(entry.filePath()); - FSRef fsref; - if (FSPathMakeRef((const UInt8 *)path.toUtf8().data(), &fsref, 0) == noErr) { - CFURLRef urlref = CFURLCreateFromFSRef(NULL, &fsref); - CFStringRef canonicalPath = CFURLCopyFileSystemPath(urlref, kCFURLPOSIXPathStyle); - QString ret = QCFString::toQString(canonicalPath); - CFRelease(canonicalPath); - CFRelease(urlref); - return QFileSystemEntry(ret); - } +# if defined(Q_OS_DARWIN) + ret = (char*)malloc(PATH_MAX + 1); + if (ret && realpath(entry.nativeFilePath().constData(), (char*)ret) == 0) { + const int savedErrno = errno; // errno is checked below, and free() might change it + free(ret); + errno = savedErrno; + ret = 0; } - # elif defined(Q_OS_ANDROID) // On some Android versions, realpath() will return a path even if it does not exist // To work around this, we check existence in advance. @@ -406,7 +396,7 @@ QString QFileSystemEngine::resolveGroupName(uint groupId) return QString(); } -#if defined(Q_OS_MACX) +#if defined(Q_OS_DARWIN) //static QString QFileSystemEngine::bundleName(const QFileSystemEntry &entry) { @@ -426,7 +416,7 @@ QString QFileSystemEngine::bundleName(const QFileSystemEntry &entry) bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data, QFileSystemMetaData::MetaDataFlags what) { -#if defined(Q_OS_MACX) +#if defined(Q_OS_DARWIN) if (what & QFileSystemMetaData::BundleType) { if (!data.hasFlags(QFileSystemMetaData::DirectoryType)) what |= QFileSystemMetaData::DirectoryType; @@ -435,7 +425,7 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM // OS X >= 10.5: st_flags & UF_HIDDEN what |= QFileSystemMetaData::PosixStatFlags; } -#endif // defined(Q_OS_MACX) +#endif // defined(Q_OS_DARWIN) if (what & QFileSystemMetaData::PosixStatFlags) what |= QFileSystemMetaData::PosixStatFlags; @@ -496,19 +486,11 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM | QFileSystemMetaData::ExistsAttribute; } -#if defined(Q_OS_MACX) +#if defined(Q_OS_DARWIN) if (what & QFileSystemMetaData::AliasType) { - if (entryExists) { - FSRef fref; - if (FSPathMakeRef((const UInt8 *)nativeFilePath, &fref, NULL) == noErr) { - Boolean isAlias, isFolder; - if (FSIsAliasFile(&fref, &isAlias, &isFolder) == noErr) { - if (isAlias) - data.entryFlags |= QFileSystemMetaData::AliasType; - } - } - } + if (entryExists && hasResourcePropertyFlag(data, entry, kCFURLIsAliasFileKey)) + data.entryFlags |= QFileSystemMetaData::AliasType; data.knownFlagsMask |= QFileSystemMetaData::AliasType; } #endif @@ -537,12 +519,15 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM && !data.isHidden()) { QString fileName = entry.fileName(); if ((fileName.size() > 0 && fileName.at(0) == QLatin1Char('.')) - || (entryExists && _q_isMacHidden(nativeFilePath))) +#if defined(Q_OS_DARWIN) + || (entryExists && hasResourcePropertyFlag(data, entry, kCFURLIsHiddenKey)) +#endif + ) data.entryFlags |= QFileSystemMetaData::HiddenAttribute; data.knownFlagsMask |= QFileSystemMetaData::HiddenAttribute; } -#if defined(Q_OS_MACX) +#if defined(Q_OS_DARWIN) if (what & QFileSystemMetaData::BundleType) { if (entryExists && isPackage(data, entry)) data.entryFlags |= QFileSystemMetaData::BundleType; diff --git a/src/corelib/io/qfilesystemmetadata_p.h b/src/corelib/io/qfilesystemmetadata_p.h index da9576b5f8..828b5b329c 100644 --- a/src/corelib/io/qfilesystemmetadata_p.h +++ b/src/corelib/io/qfilesystemmetadata_p.h @@ -93,7 +93,7 @@ public: LinkType = 0x00010000, FileType = 0x00020000, DirectoryType = 0x00040000, -#if defined(Q_OS_MACX) +#if defined(Q_OS_DARWIN) BundleType = 0x00080000, AliasType = 0x08000000, #else @@ -243,7 +243,7 @@ private: Q_DECLARE_OPERATORS_FOR_FLAGS(QFileSystemMetaData::MetaDataFlags) -#if defined(Q_OS_MACX) +#if defined(Q_OS_DARWIN) inline bool QFileSystemMetaData::isBundle() const { return (entryFlags & BundleType); } inline bool QFileSystemMetaData::isAlias() const { return (entryFlags & AliasType); } #else diff --git a/src/corelib/io/qstorageinfo_mac.cpp b/src/corelib/io/qstorageinfo_mac.cpp index 1ef9983918..64ca6d7175 100644 --- a/src/corelib/io/qstorageinfo_mac.cpp +++ b/src/corelib/io/qstorageinfo_mac.cpp @@ -147,32 +147,24 @@ void QStorageInfoPrivate::retrieveUrlProperties(bool initRootPath) void QStorageInfoPrivate::retrieveLabel() { -#if !defined(Q_OS_IOS) - // deprecated since 10.8 - FSRef ref; - FSPathMakeRef(reinterpret_cast(QFile::encodeName(rootPath).constData()), - &ref, - Q_NULLPTR); - - // deprecated since 10.8 - FSCatalogInfo catalogInfo; - OSErr error; - error = FSGetCatalogInfo(&ref, kFSCatInfoVolume, &catalogInfo, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR); - if (error != noErr) + QCFString path = CFStringCreateWithFileSystemRepresentation(0, + QFile::encodeName(rootPath).constData()); + if (!path) return; - // deprecated (use CFURLCopyResourcePropertiesForKeys for 10.7 and higher) - HFSUniStr255 volumeName; - error = FSGetVolumeInfo(catalogInfo.volume, - 0, - Q_NULLPTR, - kFSVolInfoFSInfo, - Q_NULLPTR, - &volumeName, - Q_NULLPTR); - if (error == noErr) - name = QCFString(FSCreateStringFromHFSUniStr(Q_NULLPTR, &volumeName)); -#endif + QCFType url = CFURLCreateWithFileSystemPath(0, path, kCFURLPOSIXPathStyle, true); + if (!url) + return; + + QCFType volumeUrl; + if (!CFURLCopyResourcePropertyForKey(url, kCFURLVolumeURLKey, &volumeUrl, NULL)) + return; + + QCFString volumeName; + if (!CFURLCopyResourcePropertyForKey(url, kCFURLNameKey, &volumeName, NULL)) + return; + + name = volumeName; } QList QStorageInfoPrivate::mountedVolumes() -- cgit v1.2.3 From dc1bf3008e747e12922281c81a0a46775f65880b Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Sun, 6 Sep 2015 15:29:37 -0700 Subject: Clean up some Apple-related includes and declarations. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I92db9691c2243ae72ecd4e11dd4640afaf4bf822 Reviewed-by: Tor Arne Vestbø --- src/corelib/global/qglobal.cpp | 23 ---------------------- src/corelib/kernel/qcore_mac_p.h | 4 ---- src/corelib/thread/qthread_unix.cpp | 3 --- src/network/kernel/qnetworkproxy_mac.cpp | 1 + src/network/ssl/qsslsocket_mac.cpp | 4 ++++ .../fontdatabases/mac/qcoretextfontdatabase.mm | 4 ++-- .../platforms/cocoa/qcocoafiledialoghelper.mm | 3 --- 7 files changed, 7 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index f0208846aa..7da9713e80 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -83,10 +83,6 @@ using namespace ABI::Windows::Networking::Sockets; # include #endif -#if defined(Q_OS_MACX) -#include -#endif - #if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_NO_SDK) #include #endif @@ -1865,25 +1861,6 @@ QT_BEGIN_INCLUDE_NAMESPACE #include "qnamespace.h" QT_END_INCLUDE_NAMESPACE -#if defined(Q_OS_OSX) - -Q_CORE_EXPORT OSErr qt_mac_create_fsref(const QString &file, FSRef *fsref) -{ - return FSPathMakeRef(reinterpret_cast(file.toUtf8().constData()), fsref, 0); -} - -Q_CORE_EXPORT void qt_mac_to_pascal_string(QString s, Str255 str, TextEncoding encoding=0, int len=-1) -{ - Q_UNUSED(encoding); - Q_UNUSED(len); - CFStringGetPascalString(QCFString(s), str, 256, CFStringGetSystemEncoding()); -} - -Q_CORE_EXPORT QString qt_mac_from_pascal_string(const Str255 pstr) { - return QCFString(CFStringCreateWithPascalString(0, pstr, CFStringGetSystemEncoding())); -} -#endif // defined(Q_OS_OSX) - QSysInfo::MacVersion QSysInfo::macVersion() { const QAppleOperatingSystemVersion version = qt_apple_os_version(); // qtcore_mac_objc.mm diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index 4834c14ca8..16156d0f2c 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -57,10 +57,6 @@ #include "qglobal.h" -#ifdef Q_OS_MACX -#include -#endif - #ifdef __OBJC__ #include #endif diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index f054a727cf..4b50936958 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -75,9 +75,6 @@ # define old_qDebug qDebug # undef qDebug # endif -#ifdef Q_OS_MACX -# include -#endif // Q_OS_MACX # ifdef old_qDebug # undef qDebug diff --git a/src/network/kernel/qnetworkproxy_mac.cpp b/src/network/kernel/qnetworkproxy_mac.cpp index 51400f55bb..05d4c6955a 100644 --- a/src/network/kernel/qnetworkproxy_mac.cpp +++ b/src/network/kernel/qnetworkproxy_mac.cpp @@ -35,6 +35,7 @@ #ifndef QT_NO_NETWORKPROXY +#include #include #include diff --git a/src/network/ssl/qsslsocket_mac.cpp b/src/network/ssl/qsslsocket_mac.cpp index 759aee7485..06c707f271 100644 --- a/src/network/ssl/qsslsocket_mac.cpp +++ b/src/network/ssl/qsslsocket_mac.cpp @@ -51,6 +51,10 @@ #include #include +#ifdef Q_OS_OSX +#include +#endif + QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC_WITH_ARGS(QMutex, qt_securetransport_mutex, (QMutex::Recursive)) diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index 357228db14..0af779097c 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -721,8 +721,8 @@ QStringList QCoreTextFontDatabase::addApplicationFont(const QByteArray &fontData kATSOptionFlagsDefault, &fontContainer); } else { FSRef ref; - OSErr qt_mac_create_fsref(const QString &file, FSRef *fsref); - if (qt_mac_create_fsref(fileName, &ref) != noErr) + if (FSPathMakeRef(reinterpret_cast(fileName.toUtf8().constData()), + &ref, 0) != noErr) return QStringList(); e = ATSFontActivateFromFileReference(&ref, kATSFontContextLocal, kATSFontFormatUnspecified, 0, kATSOptionFlagsDefault, &fontContainer); diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index 93ee4e8624..9dc013ba4d 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -588,9 +588,6 @@ void QCocoaFileDialogHelper::QNSOpenSavePanelDelegate_filterSelected(int menuInd emit filterSelected(menuIndex >= 0 && menuIndex < filters.size() ? filters.at(menuIndex) : QString()); } -extern OSErr qt_mac_create_fsref(const QString &, FSRef *); // qglobal.cpp -extern void qt_mac_to_pascal_string(QString s, Str255 str, TextEncoding encoding=0, int len=-1); // qglobal.cpp - void QCocoaFileDialogHelper::setDirectory(const QUrl &directory) { if (mDelegate) -- cgit v1.2.3 From 1af2b861d8915cfa9fe2d79f6ebb2ae22749f37b Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 7 Sep 2015 15:00:09 +0200 Subject: Ensure the accepted state of mouse events is passed to QWindowSystemInterface. On Windows, Qt needs to return false in case it does not handle the "extra" buttons (like WM_XBUTTONDOWN) which causes Windows to send the corresponding WM_APPCOMMAND message (like APPCOMMAND_BROWSER_FORWARD). Task-number: QTBUG-48117 Change-Id: I093cd2d8205a39c3a042dd8a0d19c7229003761f Reviewed-by: Andy Shaw --- src/gui/kernel/qguiapplication.cpp | 1 + src/widgets/kernel/qwidgetwindow.cpp | 1 + 2 files changed, 2 insertions(+) (limited to 'src') diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 94c831e18c..736580f547 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1809,6 +1809,7 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo } QGuiApplication::sendSpontaneousEvent(window, &ev); + e->eventAccepted = ev.isAccepted(); if (!e->synthetic() && !ev.isAccepted() && !frameStrut && qApp->testAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents)) { diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index deaac4e263..09b4edaf1d 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -552,6 +552,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) translated.setTimestamp(event->timestamp()); QApplicationPrivate::sendMouseEvent(receiver, &translated, widget, m_widget, &qt_button_down, qt_last_mouse_receiver); + event->setAccepted(translated.isAccepted()); } #ifndef QT_NO_CONTEXTMENU if (event->type() == contextMenuTrigger && event->button() == Qt::RightButton -- cgit v1.2.3 From 28f251993a067a2e95ccaf3d295460489e8c6e30 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 7 Sep 2015 14:56:15 +0200 Subject: Windows: Return accepted state of XBUTTON mouse events to the OS. Qt needs to return false in case it does not handle the "extra" buttons (like WM_XBUTTONDOWN) which causes Windows to send the corresponding WM_APPCOMMAND message (like APPCOMMAND_BROWSER_FORWARD). Task-number: QTBUG-48117 Change-Id: Id2c8005ee992b0abd8af2aacbcb97c4eedcfa32f Reviewed-by: Andy Shaw --- src/plugins/platforms/windows/qwindowsmousehandler.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index 200eb11855..4ab861a960 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -368,7 +368,10 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, QWindowsKeyMapper::queryKeyboardModifiers(), source); m_previousCaptureWindow = hasCapture ? window : 0; - return true; + // QTBUG-48117, force synchronous handling for the extra buttons so that WM_APPCOMMAND + // is sent for unhandled WM_XBUTTONDOWN. + return (msg.message != WM_XBUTTONUP && msg.message != WM_XBUTTONDOWN && msg.message != WM_XBUTTONDBLCLK) + || QWindowSystemInterface::flushWindowSystemEvents(); } static bool isValidWheelReceiver(QWindow *candidate) -- cgit v1.2.3 From 6a8251a89b6a61258498f4af1ba7b3d5b7f7096c Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 17 Jul 2015 13:22:13 -0700 Subject: Reorganize the bits for the CPU feature detection Instead of trying to detect one bit and set another, let's just use the bits from the x86 CPUID instruction on x86. This makes use of the full 64-bit space now. Since MSVC doesn't like enums bigger than 32-bit, we have to store the bit number instead of the actual bit value in the constant. For that reason, I also renamed the constants, to catch anyone who was using them directly, instead of through qCpuHasFeature. Change-Id: Ib306f8f647014b399b87ffff13f1d587692d827a Reviewed-by: Oswald Buddenhagen Reviewed-by: Thiago Macieira --- src/corelib/tools/qsimd.cpp | 182 ++++++++++++++++++++++++++------------- src/corelib/tools/qsimd_p.h | 60 +++++++------ src/gui/painting/qdrawhelper.cpp | 6 +- 3 files changed, 159 insertions(+), 89 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index 91700c053d..825028037f 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -78,28 +78,28 @@ static inline uint detectProcessorFeatures() return 0; } #elif defined (Q_OS_WINCE) -static inline uint detectProcessorFeatures() +static inline quint64 detectProcessorFeatures() { - uint features = 0; + quint64 features = 0; #if defined (ARM) # ifdef PF_ARM_NEON if (IsProcessorFeaturePresent(PF_ARM_NEON)) - features |= ARM_NEON; + features |= Q_UINT64_C(1) << CpuFeatureNEON; # endif #elif defined(_X86_) if (IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE)) - features |= SSE2; + features |= Q_UINT64_C(1) << CpuFeatureSSE2; if (IsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE)) - features |= SSE3; + features |= Q_UINT64_C(1) << CpuFeatureSSE3; #endif return features; } #elif defined(Q_PROCESSOR_ARM) -static inline uint detectProcessorFeatures() +static inline quint64 detectProcessorFeatures() { - uint features = 0; + quint64 features = 0; #if defined(Q_OS_LINUX) int auxv = qt_safe_open("/proc/self/auxv", O_RDONLY); @@ -117,7 +117,7 @@ static inline uint detectProcessorFeatures() for (int i = 0; i < max; i += 2) if (vector[i] == AT_HWCAP) { if (vector[i+1] & HWCAP_NEON) - features |= NEON; + features |= Q_UINT64_C(1) << CpuFeatureNEON; break; } } @@ -129,7 +129,7 @@ static inline uint detectProcessorFeatures() #endif #if defined(__ARM_NEON__) - features = NEON; + features = Q_UINT64_C(1) << CpuFeatureNEON; #endif return features; @@ -257,6 +257,8 @@ static quint64 detectProcessorFeatures() AVXState = XMM0_15 | YMM0_15Hi128, AVX512State = AVXState | OpMask | ZMM0_15Hi256 | ZMM16_31 }; + static const quint64 AllAVX2 = (Q_UINT64_C(1) << CpuFeatureAVX2); + static const quint64 AllAVX = (Q_UINT64_C(1) << CpuFeatureAVX) | AllAVX2; quint64 features = 0; int cpuidLevel = maxBasicCpuidSupported(); @@ -269,28 +271,23 @@ static quint64 detectProcessorFeatures() uint cpuid01ECX = 0, cpuid01EDX = 0; cpuidFeatures01(cpuid01ECX, cpuid01EDX); + + // the low 32-bits of features is cpuid01ECX + // note: we need to check OS support for saving the AVX register state + features = cpuid01ECX; + #if defined(Q_PROCESSOR_X86_32) // x86 might not have SSE2 support if (cpuid01EDX & (1u << 26)) - features |= SSE2; + features |= Q_UINT64_C(1) << CpuFeatureSSE2; + else + features &= ~(Q_UINT64_C(1) << CpuFeatureSSE2); // we should verify that the OS enabled saving of the SSE state... #else // x86-64 or x32 - features = SSE2; + features |= Q_UINT64_C(1) << CpuFeatureSSE2; #endif - // common part between 32- and 64-bit - if (cpuid01ECX & (1u)) - features |= SSE3; - if (cpuid01ECX & (1u << 9)) - features |= SSSE3; - if (cpuid01ECX & (1u << 19)) - features |= SSE4_1; - if (cpuid01ECX & (1u << 20)) - features |= SSE4_2; - if (cpuid01ECX & (1u << 25)) - features |= 0; // AES, enable if needed - uint xgetbvA = 0, xgetbvD = 0; if (cpuid01ECX & (1u << 27)) { // XGETBV enabled @@ -298,22 +295,17 @@ static quint64 detectProcessorFeatures() } uint cpuid0700EBX = 0; - if (cpuidLevel >= 7) + if (cpuidLevel >= 7) { cpuidFeatures07_00(cpuid0700EBX); - if ((xgetbvA & AVXState) == AVXState) { - // support for YMM and XMM registers is enabled - if (cpuid01ECX & (1u << 28)) - features |= AVX; - - if (cpuid0700EBX & (1u << 5)) - features |= AVX2; + // the high 32-bits of features is cpuid0700EBX + features |= quint64(cpuid0700EBX) << 32; } - if (cpuid0700EBX & (1u << 4)) - features |= HLE; // Hardware Lock Ellision - if (cpuid0700EBX & (1u << 11)) - features |= RTM; // Restricted Transactional Memory + if ((xgetbvA & AVXState) != AVXState) { + // support for YMM registers is disabled, disable all AVX + features &= ~AllAVX; + } return features; } @@ -430,24 +422,24 @@ static bool procCpuinfoContains(const char *prefix, const char *string) } #endif -static inline uint detectProcessorFeatures() +static inline quint64 detectProcessorFeatures() { // NOTE: MIPS 74K cores are the only ones supporting DSPr2. - uint flags = 0; + quint64 flags = 0; #if defined __mips_dsp - flags |= DSP; + flags |= Q_UINT64_C(1) << CpuFeatureDSP; # if defined __mips_dsp_rev && __mips_dsp_rev >= 2 - flags |= DSPR2; + flags |= Q_UINT64_C(1) << CpuFeatureDSPR2; # elif defined(Q_OS_LINUX) if (procCpuinfoContains("cpu model", "MIPS 74Kc") || procCpuinfoContains("cpu model", "MIPS 74Kf")) - flags |= DSPR2; + flags |= Q_UINT64_C(1) << CpuFeatureDSPR2; # endif #elif defined(Q_OS_LINUX) if (procCpuinfoContains("ASEs implemented", "dsp")) { - flags |= DSP; + flags |= Q_UINT64_C(1) << CpuFeatureDSP; if (procCpuinfoContains("cpu model", "MIPS 74Kc") || procCpuinfoContains("cpu model", "MIPS 74Kf")) - flags |= DSPR2; + flags |= Q_UINT64_C(1) << CpuFeatureDSPR2; } #endif @@ -462,47 +454,115 @@ static inline uint detectProcessorFeatures() #endif /* - * Use kdesdk/scripts/generate_string_table.pl to update the table below. - * Here's the data (don't forget the ONE leading space): + * Use kdesdk/scripts/generate_string_table.pl to update the table below. Note + * that the x86 version has a lot of blanks that must be kept and that the + * offset table's type is changed to make the table smaller. We also remove the + * terminating -1 that the script adds. + */ +// begin generated +#if defined(Q_PROCESSOR_ARM) +/* Data: neon - sse2 + */ +static const char features_string[] = " neon\0"; +static const int features_indices[] = { 0 }; +#elif defined(Q_PROCESSOR_MIPS) +/* Data: + dsp + dspr2 +*/ +static const char features_string[] = + " dsp\0" + " dspr2\0" + "\0"; + +static const int features_indices[] = { + 0, 5 +}; +#elif defined(Q_PROCESSOR_X86) +/* Data: sse3 + sse2 + + + + + + + ssse3 + + + fma + cmpxchg16b + + + + + sse4.1 sse4.2 + + movbe + popcnt + + aes + + avx - avx2 + f16c + rdrand + + + + + bmi hle - rtm - dsp - dspr2 - */ + avx2 -// begin generated + + bmi2 + + + rtm + */ static const char features_string[] = - "\0" - " neon\0" - " sse2\0" " sse3\0" + " sse2\0" " ssse3\0" + " fma\0" + " cmpxchg16b\0" " sse4.1\0" " sse4.2\0" + " movbe\0" + " popcnt\0" + " aes\0" " avx\0" - " avx2\0" + " f16c\0" + " rdrand\0" + " bmi\0" " hle\0" + " avx2\0" + " bmi2\0" " rtm\0" - " dsp\0" - " dspr2\0" "\0"; -static const int features_indices[] = { - 0, 1, 7, 13, 19, 26, 34, 42, - 47, 53, 58, 63, 68, -1 +static const quint8 features_indices[] = { + 0, 6, 5, 5, 5, 5, 5, 5, + 5, 12, 5, 5, 19, 24, 5, 5, + 5, 5, 5, 36, 44, 5, 52, 59, + 5, 67, 5, 5, 72, 77, 83, 5, + 5, 5, 5, 91, 96, 101, 5, 5, + 107, 5, 5, 113 }; +#else +static const char features_string[] = ""; +static const int features_indices[] = { }; +#endif // end generated -static const int features_count = (sizeof features_indices - 1) / (sizeof features_indices[0]); +static const int features_count = (sizeof features_indices) / (sizeof features_indices[0]); // record what CPU features were enabled by default in this Qt build static const quint64 minFeature = qCompilerCpuFeatures; diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h index 6ca3836ca9..b815e976a7 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -245,18 +245,29 @@ QT_BEGIN_NAMESPACE enum CPUFeatures { - NEON = 0x2, ARM_NEON = NEON, - SSE2 = 0x4, - SSE3 = 0x8, - SSSE3 = 0x10, - SSE4_1 = 0x20, - SSE4_2 = 0x40, - AVX = 0x80, - AVX2 = 0x100, - HLE = 0x200, - RTM = 0x400, - DSP = 0x800, - DSPR2 = 0x1000, +#if defined(Q_PROCESSOR_ARM) + CpuFeatureNEON = 0, + CpuFeatureARM_NEON = CpuFeatureNEON, +#elif defined(Q_PROCESSOR_MIPS) + CpuFeatureDSP = 0, + CpuFeatureDSPR2 = 1, +#elif defined(Q_PROCESSOR_X86) + // The order of the flags is jumbled so it matches most closely the bits in CPUID + // Out of order: + CpuFeatureSSE2 = 1, // uses the bit for PCLMULQDQ + // in level 1, ECX + CpuFeatureSSE3 = (0 + 0), + CpuFeatureSSSE3 = (0 + 9), + CpuFeatureSSE4_1 = (0 + 19), + CpuFeatureSSE4_2 = (0 + 20), + CpuFeatureAES = (0 + 25), + CpuFeatureAVX = (0 + 28), + + // in level 7, leaf 0, EBX + CpuFeatureHLE = (32 + 4), + CpuFeatureAVX2 = (32 + 5), + CpuFeatureRTM = (32 + 11), +#endif // used only to indicate that the CPU detection was initialised QSimdInitialized = 0x80000000 @@ -264,37 +275,37 @@ enum CPUFeatures { static const uint qCompilerCpuFeatures = 0 #if defined __RTM__ - | RTM + | (Q_UINT64_C(1) << CpuFeatureRTM) #endif #if defined __AVX2__ - | AVX2 + | (Q_UINT64_C(1) << CpuFeatureAVX2) #endif #if defined __AVX__ - | AVX + | (Q_UINT64_C(1) << CpuFeatureAVX) #endif #if defined __SSE4_2__ - | SSE4_2 + | (Q_UINT64_C(1) << CpuFeatureSSE4_2) #endif #if defined __SSE4_1__ - | SSE4_1 + | (Q_UINT64_C(1) << CpuFeatureSSE4_1) #endif #if defined __SSSE3__ - | SSSE3 + | (Q_UINT64_C(1) << CpuFeatureSSSE3) #endif #if defined __SSE3__ - | SSE3 + | (Q_UINT64_C(1) << CpuFeatureSSE3) #endif #if defined __SSE2__ - | SSE2 + | (Q_UINT64_C(1) << CpuFeatureSSE2) #endif #if defined __ARM_NEON__ - | NEON + | (Q_UINT64_C(1) << CpuFeatureNEON) #endif #if defined __mips_dsp - | DSP + | (Q_UINT64_C(1) << CpuFeatureDSP) #endif #if defined __mips_dspr2 - | DSPR2 + | (Q_UINT64_C(1) << CpuFeatureDSPR2) #endif ; @@ -322,7 +333,8 @@ static inline quint64 qCpuFeatures() return features; } -#define qCpuHasFeature(feature) ((qCompilerCpuFeatures & (feature)) || (qCpuFeatures() & (feature))) +#define qCpuHasFeature(feature) ((qCompilerCpuFeatures & (Q_UINT64_C(1) << CpuFeature ## feature)) \ + || (qCpuFeatures() & (Q_UINT64_C(1) << CpuFeature ## feature))) #ifdef Q_PROCESSOR_X86 // Bit scan functions for x86 diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 0cf7e20605..64a363868a 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -6326,8 +6326,6 @@ template const uint *QT_FASTCALL convertA2RGB30PMFromARGB32PM_sse4 void qInitDrawhelperAsm() { - const uint features = qCpuFeatures(); - Q_UNUSED(features); #ifdef __SSE2__ qDrawHelper[QImage::Format_RGB32].bitmapBlit = qt_bitmapblit32_sse2; qDrawHelper[QImage::Format_ARGB32].bitmapBlit = qt_bitmapblit32_sse2; @@ -6372,7 +6370,7 @@ void qInitDrawhelperAsm() qt_fetch_radial_gradient = qt_fetch_radial_gradient_sse2; #ifdef QT_COMPILER_SUPPORTS_SSSE3 - if (features & SSSE3) { + if (qCpuHasFeature(SSSE3)) { extern void qt_blend_argb32_on_argb32_ssse3(uchar *destPixels, int dbpl, const uchar *srcPixels, int sbpl, int w, int h, @@ -6466,7 +6464,7 @@ void qInitDrawhelperAsm() #endif // Q_PROCESSOR_MIPS_32 #if defined(QT_COMPILER_SUPPORTS_MIPS_DSP) || defined(QT_COMPILER_SUPPORTS_MIPS_DSPR2) - if (features & (DSP | DSPR2)) { + if (qCpuHasFeature(DSP) && qCpuHasFeature(DSPR2)) { // Composition functions are all DSP r1 qt_functionForMode_C[QPainter::CompositionMode_SourceOver] = comp_func_SourceOver_asm_mips_dsp; qt_functionForMode_C[QPainter::CompositionMode_Source] = comp_func_Source_mips_dsp; -- cgit v1.2.3 From 0829baf902dbf5982732aa54454178f55b50bdc6 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 17 Jul 2015 14:25:37 -0700 Subject: Expand reporting of the Intel instruction set extensions Detection for most of them is free because we're loading the entire registers anyway. The only exception is AVX512VBMI, which is in a new register we hadn't yet read from. I've also added the new GCC names so they can be used with QT_FUNCTION_TARGET. The only two exceptions are "movbe" and "popcnt", which are extremely restricted in use and we are not likely to have code dedicated to using them. Change-Id: Ib306f8f647014b399b87ffff13f1d8fd29e58be0 Reviewed-by: Oswald Buddenhagen Reviewed-by: Thiago Macieira --- src/corelib/tools/qsimd.cpp | 75 ++++++++++++++++++++++++++++++------ src/corelib/tools/qsimd_p.h | 93 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 155 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index 825028037f..d0c65a04b1 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -205,21 +205,24 @@ static void cpuidFeatures01(uint &ecx, uint &edx) inline void __cpuidex(int info[4], int, __int64) { memset(info, 0, 4*sizeof(int));} #endif -static void cpuidFeatures07_00(uint &ebx) +static void cpuidFeatures07_00(uint &ebx, uint &ecx) { #if defined(Q_CC_GNU) qregisteruint rbx; // in case it's 64-bit + qregisteruint rcx = 0; asm ("xchg " PICreg", %0\n" "cpuid\n" "xchg " PICreg", %0\n" - : "=&r" (rbx) - : "a" (7), "c" (0) + : "=&r" (rbx), "+&c" (rcx) + : "a" (7) : "%edx"); ebx = rbx; + ecx = rcx; #elif defined(Q_OS_WIN) int info[4]; __cpuidex(info, 7, 0); ebx = info[1]; + ecx = info[2]; #endif } @@ -257,7 +260,12 @@ static quint64 detectProcessorFeatures() AVXState = XMM0_15 | YMM0_15Hi128, AVX512State = AVXState | OpMask | ZMM0_15Hi256 | ZMM16_31 }; - static const quint64 AllAVX2 = (Q_UINT64_C(1) << CpuFeatureAVX2); + static const quint64 AllAVX512 = (Q_UINT64_C(1) << CpuFeatureAVX512F) | (Q_UINT64_C(1) << CpuFeatureAVX512CD) | + (Q_UINT64_C(1) << CpuFeatureAVX512ER) | (Q_UINT64_C(1) << CpuFeatureAVX512PF) | + (Q_UINT64_C(1) << CpuFeatureAVX512BW) | (Q_UINT64_C(1) << CpuFeatureAVX512DQ) | + (Q_UINT64_C(1) << CpuFeatureAVX512VL) | + (Q_UINT64_C(1) << CpuFeatureAVX512IFMA) | (Q_UINT64_C(1) << CpuFeatureAVX512VBMI); + static const quint64 AllAVX2 = (Q_UINT64_C(1) << CpuFeatureAVX2) | AllAVX512; static const quint64 AllAVX = (Q_UINT64_C(1) << CpuFeatureAVX) | AllAVX2; quint64 features = 0; @@ -295,8 +303,9 @@ static quint64 detectProcessorFeatures() } uint cpuid0700EBX = 0; + uint cpuid0700ECX = 0; if (cpuidLevel >= 7) { - cpuidFeatures07_00(cpuid0700EBX); + cpuidFeatures07_00(cpuid0700EBX, cpuid0700ECX); // the high 32-bits of features is cpuid0700EBX features |= quint64(cpuid0700EBX) << 32; @@ -305,6 +314,15 @@ static quint64 detectProcessorFeatures() if ((xgetbvA & AVXState) != AVXState) { // support for YMM registers is disabled, disable all AVX features &= ~AllAVX; + } else if ((xgetbvA & AVX512State) != AVX512State) { + // support for ZMM registers or mask registers is disabled, disable all AVX512 + features &= ~AllAVX512; + } else { + // this feature is out of order + if (cpuid0700ECX & (1u << 1)) + features |= Q_UINT64_C(1) << CpuFeatureAVX512VBMI; + else + features &= ~(Q_UINT64_C(1) << CpuFeatureAVX512VBMI); } return features; @@ -484,7 +502,7 @@ static const int features_indices[] = { /* Data: sse3 sse2 - + avx512vbmi @@ -526,10 +544,31 @@ static const int features_indices[] = { rtm + + + + + avx512f + avx512dq + rdseed + + + avx512ifma + + + + + avx512pf + avx512er + avx512cd + sha + avx512bw + avx512vl */ static const char features_string[] = " sse3\0" " sse2\0" + " avx512vbmi\0" " ssse3\0" " fma\0" " cmpxchg16b\0" @@ -546,15 +585,27 @@ static const char features_string[] = " avx2\0" " bmi2\0" " rtm\0" + " avx512f\0" + " avx512dq\0" + " rdseed\0" + " avx512ifma\0" + " avx512pf\0" + " avx512er\0" + " avx512cd\0" + " sha\0" + " avx512bw\0" + " avx512vl\0" "\0"; static const quint8 features_indices[] = { - 0, 6, 5, 5, 5, 5, 5, 5, - 5, 12, 5, 5, 19, 24, 5, 5, - 5, 5, 5, 36, 44, 5, 52, 59, - 5, 67, 5, 5, 72, 77, 83, 5, - 5, 5, 5, 91, 96, 101, 5, 5, - 107, 5, 5, 113 + 0, 6, 12, 5, 5, 5, 5, 5, + 5, 24, 5, 5, 31, 36, 5, 5, + 5, 5, 5, 48, 56, 5, 64, 71, + 5, 79, 5, 5, 84, 89, 95, 5, + 5, 5, 5, 103, 108, 113, 5, 5, + 119, 5, 5, 125, 5, 5, 5, 5, + 130, 139, 149, 5, 5, 157, 5, 5, + 5, 5, 169, 179, 189, 199, 204, 214 }; #else static const char features_string[] = ""; diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h index b815e976a7..be003f6c6d 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -218,6 +218,23 @@ # endif #endif +#define QT_FUNCTION_TARGET_STRING_AVX512F "avx512f" +#define QT_FUNCTION_TARGET_STRING_AVX512CD "avx512cd" +#define QT_FUNCTION_TARGET_STRING_AVX512ER "avx512er" +#define QT_FUNCTION_TARGET_STRING_AVX512PF "avx512pf" +#define QT_FUNCTION_TARGET_STRING_AVX512BW "avx512bw" +#define QT_FUNCTION_TARGET_STRING_AVX512DQ "avx512dq" +#define QT_FUNCTION_TARGET_STRING_AVX512VL "avx512vl" +#define QT_FUNCTION_TARGET_STRING_AVX512IFMA "avx512ifma" +#define QT_FUNCTION_TARGET_STRING_AVX512VBMI "avx512vbmi" + +#define QT_FUNCTION_TARGET_STRING_F16C "f16c" +#define QT_FUNCTION_TARGET_STRING_RDRAND "rdrnd" +#define QT_FUNCTION_TARGET_STRING_BMI "bmi" +#define QT_FUNCTION_TARGET_STRING_BMI2 "bmi2" +#define QT_FUNCTION_TARGET_STRING_RDSEED "rdseed" +#define QT_FUNCTION_TARGET_STRING_SHA "sha" + // other x86 intrinsics #if defined(Q_PROCESSOR_X86) && ((defined(Q_CC_GNU) && (Q_CC_GNU >= 404)) \ || (defined(Q_CC_CLANG) && (Q_CC_CLANG >= 208)) \ @@ -260,23 +277,97 @@ enum CPUFeatures { CpuFeatureSSSE3 = (0 + 9), CpuFeatureSSE4_1 = (0 + 19), CpuFeatureSSE4_2 = (0 + 20), + CpuFeatureMOVBE = (0 + 22), + CpuFeaturePOPCNT = (0 + 23), CpuFeatureAES = (0 + 25), CpuFeatureAVX = (0 + 28), + CpuFeatureF16C = (0 + 29), + CpuFeatureRDRAND = (0 + 30), + // 31 is always zero and we've used it for the QSimdInitialized // in level 7, leaf 0, EBX + CpuFeatureBMI = (32 + 3), CpuFeatureHLE = (32 + 4), CpuFeatureAVX2 = (32 + 5), + CpuFeatureBMI2 = (32 + 8), CpuFeatureRTM = (32 + 11), + CpuFeatureAVX512F = (32 + 16), + CpuFeatureAVX512DQ = (32 + 17), + CpuFeatureRDSEED = (32 + 18), + CpuFeatureAVX512IFMA = (32 + 21), + CpuFeatureAVX512PF = (32 + 26), + CpuFeatureAVX512ER = (32 + 27), + CpuFeatureAVX512CD = (32 + 28), + CpuFeatureSHA = (32 + 29), + CpuFeatureAVX512BW = (32 + 30), + CpuFeatureAVX512VL = (32 + 31), + + // in level 7, leaf 0, ECX (out of order, for now) + CpuFeatureAVX512VBMI = 2, // uses the bit for DTES64 #endif // used only to indicate that the CPU detection was initialised QSimdInitialized = 0x80000000 }; -static const uint qCompilerCpuFeatures = 0 +static const quint64 qCompilerCpuFeatures = 0 +#if defined __SHA__ + | (Q_UINT64_C(1) << CpuFeatureSHA) +#endif +#if defined __AES__ + | (Q_UINT64_C(1) << CpuFeatureAES) +#endif #if defined __RTM__ | (Q_UINT64_C(1) << CpuFeatureRTM) #endif +#ifdef __RDRND__ + | (Q_UINT64_C(1) << CpuFeatureRDRAND) +#endif +#ifdef __RDSEED__ + | (Q_UINT64_C(1) << CpuFeatureRDSEED) +#endif +#if defined __BMI__ + | (Q_UINT64_C(1) << CpuFeatureBMI) +#endif +#if defined __BMI2__ + | (Q_UINT64_C(1) << CpuFeatureBMI2) +#endif +#if defined __F16C__ + | (Q_UINT64_C(1) << CpuFeatureF16C) +#endif +#if defined __POPCNT__ + | (Q_UINT64_C(1) << CpuFeaturePOPCNT) +#endif +#if defined __MOVBE__ // GCC and Clang don't seem to define this + | (Q_UINT64_C(1) << CpuFeatureMOVBE) +#endif +#if defined __AVX512F__ + | (Q_UINT64_C(1) << CpuFeatureAVX512F) +#endif +#if defined __AVX512CD__ + | (Q_UINT64_C(1) << CpuFeatureAVX512CD) +#endif +#if defined __AVX512ER__ + | (Q_UINT64_C(1) << CpuFeatureAVX512ER) +#endif +#if defined __AVX512PF__ + | (Q_UINT64_C(1) << CpuFeatureAVX512PF) +#endif +#if defined __AVX512BW__ + | (Q_UINT64_C(1) << CpuFeatureAVX512BW) +#endif +#if defined __AVX512DQ__ + | (Q_UINT64_C(1) << CpuFeatureAVX512DQ) +#endif +#if defined __AVX512VL__ + | (Q_UINT64_C(1) << CpuFeatureAVX512VL) +#endif +#if defined __AVX512IFMA__ + | (Q_UINT64_C(1) << CpuFeatureAVX512IFMA) +#endif +#if defined __AVX512VBMI__ + | (Q_UINT64_C(1) << CpuFeatureAVX512VBMI) +#endif #if defined __AVX2__ | (Q_UINT64_C(1) << CpuFeatureAVX2) #endif -- cgit v1.2.3 From 4f3379655caac2032e894bf838316ce087802bb7 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Tue, 22 Sep 2015 09:01:30 +0200 Subject: Add an option to skip the generic bearer engine Add an option to skip a generic bearer engine if needed (by testing environment variable QT_EXCLUDE_GENERIC_BEARER). Task-number: QTBUG-41866 Change-Id: I1b53ed1d22a7b34de5c6f6d0386ed242b2ca5e00 Reviewed-by: Alex Blasche --- src/network/bearer/qnetworkconfigmanager_p.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/network/bearer/qnetworkconfigmanager_p.cpp b/src/network/bearer/qnetworkconfigmanager_p.cpp index 49daa22ec8..71e435b771 100644 --- a/src/network/bearer/qnetworkconfigmanager_p.cpp +++ b/src/network/bearer/qnetworkconfigmanager_p.cpp @@ -43,6 +43,10 @@ #include #include +#include +#include + + #ifndef QT_NO_BEARERMANAGEMENT QT_BEGIN_NAMESPACE @@ -375,6 +379,8 @@ void QNetworkConfigurationManagerPrivate::updateConfigurations() updating = false; #ifndef QT_NO_LIBRARY + bool envOK = false; + const int skipGeneric = qgetenv("QT_EXCLUDE_GENERIC_BEARER").toInt(&envOK); QBearerEngine *generic = 0; QFactoryLoader *l = loader(); const PluginKeyMap keyMap = l->keyMap(); @@ -409,8 +415,10 @@ void QNetworkConfigurationManagerPrivate::updateConfigurations() } } - if (generic) - sessionEngines.append(generic); + if (generic) { + if (!envOK || skipGeneric <= 0) + sessionEngines.append(generic); + } #endif // QT_NO_LIBRARY } -- cgit v1.2.3 From 9e81fb4df6809bb2ff909af595ac9e2487760181 Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Mon, 21 Sep 2015 15:52:13 +0200 Subject: Make QWidget::grab work with graphics effects Change 071098b08b12fc1af6341ff6d7ba6713e5de1481 changed QWidget::render to work with all paint devices. Before that change, QWidget::grab would effectively call QWidgetPrivate::render(), since the QWidget::render overload was just a direct call to the private class implementation. This change fixes the regression by calling QWidgetPrivate::render() directly from QWidget::grab(). Task-number: QTBUG-43968 Change-Id: I1aa2fa91c722374612b6cfa76fd0891d168ecac9 Reviewed-by: Lars Knoll Reviewed-by: Friedemann Kleint --- src/widgets/kernel/qwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index b9628cfa1e..2c9cc5c07b 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -5203,7 +5203,7 @@ QPixmap QWidget::grab(const QRect &rectangle) QPixmap res(r.size()); if (!d->isOpaque) res.fill(Qt::transparent); - render(&res, QPoint(), QRegion(r), renderFlags); + d->render(&res, QPoint(), QRegion(r), renderFlags); d->dirtyOpaqueChildren = oldDirtyOpaqueChildren; return res; -- cgit v1.2.3 From eecc351c5d05989c1b0ea3349f76a579b83eb446 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 8 Sep 2015 09:23:34 +0200 Subject: Null out QOpenGLContext::screen upon screen disconnect Returning a dangling pointer is no good. Do what QOffscreenSurface does: just null it out. Task-number: QTBUG-42803 Change-Id: I01a6db9ae8974a1c78157ebc67097c8dac3a6b6e Reviewed-by: Gunnar Sletta --- src/gui/kernel/qopenglcontext.cpp | 16 ++++++++++++++-- src/gui/kernel/qopenglcontext.h | 2 ++ src/gui/kernel/qopenglcontext_p.h | 2 ++ 3 files changed, 18 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index 9e5767658f..85d05959de 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -462,8 +462,7 @@ QPlatformOpenGLContext *QOpenGLContext::shareHandle() const QOpenGLContext::QOpenGLContext(QObject *parent) : QObject(*new QOpenGLContextPrivate(), parent) { - Q_D(QOpenGLContext); - d->screen = QGuiApplication::primaryScreen(); + setScreen(QGuiApplication::primaryScreen()); } /*! @@ -499,9 +498,20 @@ void QOpenGLContext::setShareContext(QOpenGLContext *shareContext) void QOpenGLContext::setScreen(QScreen *screen) { Q_D(QOpenGLContext); + if (d->screen) + disconnect(d->screen, SIGNAL(destroyed(QObject*)), this, SLOT(_q_screenDestroyed(QObject*))); d->screen = screen; if (!d->screen) d->screen = QGuiApplication::primaryScreen(); + if (d->screen) + connect(d->screen, SIGNAL(destroyed(QObject*)), this, SLOT(_q_screenDestroyed(QObject*))); +} + +void QOpenGLContextPrivate::_q_screenDestroyed(QObject *object) +{ + Q_Q(QOpenGLContext); + if (object == static_cast(screen)) + q->setScreen(0); } /*! @@ -1626,4 +1636,6 @@ void QOpenGLMultiGroupSharedResource::cleanup(QOpenGLContextGroup *group, QOpenG m_groups.removeOne(group); } +#include "moc_qopenglcontext.cpp" + QT_END_NAMESPACE diff --git a/src/gui/kernel/qopenglcontext.h b/src/gui/kernel/qopenglcontext.h index 85e7abfa26..841967a545 100644 --- a/src/gui/kernel/qopenglcontext.h +++ b/src/gui/kernel/qopenglcontext.h @@ -241,6 +241,8 @@ private: void setTextureFunctions(QOpenGLTextureHelper* textureFuncs); void destroy(); + + Q_PRIVATE_SLOT(d_func(), void _q_screenDestroyed(QObject *object)) }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h index f9f3ce2c5f..4a746bf12b 100644 --- a/src/gui/kernel/qopenglcontext_p.h +++ b/src/gui/kernel/qopenglcontext_p.h @@ -270,6 +270,8 @@ public: static QHash makeCurrentTracker; static QMutex makeCurrentTrackerMutex; #endif + + void _q_screenDestroyed(QObject *object); }; Q_GUI_EXPORT void qt_gl_set_global_share_context(QOpenGLContext *context); -- cgit v1.2.3 From 863dfb1541f4f0865a6e4ee42dbef159eaa7f2d0 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 15 Sep 2015 17:06:39 +0200 Subject: eglfs: Create input handlers only when screens are available Some code may rely on the primary screen geometry for example. Task-number: QTBUG-47002 Change-Id: I42fc1ccf0c1d91beb5d8e9691ac6ec4e7400e567 Reviewed-by: Louai Al-Khanji --- src/plugins/platforms/eglfs/qeglfsintegration.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp index 5f2cc9abbc..f0946b9b64 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -129,13 +129,14 @@ void QEglFSIntegration::initialize() m_vtHandler.reset(new QFbVtHandler); - if (!m_disableInputHandlers) - createInputHandlers(); - if (qt_egl_device_integration()->usesDefaultScreen()) addScreen(new QEglFSScreen(display())); else qt_egl_device_integration()->screenInit(); + + // Input code may rely on the screens, so do it only after the screen init. + if (!m_disableInputHandlers) + createInputHandlers(); } void QEglFSIntegration::destroy() -- cgit v1.2.3 From a14fadfb640103ecea76c3966cf23668bb7f448b Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Mon, 21 Sep 2015 15:53:49 +0200 Subject: Add getter and setter for qt_qhash_seed In some cases it's not possible to use QT_HASH_SEED, specially when we need to set the environment variable from inside the application, as dynamically loaded libraries or plugins may create static QHash instances. That would set qt_qhash_seed to a value different from -1 and skip the env var value. For those cases, and when we still want to set qt_qhash_seed, we provide a way to enforce its value. Auto-tests accessing qt_qhash_seed directly have been updated accordingly. Usage in qdoc, uic and rcc has been left as is for the time being. Change-Id: I3b35b4fa0223c83b1348a6508641905a2a63266f Reviewed-by: Lars Knoll --- src/corelib/tools/qhash.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++++- src/corelib/tools/qhash.h | 3 +++ 2 files changed, 52 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index 1f3ea36121..b334a697a9 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -290,6 +290,53 @@ static void qt_initialize_qhash_seed() } } +/*! \relates QHash + \since 5.6 + + Returns the current global QHash seed. + + The seed is set in any newly created QHash. See \l{qHash} about how this seed + is being used by QHash. + + \sa qSetGlobalQHashSeed + */ +int qGlobalQHashSeed() +{ + return qt_qhash_seed.load(); +} + +/*! \relates QHash + \since 5.6 + + Sets the global QHash seed. + + Manually setting the global QHash seed value should be done only for testing + and debugging purposes, when deterministic and reproducible behavior on a QHash + is needed. We discourage to do it in production code as it can make your + application susceptible to \l{algorithmic complexity attacks}. + + The seed is set in any newly created QHash. See \l{qHash} about how this seed + is being used by QHash. + + If the environment variable \c QT_HASH_SEED is set, calling this function will + result in a no-op. + + Passing the value -1 will reinitialize the global QHash seed to a random value. + + \sa qGlobalQHashSeed + */ +void qSetGlobalQHashSeed(int newSeed) +{ + if (qEnvironmentVariableIsSet("QT_HASH_SEED")) + return; + if (newSeed == -1) { + int x(qt_create_qhash_seed() & INT_MAX); + qt_qhash_seed.store(x); + } else { + qt_qhash_seed.store(newSeed & INT_MAX); + } +} + /*! \internal @@ -1132,7 +1179,8 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW where you temporarily need deterministic behavior, for example for debugging or regression testing. To disable the randomization, define the environment variable \c QT_HASH_SEED. The contents of that variable, interpreted as a - decimal value, will be used as the seed for qHash(). + decimal value, will be used as the seed for qHash(). Alternatively, you can + call the qSetGlobalQHashSeed() function. \sa QHashIterator, QMutableHashIterator, QMap, QSet */ diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index e367cc0068..8d65a018ae 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -1037,6 +1037,9 @@ Q_INLINE_TEMPLATE int QMultiHash::count(const Key &key, const T &value) return n; } +Q_CORE_EXPORT int qGlobalQHashSeed(); +Q_CORE_EXPORT void qSetGlobalQHashSeed(int newSeed); + Q_DECLARE_ASSOCIATIVE_ITERATOR(Hash) Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(Hash) -- cgit v1.2.3 From b9c5a938c0b578249cac7491592547042f5aa4d2 Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Tue, 3 Mar 2015 18:46:57 +0300 Subject: xcb: Always send dnd events to the proxy window if it exists The standard http://www.newplanetsoftware.com/xdnd/ says: "The only place where the proxy window should be used is when checking XdndAware and in the calls to XSendEvent()". Change-Id: I62e504ba52ec7ec2a941c53a84889bb3eb4b4cc1 Reviewed-by: Lars Knoll --- src/plugins/platforms/xcb/qxcbdrag.cpp | 17 ++++++++++++----- src/plugins/platforms/xcb/qxcbdrag.h | 2 +- 2 files changed, 13 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index a3e646ed7a..de23c59a63 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -444,7 +444,7 @@ void QXcbDrag::move(const QPoint &globalPos) DEBUG() << "sending Xdnd enter source=" << enter.data.data32[0]; if (w) - handleEnter(w, &enter); + handleEnter(w, &enter, current_proxy_target); else if (target) xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&enter); waiting_for_status = false; @@ -665,7 +665,7 @@ static bool checkEmbedded(QWidget* w, const XEvent* xe) #endif -void QXcbDrag::handleEnter(QPlatformWindow *window, const xcb_client_message_event_t *event) +void QXcbDrag::handleEnter(QPlatformWindow *window, const xcb_client_message_event_t *event, xcb_window_t proxy) { Q_UNUSED(window); DEBUG() << "handleEnter" << window; @@ -677,6 +677,9 @@ void QXcbDrag::handleEnter(QPlatformWindow *window, const xcb_client_message_eve return; xdnd_dragsource = event->data.data32[0]; + if (!proxy) + proxy = xdndProxy(connection(), xdnd_dragsource); + current_proxy_target = proxy ? proxy : xdnd_dragsource; if (event->data.data32[1] & 1) { // get the types from XdndTypeList @@ -775,7 +778,7 @@ void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message if (xdnd_dragsource == connection()->clipboard()->owner()) handle_xdnd_status(&response); else - Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xdnd_dragsource, + Q_XCB_CALL(xcb_send_event(xcb_connection(), false, current_proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&response)); } @@ -967,7 +970,7 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e finished.data.data32[0] = currentWindow ? xcb_window(currentWindow.data()) : XCB_NONE; finished.data.data32[1] = response.isAccepted(); // flags finished.data.data32[2] = toXdndAction(response.acceptedAction()); - Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xdnd_dragsource, + Q_XCB_CALL(xcb_send_event(xcb_connection(), false, current_proxy_target, XCB_EVENT_MASK_NO_EVENT, (char *)&finished)); xdnd_dragsource = 0; @@ -1132,7 +1135,11 @@ void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event } } - xcb_send_event(xcb_connection(), false, event->requestor, XCB_EVENT_MASK_NO_EVENT, (const char *)¬ify); + xcb_window_t proxy_target = xdndProxy(connection(), event->requestor); + if (!proxy_target) + proxy_target = event->requestor; + + xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)¬ify); } diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h index 699d402ea6..9584c04238 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.h +++ b/src/plugins/platforms/xcb/qxcbdrag.h @@ -76,7 +76,7 @@ public: void drop(const QPoint &globalPos) Q_DECL_OVERRIDE; void endDrag() Q_DECL_OVERRIDE; - void handleEnter(QPlatformWindow *window, const xcb_client_message_event_t *event); + void handleEnter(QPlatformWindow *window, const xcb_client_message_event_t *event, xcb_window_t proxy = 0); void handlePosition(QPlatformWindow *w, const xcb_client_message_event_t *event); void handleLeave(QPlatformWindow *w, const xcb_client_message_event_t *event); void handleDrop(QPlatformWindow *, const xcb_client_message_event_t *event); -- cgit v1.2.3 From 7edd10e6cc215c419c2cb492ffca997faa520c4c Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Thu, 6 Aug 2015 10:47:15 +0200 Subject: xcb: Compress mouse motion and touch update events The current version of the mouse motion event compression algorithm does not work with certain configurations - situations where we get one XCB_GE_GENERIC event between every XCB_MOTION_NOTIFY event. The new implementation tries to be less fragile. The previous approach checked "is *the next* event the same type as the current event", the new check asks "have we buffered more events of the same type as the current event". We buffer events of the same type only when the main thread is unresponsive. This patch adds event compression for XI_TouchUpdate in addition to the fix for motion even compression. Change-Id: Ie215eb5969e2060e463ebe48e3d3007390a30deb Task-number: QTBUG-40889 Task-number: QTBUG-47069 Reviewed-by: Laszlo Agocs --- src/plugins/platforms/xcb/qxcbconnection.cpp | 220 +++++++++++++++-------- src/plugins/platforms/xcb/qxcbconnection.h | 3 +- src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 119 ++++++------ 3 files changed, 208 insertions(+), 134 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 5fd0df54d8..1cc71b4e1e 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -107,6 +107,24 @@ Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.screen") #define XCB_GE_GENERIC 35 #endif +// Starting from the xcb version 1.9.3 struct xcb_ge_event_t has changed: +// - "pad0" became "extension" +// - "pad1" and "pad" became "pad0" +// New and old version of this struct share the following fields: +typedef struct qt_xcb_ge_event_t { + uint8_t response_type; + uint8_t extension; + uint16_t sequence; + uint32_t length; + uint16_t event_type; +} qt_xcb_ge_event_t; + +static inline bool isXIEvent(xcb_generic_event_t *event, int opCode) +{ + qt_xcb_ge_event_t *e = (qt_xcb_ge_event_t *)event; + return e->extension == opCode; +} + #ifdef XCB_USE_XLIB static const char * const xcbConnectionErrors[] = { "No error", /* Error 0 */ @@ -1109,7 +1127,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) #if defined(XCB_USE_XINPUT2) case XCB_GE_GENERIC: // Here the windowEventListener is invoked from xi2HandleEvent() - if (m_xi2Enabled) + if (m_xi2Enabled && isXIEvent(event, m_xiOpCode)) xi2HandleEvent(reinterpret_cast(event)); break; #endif @@ -1431,6 +1449,105 @@ void *QXcbConnection::createVisualInfoForDefaultVisualId() const #endif +#if defined(XCB_USE_XINPUT2) +// it is safe to cast XI_* events here as long as we are only touching the first 32 bytes, +// after that position event needs memmove, see xi2PrepareXIGenericDeviceEvent +static inline bool isXIType(xcb_generic_event_t *event, int opCode, uint16_t type) +{ + if (!isXIEvent(event, opCode)) + return false; + + xXIGenericDeviceEvent *xiEvent = reinterpret_cast(event); + return xiEvent->evtype == type; +} +#endif +static inline bool isValid(xcb_generic_event_t *event) +{ + return event && (event->response_type & ~0x80); +} + +/*! \internal + + Compresses events of the same type to avoid swamping the event queue. + If event compression is not desired there are several options what developers can do: + + 1) Write responsive applications. We drop events that have been buffered in the event + queue while waiting on unresponsive GUI thread. + 2) Use QAbstractNativeEventFilter to get all events from X connection. This is not optimal + because it requires working with native event types. + 3) Or add public API to Qt for disabling event compression QTBUG-44964 + +*/ +bool QXcbConnection::compressEvent(xcb_generic_event_t *event, int currentIndex, QXcbEventArray *eventqueue) const +{ + uint responseType = event->response_type & ~0x80; + int nextIndex = currentIndex + 1; + + if (responseType == XCB_MOTION_NOTIFY) { + // compress XCB_MOTION_NOTIFY notify events + for (int j = nextIndex; j < eventqueue->size(); ++j) { + xcb_generic_event_t *next = eventqueue->at(j); + if (!isValid(next)) + continue; + if (next->response_type == XCB_MOTION_NOTIFY) + return true; + } + return false; + } +#if defined(XCB_USE_XINPUT2) + // compress XI_* events + if (responseType == XCB_GE_GENERIC) { + if (!m_xi2Enabled) + return false; + + // compress XI_Motion + if (isXIType(event, m_xiOpCode, XI_Motion)) { + for (int j = nextIndex; j < eventqueue->size(); ++j) { + xcb_generic_event_t *next = eventqueue->at(j); + if (!isValid(next)) + continue; + if (isXIType(next, m_xiOpCode, XI_Motion)) + return true; + } + return false; + } +#ifdef XCB_USE_XINPUT22 + // compress XI_TouchUpdate for the same touch point id + if (isXIType(event, m_xiOpCode, XI_TouchUpdate)) { + xXIDeviceEvent *xiDeviceEvent = reinterpret_cast(event); + uint32_t id = xiDeviceEvent->detail % INT_MAX; + for (int j = nextIndex; j < eventqueue->size(); ++j) { + xcb_generic_event_t *next = eventqueue->at(j); + if (!isValid(next)) + continue; + if (isXIType(next, m_xiOpCode, XI_TouchUpdate)) { + xXIDeviceEvent *xiDeviceNextEvent = reinterpret_cast(next); + if (id == xiDeviceNextEvent->detail % INT_MAX) + return true; + } + } + return false; + } +#endif + return false; + } +#endif + if (responseType == XCB_CONFIGURE_NOTIFY) { + // compress multiple configure notify events for the same window + for (int j = nextIndex; j < eventqueue->size(); ++j) { + xcb_generic_event_t *next = eventqueue->at(j); + if (isValid(next) && next->response_type == XCB_CONFIGURE_NOTIFY + && ((xcb_configure_notify_event_t *)next)->event == ((xcb_configure_notify_event_t*)event)->event) + { + return true; + } + } + return false; + } + + return false; +} + void QXcbConnection::processXcbEvents() { int connection_error = xcb_connection_has_error(xcb_connection()); @@ -1441,61 +1558,39 @@ void QXcbConnection::processXcbEvents() QXcbEventArray *eventqueue = m_reader->lock(); - for(int i = 0; i < eventqueue->size(); ++i) { + for (int i = 0; i < eventqueue->size(); ++i) { xcb_generic_event_t *event = eventqueue->at(i); if (!event) continue; QScopedPointer eventGuard(event); (*eventqueue)[i] = 0; - uint response_type = event->response_type & ~0x80; - - if (!response_type) { + if (!(event->response_type & ~0x80)) { handleXcbError((xcb_generic_error_t *)event); - } else { - if (response_type == XCB_MOTION_NOTIFY) { - // compress multiple motion notify events in a row - // to avoid swamping the event queue - xcb_generic_event_t *next = eventqueue->value(i+1, 0); - if (next && (next->response_type & ~0x80) == XCB_MOTION_NOTIFY) - continue; - } + continue; + } - if (response_type == XCB_CONFIGURE_NOTIFY) { - // compress multiple configure notify events for the same window - bool found = false; - for (int j = i; j < eventqueue->size(); ++j) { - xcb_generic_event_t *other = eventqueue->at(j); - if (other && (other->response_type & ~0x80) == XCB_CONFIGURE_NOTIFY - && ((xcb_configure_notify_event_t *)other)->event == ((xcb_configure_notify_event_t *)event)->event) - { - found = true; - break; - } - } - if (found) - continue; - } + if (compressEvent(event, i, eventqueue)) + continue; - bool accepted = false; - if (clipboard()->processIncr()) - clipboard()->incrTransactionPeeker(event, accepted); - if (accepted) - continue; + bool accepted = false; + if (clipboard()->processIncr()) + clipboard()->incrTransactionPeeker(event, accepted); + if (accepted) + continue; - QVector::iterator it = m_peekFuncs.begin(); - while (it != m_peekFuncs.end()) { - // These callbacks return true if the event is what they were - // waiting for, remove them from the list in that case. - if ((*it)(this, event)) - it = m_peekFuncs.erase(it); - else - ++it; - } - m_reader->unlock(); - handleXcbEvent(event); - m_reader->lock(); + QVector::iterator it = m_peekFuncs.begin(); + while (it != m_peekFuncs.end()) { + // These callbacks return true if the event is what they were + // waiting for, remove them from the list in that case. + if ((*it)(this, event)) + it = m_peekFuncs.erase(it); + else + ++it; } + m_reader->unlock(); + handleXcbEvent(event); + m_reader->lock(); } eventqueue->clear(); @@ -2037,34 +2132,13 @@ bool QXcbConnection::xi2GetValuatorValueIfSet(void *event, int valuatorNum, doub return true; } -// Starting from the xcb version 1.9.3 struct xcb_ge_event_t has changed: -// - "pad0" became "extension" -// - "pad1" and "pad" became "pad0" -// New and old version of this struct share the following fields: -// NOTE: API might change again in the next release of xcb in which case this comment will -// need to be updated to reflect the reality. -typedef struct qt_xcb_ge_event_t { - uint8_t response_type; - uint8_t extension; - uint16_t sequence; - uint32_t length; - uint16_t event_type; -} qt_xcb_ge_event_t; - -bool QXcbConnection::xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *ev, int opCode) -{ - qt_xcb_ge_event_t *event = (qt_xcb_ge_event_t *)ev; - // xGenericEvent has "extension" on the second byte, the same is true for xcb_ge_event_t starting from - // the xcb version 1.9.3, prior to that it was called "pad0". - if (event->extension == opCode) { - // xcb event structs contain stuff that wasn't on the wire, the full_sequence field - // adds an extra 4 bytes and generic events cookie data is on the wire right after the standard 32 bytes. - // Move this data back to have the same layout in memory as it was on the wire - // and allow casting, overwriting the full_sequence field. - memmove((char*) event + 32, (char*) event + 36, event->length * 4); - return true; - } - return false; +void QXcbConnection::xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event) +{ + // xcb event structs contain stuff that wasn't on the wire, the full_sequence field + // adds an extra 4 bytes and generic events cookie data is on the wire right after the standard 32 bytes. + // Move this data back to have the same layout in memory as it was on the wire + // and allow casting, overwriting the full_sequence field. + memmove((char*) event + 32, (char*) event + 36, event->length * 4); } #endif // defined(XCB_USE_XINPUT2) diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 4a0348aa0c..2e5a2d7788 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -522,6 +522,7 @@ private: bool checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output); void initializeScreens(); void updateScreens(const xcb_randr_notify_event_t *event); + bool compressEvent(xcb_generic_event_t *event, int currentIndex, QXcbEventArray *eventqueue) const; bool m_xi2Enabled; int m_xi2Minor; @@ -574,7 +575,7 @@ private: QHash m_scrollingDevices; static bool xi2GetValuatorValueIfSet(void *event, int valuatorNum, double *value); - static bool xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event, int opCode); + static void xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event); #endif xcb_connection_t *m_connection; diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 7a5480a8a5..e78ae8fa35 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -459,82 +459,81 @@ static inline qreal fixed1616ToReal(FP1616 val) void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) { - if (xi2PrepareXIGenericDeviceEvent(event, m_xiOpCode)) { - xXIGenericDeviceEvent *xiEvent = reinterpret_cast(event); - int sourceDeviceId = xiEvent->deviceid; // may be the master id - xXIDeviceEvent *xiDeviceEvent = 0; - QXcbWindowEventListener *eventListener = 0; + xi2PrepareXIGenericDeviceEvent(event); + xXIGenericDeviceEvent *xiEvent = reinterpret_cast(event); + int sourceDeviceId = xiEvent->deviceid; // may be the master id + xXIDeviceEvent *xiDeviceEvent = 0; + QXcbWindowEventListener *eventListener = 0; - switch (xiEvent->evtype) { - case XI_ButtonPress: - case XI_ButtonRelease: - case XI_Motion: + switch (xiEvent->evtype) { + case XI_ButtonPress: + case XI_ButtonRelease: + case XI_Motion: #ifdef XCB_USE_XINPUT22 - case XI_TouchBegin: - case XI_TouchUpdate: - case XI_TouchEnd: + case XI_TouchBegin: + case XI_TouchUpdate: + case XI_TouchEnd: #endif - { - xiDeviceEvent = reinterpret_cast(event); - eventListener = windowEventListenerFromId(xiDeviceEvent->event); - if (eventListener) { - long result = 0; - if (eventListener->handleGenericEvent(reinterpret_cast(event), &result)) - return; - } - sourceDeviceId = xiDeviceEvent->sourceid; // use the actual device id instead of the master - break; - } - case XI_HierarchyChanged: - xi2HandleHierachyEvent(xiEvent); - return; - case XI_DeviceChanged: - xi2HandleDeviceChangedEvent(xiEvent); - return; - default: - break; + { + xiDeviceEvent = reinterpret_cast(event); + eventListener = windowEventListenerFromId(xiDeviceEvent->event); + if (eventListener) { + long result = 0; + if (eventListener->handleGenericEvent(reinterpret_cast(event), &result)) + return; } + sourceDeviceId = xiDeviceEvent->sourceid; // use the actual device id instead of the master + break; + } + case XI_HierarchyChanged: + xi2HandleHierachyEvent(xiEvent); + return; + case XI_DeviceChanged: + xi2HandleDeviceChangedEvent(xiEvent); + return; + default: + break; + } #ifndef QT_NO_TABLETEVENT - for (int i = 0; i < m_tabletData.count(); ++i) { - if (m_tabletData.at(i).deviceId == sourceDeviceId) { - if (xi2HandleTabletEvent(xiEvent, &m_tabletData[i], eventListener)) - return; - } + for (int i = 0; i < m_tabletData.count(); ++i) { + if (m_tabletData.at(i).deviceId == sourceDeviceId) { + if (xi2HandleTabletEvent(xiEvent, &m_tabletData[i], eventListener)) + return; } + } #endif // QT_NO_TABLETEVENT #ifdef XCB_USE_XINPUT21 - QHash::iterator device = m_scrollingDevices.find(sourceDeviceId); - if (device != m_scrollingDevices.end()) - xi2HandleScrollEvent(xiEvent, device.value()); + QHash::iterator device = m_scrollingDevices.find(sourceDeviceId); + if (device != m_scrollingDevices.end()) + xi2HandleScrollEvent(xiEvent, device.value()); #endif // XCB_USE_XINPUT21 #ifdef XCB_USE_XINPUT22 - if (xiDeviceEvent) { - switch (xiDeviceEvent->evtype) { - case XI_ButtonPress: - case XI_ButtonRelease: - case XI_Motion: - if (xi2MouseEvents() && eventListener && !(xiDeviceEvent->flags & XIPointerEmulated)) - eventListener->handleXIMouseEvent(event); - break; + if (xiDeviceEvent) { + switch (xiDeviceEvent->evtype) { + case XI_ButtonPress: + case XI_ButtonRelease: + case XI_Motion: + if (xi2MouseEvents() && eventListener && !(xiDeviceEvent->flags & XIPointerEmulated)) + eventListener->handleXIMouseEvent(event); + break; - case XI_TouchBegin: - case XI_TouchUpdate: - case XI_TouchEnd: - if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled())) - qCDebug(lcQpaXInput, "XI2 touch event type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f on window %x", - event->event_type, xiDeviceEvent->sequenceNumber, xiDeviceEvent->detail, - fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y), - fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y),xiDeviceEvent->event); - if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event)) - xi2ProcessTouch(xiDeviceEvent, platformWindow); - break; - } + case XI_TouchBegin: + case XI_TouchUpdate: + case XI_TouchEnd: + if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled())) + qCDebug(lcQpaXInput, "XI2 touch event type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f on window %x", + event->event_type, xiDeviceEvent->sequenceNumber, xiDeviceEvent->detail, + fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y), + fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y),xiDeviceEvent->event); + if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event)) + xi2ProcessTouch(xiDeviceEvent, platformWindow); + break; } -#endif // XCB_USE_XINPUT22 } +#endif // XCB_USE_XINPUT22 } #ifdef XCB_USE_XINPUT22 -- cgit v1.2.3 From d417f81f28039b9165780f937c08ac9b2b92127d Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 22 Sep 2015 09:15:33 +0200 Subject: QAbstractSpinBox::inputMethodQuery(): Consider input method hints set on the spin box. The derived classes (QSpinBox, QDoubleSpinBox, QDateTimeEdit, QTimeEdit) set various input method hints on the spin box in the init() methods of their private classes which did not have any effect since QAbstractSpinBox::inputMethodQuery() was implemented to return the hints of the embedded QLineEdit only. Change it so that hints set on the QAbstractSpinBox are also considered. Change-Id: I76b7c4d3e0869589c110cf3a0b2c3f94201db5d5 Reviewed-by: Andy Shaw Reviewed-by: Liang Qi --- src/widgets/widgets/qabstractspinbox.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp index c96c779d6a..ba4bbe40a8 100644 --- a/src/widgets/widgets/qabstractspinbox.cpp +++ b/src/widgets/widgets/qabstractspinbox.cpp @@ -720,7 +720,16 @@ void QAbstractSpinBox::interpretText() QVariant QAbstractSpinBox::inputMethodQuery(Qt::InputMethodQuery query) const { Q_D(const QAbstractSpinBox); - return d->edit->inputMethodQuery(query); + const QVariant lineEditValue = d->edit->inputMethodQuery(query); + switch (query) { + case Qt::ImHints: + if (const int hints = inputMethodHints()) + return QVariant(hints | lineEditValue.toInt()); + break; + default: + break; + } + return lineEditValue; } /*! -- cgit v1.2.3 From 47ff3dcd087c1239e885439963f02bb8b53b19ed Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 22 Sep 2015 10:57:51 +0200 Subject: Windows: Disable Windows input context when another context is used. Remove QWindowsContext::instance() method and use QPlatformIntegration::inputContext() with proper check instead. Extract static method to disable Windows IME on a window by associating a null context from QWindowsInputContext and use that to disable the IME if another context is in use. Amends change b46fe39d940712c5d401e731e171a7ccfadfe648. Change-Id: Icaad99d390cea5559167602ffbf994660d4717a5 Reviewed-by: Lars Knoll --- src/plugins/platforms/windows/qwindowscontext.cpp | 31 +++++++++++++----- .../platforms/windows/qwindowsinputcontext.cpp | 38 ++++++++++------------ .../platforms/windows/qwindowsinputcontext.h | 5 +-- .../platforms/windows/qwindowskeymapper.cpp | 5 ++- 4 files changed, 48 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 717adcc47f..4ec34c05bd 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -33,6 +33,7 @@ ****************************************************************************/ #include "qwindowscontext.h" +#include "qwindowsintegration.h" #include "qwindowswindow.h" #include "qwindowskeymapper.h" #include "qwindowsguieventdispatcher.h" @@ -907,16 +908,30 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, return true; } } + if (et & QtWindows::InputMethodEventFlag) { + QWindowsInputContext *windowsInputContext = + qobject_cast(QWindowsIntegration::instance()->inputContext()); + // Disable IME assuming this is a special implementation hooking into keyboard input. + // "Real" IME implementations should use a native event filter intercepting IME events. + if (!windowsInputContext) { + QWindowsInputContext::setWindowsImeEnabled(platformWindow, false); + return false; + } + switch (et) { + case QtWindows::InputMethodStartCompositionEvent: + return windowsInputContext->startComposition(hwnd); + case QtWindows::InputMethodCompositionEvent: + return windowsInputContext->composition(hwnd, lParam); + case QtWindows::InputMethodEndCompositionEvent: + return windowsInputContext->endComposition(hwnd); + case QtWindows::InputMethodRequest: + return windowsInputContext->handleIME_Request(wParam, lParam, result); + default: + break; + } + } // InputMethodEventFlag switch (et) { - case QtWindows::InputMethodStartCompositionEvent: - return QWindowsInputContext::instance()->startComposition(hwnd); - case QtWindows::InputMethodCompositionEvent: - return QWindowsInputContext::instance()->composition(hwnd, lParam); - case QtWindows::InputMethodEndCompositionEvent: - return QWindowsInputContext::instance()->endComposition(hwnd); - case QtWindows::InputMethodRequest: - return QWindowsInputContext::instance()->handleIME_Request(wParam, lParam, result); case QtWindows::GestureEvent: #if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER) return platformSessionManager()->isInteractionBlocked() ? true : d->m_mouseHandler.translateGestureEvent(platformWindow->window(), hwnd, et, msg, result); diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index 554a6c8b4c..e016b84bba 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -219,21 +219,24 @@ void QWindowsInputContext::updateEnabled() const bool accepted = inputMethodAccepted(); if (QWindowsContext::verbose > 1) qCDebug(lcQpaInputMethods) << __FUNCTION__ << window << "accepted=" << accepted; - if (accepted) { - // Re-enable IME by associating default context saved on first disabling. - if (platformWindow->testFlag(QWindowsWindow::InputMethodDisabled)) { - ImmAssociateContext(platformWindow->handle(), QWindowsInputContext::m_defaultContext); - platformWindow->clearFlag(QWindowsWindow::InputMethodDisabled); - } - } else { - // Disable IME by associating 0 context. Store context first time. - if (!platformWindow->testFlag(QWindowsWindow::InputMethodDisabled)) { - const HIMC oldImC = ImmAssociateContext(platformWindow->handle(), 0); - platformWindow->setFlag(QWindowsWindow::InputMethodDisabled); - if (!QWindowsInputContext::m_defaultContext && oldImC) - QWindowsInputContext::m_defaultContext = oldImC; - } - } + QWindowsInputContext::setWindowsImeEnabled(platformWindow, accepted); + } +} + +void QWindowsInputContext::setWindowsImeEnabled(QWindowsWindow *platformWindow, bool enabled) +{ + if (!platformWindow || platformWindow->testFlag(QWindowsWindow::InputMethodDisabled) == !enabled) + return; + if (enabled) { + // Re-enable Windows IME by associating default context saved on first disabling. + ImmAssociateContext(platformWindow->handle(), QWindowsInputContext::m_defaultContext); + platformWindow->clearFlag(QWindowsWindow::InputMethodDisabled); + } else { + // Disable Windows IME by associating 0 context. Store context first time. + const HIMC oldImC = ImmAssociateContext(platformWindow->handle(), 0); + platformWindow->setFlag(QWindowsWindow::InputMethodDisabled); + if (!QWindowsInputContext::m_defaultContext && oldImC) + QWindowsInputContext::m_defaultContext = oldImC; } } @@ -306,11 +309,6 @@ void QWindowsInputContext::invokeAction(QInputMethod::Action action, int cursorP ImmReleaseContext(m_compositionContext.hwnd, himc); } -QWindowsInputContext *QWindowsInputContext::instance() -{ - return static_cast(QWindowsIntegration::instance()->inputContext()); -} - static inline QString getCompositionString(HIMC himc, DWORD dwIndex) { enum { bufferSize = 256 }; diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.h b/src/plugins/platforms/windows/qwindowsinputcontext.h index 110986c20c..eb4e3a3faa 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.h +++ b/src/plugins/platforms/windows/qwindowsinputcontext.h @@ -42,6 +42,7 @@ QT_BEGIN_NAMESPACE class QInputMethodEvent; +class QWindowsWindow; class QWindowsInputContext : public QPlatformInputContext { @@ -62,14 +63,14 @@ public: explicit QWindowsInputContext(); ~QWindowsInputContext(); + static void setWindowsImeEnabled(QWindowsWindow *platformWindow, bool enabled); + bool hasCapability(Capability capability) const Q_DECL_OVERRIDE; void reset() Q_DECL_OVERRIDE; void update(Qt::InputMethodQueries) Q_DECL_OVERRIDE; void invokeAction(QInputMethod::Action, int cursorPosition) Q_DECL_OVERRIDE; void setFocusObject(QObject *object) Q_DECL_OVERRIDE; - static QWindowsInputContext *instance(); - bool startComposition(HWND hwnd); bool composition(HWND hwnd, LPARAM lParam); bool endComposition(HWND hwnd); diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index 3636bb7893..f8e2ded228 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -33,6 +33,7 @@ #include "qwindowskeymapper.h" #include "qwindowscontext.h" +#include "qwindowsintegration.h" #include "qwindowswindow.h" #include "qwindowsguieventdispatcher.h" #include "qwindowsinputcontext.h" @@ -1074,7 +1075,9 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms // results, if we map this virtual key-code directly (for eg '?' US layouts). So try // to find the correct key using the current message parameters & keyboard state. if (uch.isNull() && msgType == WM_IME_KEYDOWN) { - if (!QWindowsInputContext::instance()->isComposing()) + const QWindowsInputContext *windowsInputContext = + qobject_cast(QWindowsIntegration::instance()->inputContext()); + if (!(windowsInputContext && windowsInputContext->isComposing())) vk_key = ImmGetVirtualKey((HWND)window->winId()); BYTE keyState[256]; wchar_t newKey[3] = {0}; -- cgit v1.2.3 From 78b2719b04f1177b5af0f52fce98316505f9000b Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 22 Sep 2015 12:21:29 +0200 Subject: Windows: Add checks to usages of QWindow::screen(). Default to primary screen and handle situations where the screen is null consistently. Remove unused QWindowsScreen::screenOf() method. Task-number: QTBUG-48288 Change-Id: I91b3c2331521d9d3be8ac77606ee820cd35ebb0f Reviewed-by: Joerg Bornemann --- src/plugins/platforms/windows/qwindowsmousehandler.cpp | 14 ++++++++++++-- src/plugins/platforms/windows/qwindowsscreen.cpp | 12 ------------ src/plugins/platforms/windows/qwindowsscreen.h | 2 -- src/plugins/platforms/windows/qwindowswindow.cpp | 12 +++++++++--- 4 files changed, 21 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index 4ab861a960..90cb6fe195 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -477,7 +477,12 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND, typedef QList QTouchPointList; Q_ASSERT(m_touchDevice); - const QRect screenGeometry = window->screen()->geometry(); + const QScreen *screen = window->screen(); + if (!screen) + screen = QGuiApplication::primaryScreen(); + if (!screen) + return true; + const QRect screenGeometry = screen->geometry(); const int winTouchPointCount = msg.wParam; QScopedArrayPointer winTouchInputs(new TOUCHINPUT[winTouchPointCount]); @@ -569,7 +574,12 @@ bool QWindowsMouseHandler::translateGestureEvent(QWindow *window, HWND hwnd, if (gi.dwID != GID_DIRECTMANIPULATION) return true; static QPoint lastTouchPos; - const QRect screenGeometry = window->screen()->geometry(); + const QScreen *screen = window->screen(); + if (!screen) + screen = QGuiApplication::primaryScreen(); + if (!screen) + return true; + const QRect screenGeometry = screen->geometry(); QWindowSystemInterface::TouchPoint touchPoint; static QWindowSystemInterface::TouchPoint touchPoint2; touchPoint.id = 0;//gi.dwInstanceID; diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index 391735a035..e6abfb2403 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -276,18 +276,6 @@ QWindow *QWindowsScreen::windowAt(const QPoint &screenPoint, unsigned flags) return result; } -QWindowsScreen *QWindowsScreen::screenOf(const QWindow *w) -{ - if (w) - if (const QScreen *s = w->screen()) - if (QPlatformScreen *pscr = s->handle()) - return static_cast(pscr); - if (const QScreen *ps = QGuiApplication::primaryScreen()) - if (QPlatformScreen *ppscr = ps->handle()) - return static_cast(ppscr); - return 0; -} - qreal QWindowsScreen::pixelDensity() const { const qreal physicalDpi = m_data.geometry.width() / m_data.physicalSizeMM.width() * qreal(25.4); diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h index 67e7ff644b..bc8fbf553b 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.h +++ b/src/plugins/platforms/windows/qwindowsscreen.h @@ -79,8 +79,6 @@ public: explicit QWindowsScreen(const QWindowsScreenData &data); - static QWindowsScreen *screenOf(const QWindow *w = 0); - QRect geometry() const Q_DECL_OVERRIDE { return m_data.geometry; } QRect availableGeometry() const Q_DECL_OVERRIDE { return m_data.availableGeometry; } int depth() const Q_DECL_OVERRIDE { return m_data.depth; } diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 531836015c..abfddcfed6 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1637,8 +1637,12 @@ void QWindowsWindow::setWindowState(Qt::WindowState state) bool QWindowsWindow::isFullScreen_sys() const { const QWindow *w = window(); - return w->isTopLevel() - && geometry_sys() == QHighDpi::toNativePixels(w->screen()->geometry(), w); + if (!w->isTopLevel()) + return false; + const QScreen *screen = w->screen(); + if (!screen) + screen = QGuiApplication::primaryScreen(); + return screen && geometry_sys() == QHighDpi::toNativePixels(screen->geometry(), w); } /*! @@ -1708,7 +1712,9 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState) // Use geometry of QWindow::screen() within creation or the virtual screen the // window is in (QTBUG-31166, QTBUG-30724). const QScreen *screen = window()->screen(); - const QRect r = QHighDpi::toNativePixels(screen->geometry(), window()); + if (!screen) + screen = QGuiApplication::primaryScreen(); + const QRect r = screen ? QHighDpi::toNativePixels(screen->geometry(), window()) : m_savedFrameGeometry; const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE; const bool wasSync = testFlag(SynchronousGeometryChangeEvent); setFlag(SynchronousGeometryChangeEvent); -- cgit v1.2.3 From 24d0f9ef5aa81390fc315fccae616191a88c26d9 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Mon, 21 Sep 2015 15:38:41 +0200 Subject: Silence the _COMPIZ_TOOLKIT_ACTION warning. It is still unclear how to act on those messages. We are already doing this for other Compiz messages -_COMPIZ_DECOR_*. Change-Id: I45f76b5f56ee1b07eb4c7398cc85b5d7bed86c4c Task-number: QTBUG-46954 Reviewed-by: Laszlo Agocs --- src/plugins/platforms/xcb/qxcbconnection.cpp | 3 ++- src/plugins/platforms/xcb/qxcbconnection.h | 1 + src/plugins/platforms/xcb/qxcbwindow.cpp | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 1cc71b4e1e..f65437fd43 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -1835,7 +1835,8 @@ static const char * xcb_atomnames = { "_XSETTINGS_SETTINGS\0" "_COMPIZ_DECOR_PENDING\0" "_COMPIZ_DECOR_REQUEST\0" - "_COMPIZ_DECOR_DELETE_PIXMAP\0" // \0\0 terminates loop. + "_COMPIZ_DECOR_DELETE_PIXMAP\0" + "_COMPIZ_TOOLKIT_ACTION\0" // \0\0 terminates loop. }; QXcbAtom::Atom QXcbConnection::qatom(xcb_atom_t xatom) const diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 2e5a2d7788..6ee32bf600 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -286,6 +286,7 @@ namespace QXcbAtom { _COMPIZ_DECOR_PENDING, _COMPIZ_DECOR_REQUEST, _COMPIZ_DECOR_DELETE_PIXMAP, + _COMPIZ_TOOLKIT_ACTION, NPredefinedAtoms, diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 1ff052f2c0..d751c6d48a 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1971,7 +1971,8 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even // and other messages. } else if (event->type == atom(QXcbAtom::_COMPIZ_DECOR_PENDING) || event->type == atom(QXcbAtom::_COMPIZ_DECOR_REQUEST) - || event->type == atom(QXcbAtom::_COMPIZ_DECOR_DELETE_PIXMAP)) { + || event->type == atom(QXcbAtom::_COMPIZ_DECOR_DELETE_PIXMAP) + || event->type == atom(QXcbAtom::_COMPIZ_TOOLKIT_ACTION)) { //silence the _COMPIZ messages for now } else { qWarning() << "QXcbWindow: Unhandled client message:" << connection()->atomName(event->type); -- cgit v1.2.3 From f5b682d320401dd82c37cee0b2e400966460e37c Mon Sep 17 00:00:00 2001 From: Rafael Roquetto Date: Thu, 3 Sep 2015 16:53:53 +0000 Subject: QGraphicsProxyWidget: forward touch events to QWidget When working with QGraphicsView/QGraphicsScene, touch events are sent to QGraphicsView's viewport() event handler, which then dispatches it to the corresponding QGraphicsItem, if any. In the case of QGraphicsProxyWidget, we need to forward these touch events to the encapsulated QWidget, otherwise it will never receive them (i.e. the event chain for touch events terminates at QGraphicsProxyWidget). This also enables QWidgets associated with QGraphicsProxyWidget to grab gestures. Task-id: QTBUG-45737 Change-Id: Ia441d3576afb6c97376be6f2ff073901e6e928a5 Reviewed-by: Andreas Aardal Hanssen --- src/widgets/graphicsview/qgraphicsproxywidget.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src') diff --git a/src/widgets/graphicsview/qgraphicsproxywidget.cpp b/src/widgets/graphicsview/qgraphicsproxywidget.cpp index 08ea1ea0e3..edb0f4e0ff 100644 --- a/src/widgets/graphicsview/qgraphicsproxywidget.cpp +++ b/src/widgets/graphicsview/qgraphicsproxywidget.cpp @@ -879,6 +879,19 @@ bool QGraphicsProxyWidget::event(QEvent *event) break; } #endif + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: { + if (event->spontaneous()) + qt_sendSpontaneousEvent(d->widget, event); + else + QApplication::sendEvent(d->widget, event); + + if (event->isAccepted()) + return true; + + break; + } default: break; } -- cgit v1.2.3 From 9c71f55ef9575c0168bf8d0b305ec9591a61999d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 27 Aug 2015 18:27:57 +0200 Subject: QFontEngine: Read minimum left and right glyph bearings from 'hhea' table This table has values precomputed based on every single glyph in the font, not just the subset we use as a fallback, which should improve both performance and correctness. The fallback codepath of computing the minimum values based on a subset of the characters in the font is left in, as we still need that for bitmap fonts, and some font tables that have invalid values. Change-Id: I71aac1e09c9f9de80446b023ba15a9e2afe7d226 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/text/qfontengine.cpp | 74 ++++++++++++++++++++++++++++++++------------ 1 file changed, 55 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 102946b545..bef4dc5547 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -581,34 +581,70 @@ qreal QFontEngine::minLeftBearing() const return m_minLeftBearing; } +#define q16Dot16ToFloat(i) ((i) / 65536.0) + +#define kMinLeftSideBearingOffset 12 +#define kMinRightSideBearingOffset 14 + qreal QFontEngine::minRightBearing() const { if (m_minRightBearing == kBearingNotInitialized) { - // To balance performance and correctness we only look at a subset of the - // possible glyphs in the font, based on which characters are more likely - // to have a left or right bearing. - static const ushort characterSubset[] = { - '(', 'C', 'F', 'K', 'V', 'X', 'Y', ']', '_', 'f', 'r', '|', - 127, 205, 645, 884, 922, 1070, 12386 - }; + // Try the 'hhea' font table first, which covers the entire font + QByteArray hheaTable = getSfntTable(MAKE_TAG('h', 'h', 'e', 'a')); + if (hheaTable.size() >= int(kMinRightSideBearingOffset + sizeof(qint16))) { + const uchar *tableData = reinterpret_cast(hheaTable.constData()); + Q_ASSERT(q16Dot16ToFloat(qFromBigEndian(tableData)) == 1.0); + + qint16 minLeftSideBearing = qFromBigEndian(tableData + kMinLeftSideBearingOffset); + qint16 minRightSideBearing = qFromBigEndian(tableData + kMinRightSideBearingOffset); + + // The table data is expressed as FUnits, meaning we have to take the number + // of units per em into account. Since pixelSize already has taken DPI into + // account we can use that directly instead of the point size. + int unitsPerEm = emSquareSize().toInt(); + qreal funitToPixelFactor = fontDef.pixelSize / unitsPerEm; + + // Some fonts on OS X (such as Gurmukhi Sangam MN, Khmer MN, Lao Sangam MN, etc.), have + // invalid values for their NBSPACE left bearing, causing the 'hhea' minimum bearings to + // be way off. We detect this by assuming that the minimum bearsings are within a certain + // range of the em square size. + static const int largestValidBearing = 4 * unitsPerEm; + + if (qAbs(minLeftSideBearing) < largestValidBearing) + m_minLeftBearing = minLeftSideBearing * funitToPixelFactor; + if (qAbs(minRightSideBearing) < largestValidBearing) + m_minRightBearing = minRightSideBearing * funitToPixelFactor; + } - // The font may have minimum bearings larger than 0, so we have to start at the max - m_minLeftBearing = m_minRightBearing = std::numeric_limits::max(); + // Fallback in case of missing 'hhea' table (bitmap fonts e.g.) or broken 'hhea' values + if (m_minLeftBearing == kBearingNotInitialized || m_minRightBearing == kBearingNotInitialized) { - for (uint i = 0; i < (sizeof(characterSubset) / sizeof(ushort)); ++i) { - const glyph_t glyph = glyphIndex(characterSubset[i]); - if (!glyph) - continue; + // To balance performance and correctness we only look at a subset of the + // possible glyphs in the font, based on which characters are more likely + // to have a left or right bearing. + static const ushort characterSubset[] = { + '(', 'C', 'F', 'K', 'V', 'X', 'Y', ']', '_', 'f', 'r', '|', + 127, 205, 645, 884, 922, 1070, 12386 + }; - glyph_metrics_t glyphMetrics = const_cast(this)->boundingBox(glyph); + // The font may have minimum bearings larger than 0, so we have to start at the max + m_minLeftBearing = m_minRightBearing = std::numeric_limits::max(); - // Glyphs with no contours shouldn't contribute to bearings - if (!glyphMetrics.width || !glyphMetrics.height) - continue; + for (uint i = 0; i < (sizeof(characterSubset) / sizeof(ushort)); ++i) { + const glyph_t glyph = glyphIndex(characterSubset[i]); + if (!glyph) + continue; + + glyph_metrics_t glyphMetrics = const_cast(this)->boundingBox(glyph); - m_minLeftBearing = qMin(m_minLeftBearing, glyphMetrics.leftBearing().toReal()); - m_minRightBearing = qMin(m_minRightBearing, glyphMetrics.rightBearing().toReal()); + // Glyphs with no contours shouldn't contribute to bearings + if (!glyphMetrics.width || !glyphMetrics.height) + continue; + + m_minLeftBearing = qMin(m_minLeftBearing, glyphMetrics.leftBearing().toReal()); + m_minRightBearing = qMin(m_minRightBearing, glyphMetrics.rightBearing().toReal()); + } } if (m_minLeftBearing == kBearingNotInitialized || m_minRightBearing == kBearingNotInitialized) -- cgit v1.2.3 From 847d5d1309a4365af7d0f4fa1bff5754b8286e34 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Mon, 17 Aug 2015 09:39:46 +0200 Subject: Implement sessionId/key generation on Windows sessionId and sessionKey generation on Windows was lost in the transition of Qt 4 to Qt 5. During the reimplementation of the QSessionManagement feature, that part has been missed. This patch fixes that. Based on Qt 4 [ChangeLog][QtGui][Windows] Fixed a regression where both sessionId/sessionKey were empty Task-number: QTBUG-47690 Change-Id: I17b5fbee9d0979d292d30b94b3a2cc3107fc54fd Reviewed-by: Friedemann Kleint --- src/gui/kernel/qguiapplication.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src') diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 736580f547..710aa714b7 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -99,6 +99,9 @@ #elif defined(Q_OS_WIN) && !defined(Q_OS_WINCE) # include # include +# if defined(Q_OS_WINPHONE) +# include +# endif #endif // Q_OS_WIN && !Q_OS_WINCE #include @@ -1232,6 +1235,16 @@ void QGuiApplicationPrivate::init() #ifndef QT_NO_SESSIONMANAGER QString session_id; QString session_key; +# if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) + wchar_t guidstr[40]; + GUID guid; + CoCreateGuid(&guid); + StringFromGUID2(guid, guidstr, 40); + session_id = QString::fromWCharArray(guidstr); + CoCreateGuid(&guid); + StringFromGUID2(guid, guidstr, 40); + session_key = QString::fromWCharArray(guidstr); +# endif #endif int j = argc ? 1 : 0; for (int i=1; i Date: Tue, 8 Sep 2015 20:35:33 -0300 Subject: Auto-detect whether 64-bit std::atomic really works The C++ standard says it must, but some badly-configured toolchains seem to be lacking support. In particular, for some 32-bit platforms without native support for them, GCC implements 64-bit atomics via out-of-line functions in libatomic. If that library is missing... well, then std::atomic 64-bit doesn't work and we mustn't try to use it. This was found when trying to compile Qt 5.6 for MIPS 32-bit: Linking library libQt5Core.so.5.6.0 .obj/qsimd.o: In function `std::__atomic_base::load(std::memory_order) const': /opt/poky/1.7/sysroots/mips32r2-poky-linux/usr/include/c++/4.9.1/bits/atomic_base.h:500: undefined reference to `__atomic_load_8' .obj/qsimd.o: In function `std::__atomic_base::store(unsigned long long, std::memory_order)': /opt/poky/1.7/sysroots/mips32r2-poky-linux/usr/include/c++/4.9.1/bits/atomic_base.h:478: undefined reference to `__atomic_store_8' Yocto bug report: https://bugzilla.yoctoproject.org/show_bug.cgi?id=8274 Change-Id: I42e7ef1a481840699a8dffff140224d6614e5c36 Reviewed-by: Oswald Buddenhagen Reviewed-by: Lars Knoll Reviewed-by: Thiago Macieira --- src/corelib/arch/arch.pri | 2 ++ src/corelib/arch/qatomic_cxx11.h | 12 +++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/corelib/arch/arch.pri b/src/corelib/arch/arch.pri index 5c3b0b78c2..99e313daf7 100644 --- a/src/corelib/arch/arch.pri +++ b/src/corelib/arch/arch.pri @@ -11,6 +11,8 @@ HEADERS += \ arch/qatomic_gcc.h \ arch/qatomic_cxx11.h +atomic64-libatomic: LIBS += -latomic + unix { # fallback implementation when no other appropriate qatomic_*.h exists HEADERS += arch/qatomic_unix.h diff --git a/src/corelib/arch/qatomic_cxx11.h b/src/corelib/arch/qatomic_cxx11.h index 0e06ca951a..4136e09ce2 100644 --- a/src/corelib/arch/qatomic_cxx11.h +++ b/src/corelib/arch/qatomic_cxx11.h @@ -78,11 +78,13 @@ template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; }; #define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_ALWAYS_NATIVE #define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT64_IS_SUPPORTED -#define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT64_TEST_AND_SET_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE +#ifndef QT_NO_STD_ATOMIC64 +# define Q_ATOMIC_INT64_IS_SUPPORTED +# define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT64_TEST_AND_SET_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE +#endif template struct QAtomicOps { -- cgit v1.2.3 From af6467c5328492e34f7f346d6a5a32badd963431 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 8 Sep 2015 12:14:45 -0300 Subject: Fix some -Wcast-qual warnings This is happening in code I don't usually test (32-bit, non-ICU, etc.) KeccakF-1600-opt32.c:481:22: error: cast from type 'const unsigned char*' to type 'UINT32* {aka unsigned int*}' casts away qualifiers [-Werror=cast-qual] KeccakF-1600-opt32.c:217:62: note: in definition of macro 'extractLanes' Change-Id: I42e7ef1a481840699a8dffff140209823301a07a Reviewed-by: Lars Knoll Reviewed-by: Richard J. Moore --- src/3rdparty/sha3/KeccakF-1600-opt32.c | 6 +++--- src/corelib/codecs/qbig5codec.cpp | 4 ++-- src/corelib/codecs/qeucjpcodec.cpp | 4 ++-- src/corelib/codecs/qeuckrcodec.cpp | 4 ++-- src/corelib/codecs/qgb18030codec.cpp | 6 +++--- src/corelib/codecs/qjiscodec.cpp | 2 +- src/corelib/codecs/qsjiscodec.cpp | 2 +- src/corelib/io/qurlidna.cpp | 2 +- 8 files changed, 15 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/3rdparty/sha3/KeccakF-1600-opt32.c b/src/3rdparty/sha3/KeccakF-1600-opt32.c index 4e32dca9cb..7d8ae6e19c 100644 --- a/src/3rdparty/sha3/KeccakF-1600-opt32.c +++ b/src/3rdparty/sha3/KeccakF-1600-opt32.c @@ -191,10 +191,10 @@ static UINT64 fromInterleaving(UINT64 x) return x; } -static void setInterleavedWordsInto8bytes(UINT8* dest, UINT32* evenAndOdd) +static void setInterleavedWordsInto8bytes(UINT8* dest, const UINT32* evenAndOdd) { #if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) - ((UINT64*)dest)[0] = fromInterleaving(*(UINT64*)evenAndOdd); + ((UINT64*)dest)[0] = fromInterleaving(*(const UINT64*)evenAndOdd); #else // (PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN) // This can be optimized UINT64 evenAndOddWord = (UINT64)evenAndOdd[0] ^ ((UINT64)evenAndOdd[1] << 32); @@ -214,7 +214,7 @@ static void setInterleavedWordsInto8bytes(UINT8* dest, UINT32* evenAndOdd) { \ unsigned i; \ for(i=0; i<(laneCount); i++) \ - setInterleavedWordsInto8bytes(data+i*8, (UINT32*)state+i*2); \ + setInterleavedWordsInto8bytes(data+i*8, (const UINT32*)state+i*2); \ } #endif // With or without interleaving tables diff --git a/src/corelib/codecs/qbig5codec.cpp b/src/corelib/codecs/qbig5codec.cpp index 6fd87bdfc9..6e6e3143bb 100644 --- a/src/corelib/codecs/qbig5codec.cpp +++ b/src/corelib/codecs/qbig5codec.cpp @@ -1794,7 +1794,7 @@ QByteArray QBig5Codec::convertFromUnicode(const QChar *uc, int len, ConverterSta ++invalid; } } - rstr.resize(cursor - (uchar*)rstr.constData()); + rstr.resize(cursor - (const uchar*)rstr.constData()); if (state) { state->invalidChars += invalid; @@ -1916,7 +1916,7 @@ QByteArray QBig5hkscsCodec::convertFromUnicode(const QChar *uc, int len, Convert ++invalid; } } - rstr.resize(cursor - (uchar*)rstr.constData()); + rstr.resize(cursor - (const uchar*)rstr.constData()); if (state) { state->invalidChars += invalid; diff --git a/src/corelib/codecs/qeucjpcodec.cpp b/src/corelib/codecs/qeucjpcodec.cpp index af218c1ab0..7b9665f1a0 100644 --- a/src/corelib/codecs/qeucjpcodec.cpp +++ b/src/corelib/codecs/qeucjpcodec.cpp @@ -92,7 +92,7 @@ QEucJpCodec::QEucJpCodec() : conv(QJpUnicodeConv::newConverter(QJpUnicodeConv::D */ QEucJpCodec::~QEucJpCodec() { - delete (QJpUnicodeConv*)conv; + delete (const QJpUnicodeConv*)conv; conv = 0; } @@ -139,7 +139,7 @@ QByteArray QEucJpCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt ++invalid; } } - rstr.resize(cursor - (uchar*)rstr.constData()); + rstr.resize(cursor - (const uchar*)rstr.constData()); if (state) { state->invalidChars += invalid; diff --git a/src/corelib/codecs/qeuckrcodec.cpp b/src/corelib/codecs/qeuckrcodec.cpp index 52776efa4d..9ef9e13ebb 100644 --- a/src/corelib/codecs/qeuckrcodec.cpp +++ b/src/corelib/codecs/qeuckrcodec.cpp @@ -108,7 +108,7 @@ QByteArray QEucKrCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt ++invalid; } } - rstr.resize(cursor - (uchar*)rstr.constData()); + rstr.resize(cursor - (const uchar*)rstr.constData()); if (state) { state->invalidChars += invalid; @@ -3421,7 +3421,7 @@ QByteArray QCP949Codec::convertFromUnicode(const QChar *uc, int len, ConverterSt } } } - rstr.resize(cursor - (uchar*)rstr.constData()); + rstr.resize(cursor - (const uchar*)rstr.constData()); if (state) { state->invalidChars += invalid; diff --git a/src/corelib/codecs/qgb18030codec.cpp b/src/corelib/codecs/qgb18030codec.cpp index feb485807f..f498072948 100644 --- a/src/corelib/codecs/qgb18030codec.cpp +++ b/src/corelib/codecs/qgb18030codec.cpp @@ -138,7 +138,7 @@ QByteArray QGb18030Codec::convertFromUnicode(const QChar *uc, int len, Converter ++invalid; } } - rstr.resize(cursor - (uchar*)rstr.constData()); + rstr.resize(cursor - (const uchar*)rstr.constData()); if (state) { state->invalidChars += invalid; @@ -415,7 +415,7 @@ QByteArray QGbkCodec::convertFromUnicode(const QChar *uc, int len, ConverterStat ++invalid; } } - rstr.resize(cursor - (uchar*)rstr.constData()); + rstr.resize(cursor - (const uchar*)rstr.constData()); if (state) { state->invalidChars += invalid; @@ -566,7 +566,7 @@ QByteArray QGb2312Codec::convertFromUnicode(const QChar *uc, int len, ConverterS ++invalid; } } - rstr.resize(cursor - (uchar*)rstr.constData()); + rstr.resize(cursor - (const uchar*)rstr.constData()); if (state) { state->invalidChars += invalid; diff --git a/src/corelib/codecs/qjiscodec.cpp b/src/corelib/codecs/qjiscodec.cpp index 25d8cf0cff..ac1b47a944 100644 --- a/src/corelib/codecs/qjiscodec.cpp +++ b/src/corelib/codecs/qjiscodec.cpp @@ -97,7 +97,7 @@ QJisCodec::QJisCodec() : conv(QJpUnicodeConv::newConverter(QJpUnicodeConv::Defau */ QJisCodec::~QJisCodec() { - delete (QJpUnicodeConv*)conv; + delete (const QJpUnicodeConv*)conv; conv = 0; } diff --git a/src/corelib/codecs/qsjiscodec.cpp b/src/corelib/codecs/qsjiscodec.cpp index 58b91b9d9d..5164d9e4ce 100644 --- a/src/corelib/codecs/qsjiscodec.cpp +++ b/src/corelib/codecs/qsjiscodec.cpp @@ -73,7 +73,7 @@ QSjisCodec::QSjisCodec() : conv(QJpUnicodeConv::newConverter(QJpUnicodeConv::Def */ QSjisCodec::~QSjisCodec() { - delete (QJpUnicodeConv*)conv; + delete (const QJpUnicodeConv*)conv; conv = 0; } diff --git a/src/corelib/io/qurlidna.cpp b/src/corelib/io/qurlidna.cpp index f9a0acf41a..46553d38a5 100644 --- a/src/corelib/io/qurlidna.cpp +++ b/src/corelib/io/qurlidna.cpp @@ -1503,7 +1503,7 @@ static bool isMappedToNothing(uint uc) static bool containsProhibitedOuptut(const QString *str, int from) { const ushort *in = reinterpret_cast(str->begin() + from); - const ushort *end = (ushort *)str->data() + str->size(); + const ushort *end = (const ushort *)str->data() + str->size(); for ( ; in < end; ++in) { uint uc = *in; if (QChar(uc).isHighSurrogate() && in < end - 1) { -- cgit v1.2.3 From e01fa5f1528b3b05d07b0d3acb25008d3a525497 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 10 Mar 2015 14:18:11 -0700 Subject: Mark QHostAddress relocatable Change-Id: Iee8cbc07c4434ce9b560ffff13ca3fb80be56be6 Reviewed-by: Marc Mutz --- src/network/kernel/qhostaddress.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/network/kernel/qhostaddress.h b/src/network/kernel/qhostaddress.h index cea54a2984..9e3ee43d04 100644 --- a/src/network/kernel/qhostaddress.h +++ b/src/network/kernel/qhostaddress.h @@ -132,6 +132,7 @@ public: protected: QScopedPointer d; }; +Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QHostAddress) inline bool operator ==(QHostAddress::SpecialAddress address1, const QHostAddress &address2) { return address2 == address1; } -- cgit v1.2.3 From a6e2213e007c700594cc3293a7b0df3d2ebb051e Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 22 Sep 2015 15:13:40 +0200 Subject: QDateTime: Remove redundant check. Change-Id: I1a027526f24707f9431fe60ad08e41b5b07ffea3 Reviewed-by: Thiago Macieira --- src/corelib/tools/qdatetime.cpp | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index eb4eff32b4..0d7225eea0 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -4792,23 +4792,21 @@ QDataStream &operator<<(QDataStream &out, const QDateTime &dateTime) // From 4.0 to 5.1 (except 5.0) we used QDateTimePrivate::Spec dateAndTime = dateTime.d->getDateTime(); out << dateAndTime; - if (out.version() >= QDataStream::Qt_4_0) { - switch (dateTime.timeSpec()) { - case Qt::UTC: - out << (qint8)QDateTimePrivate::UTC; - break; - case Qt::OffsetFromUTC: - out << (qint8)QDateTimePrivate::OffsetFromUTC; - break; - case Qt::TimeZone: + switch (dateTime.timeSpec()) { + case Qt::UTC: + out << (qint8)QDateTimePrivate::UTC; + break; + case Qt::OffsetFromUTC: + out << (qint8)QDateTimePrivate::OffsetFromUTC; + break; + case Qt::TimeZone: #ifndef QT_BOOTSTRAPPED - out << (qint8)QDateTimePrivate::TimeZone; - break; + out << (qint8)QDateTimePrivate::TimeZone; + break; #endif // QT_BOOTSTRAPPED - case Qt::LocalTime: - out << (qint8)QDateTimePrivate::LocalUnknown; - break; - } + case Qt::LocalTime: + out << (qint8)QDateTimePrivate::LocalUnknown; + break; } } else { // version < QDataStream::Qt_4_0 -- cgit v1.2.3 From a4897c224a7f5e9814a683deb3073896171c276d Mon Sep 17 00:00:00 2001 From: Serge Lysenko Date: Mon, 14 Sep 2015 13:17:05 +0300 Subject: Implement the QImageIOHandler::ImageFormat option for ico files. We need a method to check image format of .ico with QImageReader loader. That is very useful to filter out low resolution icons. Change-Id: I2dfe3aa49cbc1e05836be846ae3da30786b98ff4 Reviewed-by: Friedemann Kleint --- src/plugins/imageformats/ico/qicohandler.cpp | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp index 6d2c06c9c8..b9b51130b5 100644 --- a/src/plugins/imageformats/ico/qicohandler.cpp +++ b/src/plugins/imageformats/ico/qicohandler.cpp @@ -779,11 +779,29 @@ QtIcoHandler::~QtIcoHandler() QVariant QtIcoHandler::option(ImageOption option) const { - if (option == Size) { + if (option == Size || option == ImageFormat) { ICONDIRENTRY iconEntry; if (m_pICOReader->readIconEntry(m_currentIconIndex, &iconEntry)) { - return QSize(iconEntry.bWidth ? iconEntry.bWidth : 256, - iconEntry.bHeight ? iconEntry.bHeight : 256); + switch (option) { + case Size: + return QSize(iconEntry.bWidth ? iconEntry.bWidth : 256, + iconEntry.bHeight ? iconEntry.bHeight : 256); + + case ImageFormat: + switch (iconEntry.wBitCount) { + case 2: + return QImage::Format_Mono; + case 24: + return QImage::Format_RGB32; + case 32: + return QImage::Format_ARGB32; + default: + return QImage::Format_Indexed8; + } + break; + default: + break; + } } } return QVariant(); @@ -791,7 +809,7 @@ QVariant QtIcoHandler::option(ImageOption option) const bool QtIcoHandler::supportsOption(ImageOption option) const { - return option == Size; + return (option == Size || option == ImageFormat); } /*! -- cgit v1.2.3 From 470c8b68df539ca7356cd6b8596f8323ba3ed779 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Fri, 11 Sep 2015 12:54:41 +0200 Subject: QWidgetWindow: call base class close event impl Call the QWindow close event handler when processing close events in QWidgetWindow. Change-Id: I2b8691735962f6a222a30a847bb18cc6c86b55d4 Task-number: QTBUG-43344 Reviewed-by: Laszlo Agocs --- src/widgets/kernel/qwidgetwindow.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 09b4edaf1d..a194993328 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -708,6 +708,7 @@ void QWidgetWindow::handleCloseEvent(QCloseEvent *event) { bool is_closing = m_widget->d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent); event->setAccepted(is_closing); + QWindow::event(event); // Call QWindow QCloseEvent handler. } #ifndef QT_NO_WHEELEVENT -- cgit v1.2.3 From 2e02130e394083f8bc7fa04a8e0b6e0c0ed4e1b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Fri, 11 Sep 2015 13:03:39 +0200 Subject: Close QWidgetWindows by closing the window Close the window instead of closing the widget. This will run the QWidget close implementation followed by the QWindow close implementation. Change-Id: Iaba3cf0359410def858363a02fceaeddb7095aaa Task-number: QTBUG-43344 Reviewed-by: Laszlo Agocs --- src/widgets/kernel/qapplication.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 48c2bf5084..148ed61424 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -1905,7 +1905,7 @@ bool QApplicationPrivate::tryCloseAllWidgetWindows(QWindowList *processedWindows if (!w->isVisible() || w->data->is_closing) break; QWindow *window = w->windowHandle(); - if (!w->close()) // Qt::WA_DeleteOnClose may cause deletion. + if (!window->close()) // Qt::WA_DeleteOnClose may cause deletion. return false; if (window) processedWindows->append(window); @@ -1917,7 +1917,7 @@ bool QApplicationPrivate::tryCloseAllWidgetWindows(QWindowList *processedWindows if (w->isVisible() && w->windowType() != Qt::Desktop && !w->testAttribute(Qt::WA_DontShowOnScreen) && !w->data->is_closing) { QWindow *window = w->windowHandle(); - if (!w->close()) // Qt::WA_DeleteOnClose may cause deletion. + if (!window->close()) // Qt::WA_DeleteOnClose may cause deletion. return false; if (window) processedWindows->append(window); -- cgit v1.2.3 From 867fc30c7c9be51b4b3813d2cc558b5a9df0256d Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 23 Sep 2015 14:38:48 +0200 Subject: windows: Improve error handling with EGL When disabling the graphics adapter, things start failing with context lost and then bad_alloc and bad_access failures when creating contexts/window surfaces. Swap buffers now handles context loss. This makes it possible for Qt Quick to act when the graphics adapter goes away. Similarly, the window surface creation failure EGL_BAD_ACCESS is treated the same way as context loss. Note that this will not really help the main issue, because rendering is not possible without a GPU (reinit attempts will fail either at context creation or window surface creation), but proper logging and context loss reporting improves the situation somewhat. Also unify and prettyify the warning and debug prints. This makes it easier to understand what is going on. Change-Id: Iec3a9b54f1134e78e87eefcf938525283ec9412a Task-number: QTBUG-48095 Reviewed-by: Friedemann Kleint --- .../platforms/windows/qwindowseglcontext.cpp | 43 ++++++++++++++++------ 1 file changed, 31 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp index 06c9985cac..e4ec3f3cf8 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp @@ -350,16 +350,16 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester: { const HDC dc = QWindowsContext::instance()->displayContext(); if (!dc){ - qWarning("%s: No Display", Q_FUNC_INFO); + qWarning("%s: No Display", __FUNCTION__); return 0; } if (!libEGL.init()) { - qWarning("%s: Failed to load and resolve libEGL functions", Q_FUNC_INFO); + qWarning("%s: Failed to load and resolve libEGL functions", __FUNCTION__); return 0; } if (!libGLESv2.init()) { - qWarning("%s: Failed to load and resolve libGLESv2 functions", Q_FUNC_INFO); + qWarning("%s: Failed to load and resolve libGLESv2 functions", __FUNCTION__); return 0; } @@ -396,15 +396,15 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester: if (display == EGL_NO_DISPLAY) display = libEGL.eglGetDisplay((EGLNativeDisplayType)dc); if (!display) { - qWarning("%s: Could not obtain EGL display", Q_FUNC_INFO); + qWarning("%s: Could not obtain EGL display", __FUNCTION__); return 0; } if (!major && !libEGL.eglInitialize(display, &major, &minor)) { int err = libEGL.eglGetError(); - qWarning("%s: Could not initialize EGL display: error 0x%x\n", Q_FUNC_INFO, err); + qWarning("%s: Could not initialize EGL display: error 0x%x", __FUNCTION__, err); if (err == 0x3001) - qWarning("%s: When using ANGLE, check if d3dcompiler_4x.dll is available", Q_FUNC_INFO); + qWarning("%s: When using ANGLE, check if d3dcompiler_4x.dll is available", __FUNCTION__); return 0; } @@ -430,7 +430,7 @@ void *QWindowsEGLStaticContext::createWindowSurface(void *nativeWindow, void *na (EGLNativeWindowType) nativeWindow, 0); if (surface == EGL_NO_SURFACE) { *err = libEGL.eglGetError(); - qWarning("%s: Could not create the EGL window surface: 0x%x\n", Q_FUNC_INFO, *err); + qWarning("%s: Could not create the EGL window surface: 0x%x", __FUNCTION__, *err); } return surface; @@ -533,7 +533,12 @@ QWindowsEGLContext::QWindowsEGLContext(QWindowsEGLStaticContext *staticContext, } if (m_eglContext == EGL_NO_CONTEXT) { - qWarning("QWindowsEGLContext: eglError: %x, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this); + int err = QWindowsEGLStaticContext::libEGL.eglGetError(); + qWarning("QWindowsEGLContext: Failed to create context, eglError: %x, this: %p", err, this); + // ANGLE gives bad alloc when it fails to reset a previously lost D3D device. + // A common cause for this is disabling the graphics adapter used by the app. + if (err == EGL_BAD_ALLOC) + qWarning("QWindowsEGLContext: Graphics device lost. (Did the adapter get disabled?)"); return; } @@ -594,6 +599,12 @@ bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface) if (err == EGL_CONTEXT_LOST) { m_eglContext = EGL_NO_CONTEXT; qCDebug(lcQpaGl) << "Got EGL context lost in createWindowSurface() for context" << this; + } else if (err == EGL_BAD_ACCESS) { + // With ANGLE this means no (D3D) device and can happen when disabling/changing graphics adapters. + qCDebug(lcQpaGl) << "Bad access (missing device?) in createWindowSurface() for context" << this; + // Simulate context loss as the context is useless. + QWindowsEGLStaticContext::libEGL.eglDestroyContext(m_eglDisplay, m_eglContext); + m_eglContext = EGL_NO_CONTEXT; } return false; } @@ -623,7 +634,7 @@ bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface) // Drop the surface. Will recreate on the next makeCurrent. window->invalidateSurface(); } else { - qWarning("QWindowsEGLContext::makeCurrent: eglError: %x, this: %p \n", err, this); + qWarning("%s: Failed to make surface current. eglError: %x, this: %p", __FUNCTION__, err, this); } } @@ -635,7 +646,8 @@ void QWindowsEGLContext::doneCurrent() QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api); bool ok = QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); if (!ok) - qWarning("QWindowsEGLContext::doneCurrent: eglError: %d, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this); + qWarning("%s: Failed to make no context/surface current. eglError: %d, this: %p", __FUNCTION__, + QWindowsEGLStaticContext::libEGL.eglGetError(), this); } void QWindowsEGLContext::swapBuffers(QPlatformSurface *surface) @@ -653,8 +665,15 @@ void QWindowsEGLContext::swapBuffers(QPlatformSurface *surface) } bool ok = QWindowsEGLStaticContext::libEGL.eglSwapBuffers(m_eglDisplay, eglSurface); - if (!ok) - qWarning("QWindowsEGLContext::swapBuffers: eglError: %d, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this); + if (!ok) { + err = QWindowsEGLStaticContext::libEGL.eglGetError(); + if (err == EGL_CONTEXT_LOST) { + m_eglContext = EGL_NO_CONTEXT; + qCDebug(lcQpaGl) << "Got EGL context lost in eglSwapBuffers()"; + } else { + qWarning("%s: Failed to swap buffers. eglError: %d, this: %p", __FUNCTION__, err, this); + } + } } QFunctionPointer QWindowsEGLContext::getProcAddress(const QByteArray &procName) -- cgit v1.2.3 From 0396c7a7d89b0813b997076a52c3f29fb3a0e919 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Thu, 10 Sep 2015 17:34:56 +0200 Subject: Doc: Mention that calling parent class event() is important If you don't deleteLater and more won't work Change-Id: I47cbb24f8e22a7f269a0297410e4163878819f82 Reviewed-by: Thiago Macieira --- .../snippets/code/src_corelib_kernel_qobject.cpp | 27 ++++++++++++++++++++++ src/corelib/kernel/qobject.cpp | 7 ++++++ 2 files changed, 34 insertions(+) (limited to 'src') diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp index 8ff44c9dca..8846437b7c 100644 --- a/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp @@ -486,6 +486,33 @@ QObject::connect(socket, &QTcpSocket::connected, this, [=] () { }, Qt::AutoConnection); //! [51] +//! [52] +class MyClass : public QWidget +{ + Q_OBJECT + +public: + MyClass(QWidget *parent = 0); + ~MyClass(); + + bool event(QEvent* ev) + { + if (ev->type() == QEvent::PolishRequest) { + // overwrite handling of PolishRequest if any + doThings(); + return true; + } else if (ev->type() == QEvent::Show) { + // complement handling of Show if any + doThings2(); + QWidget::event(ev); + return true; + } + // Make sure the rest of events are handled + return QWidget::event(ev); + } +}; +//! [52] + //! [meta data] //: This is a comment for the translator. //= qtn_foo_bar diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 7f95b6a591..d324b6f150 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1219,6 +1219,13 @@ void QObject::setObjectName(const QString &name) The event() function can be reimplemented to customize the behavior of an object. + Make sure you call the parent event class implementation + for all the events you did not handle. + + Example: + + \snippet code/src_corelib_kernel_qobject.cpp 52 + \sa installEventFilter(), timerEvent(), QCoreApplication::sendEvent(), QCoreApplication::postEvent() */ -- cgit v1.2.3 From 29bc68cf169b8cf87d306a1c72e12eb9b6fbfce7 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 9 Jun 2015 17:09:18 -0700 Subject: Add code to perform overflow-checking additions and multiplication Most processors have carry flags which they set on addition overflow, so it's a good idea to access them whenever possible. Most of them also have widening multiply instructions that can be used to detect overflow of the non-widening version. Tested to compile on: Architecture Compiler x86 GCC 4.9, GCC 5*, Clang 3.6*, ICC 16 beta x86-64 GCC 4.9, GCC 5*, Clang 3.6*, ICC 16 beta x86-64 ILP32 GCC 4.9, GCC 5*, Clang 3.6* IA-64 LP64 GCC 4.8 ARMv7-A GCC 4.9, Clang 3.6* AArch64 Clang 3.6* MIPS GCC 4.9, Clang 3.6* MIPS64 GCC 4.9, Clang 3.6* PowerPC GCC 4.9, Clang 3.6* PowerPC 64 GCC 4.9, Clang 3.6* SPARC Clang 3.6* SPARCv9 Clang 3.6* [*] supports the intrinsics If the compiler does not offer a way to detect an overflow, we do it by hand. For unsigned additions, that's easy, since the C++ language specifies the behavior of the overflow. That's also the reason why this code is implemented only for unsigned integers. For the multiplication, if the compiler does not support widening multiplications, we do it with a division instead. This is necessary for GCC < 4.5 and compilers not compatible with GCC or MSVC. Change-Id: I049a653beeb5454c9539ffff13e637de0f1338c1 Reviewed-by: Ulf Hermann Reviewed-by: Alex Trotsenko Reviewed-by: Thiago Macieira --- src/corelib/global/qglobal.h | 3 ++ src/corelib/global/qnumeric_p.h | 117 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) (limited to 'src') diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index f8f306f614..6ee3e37ce6 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -448,6 +448,9 @@ template <> struct QIntegerForSize<1> { typedef quint8 Unsigned; typedef qin template <> struct QIntegerForSize<2> { typedef quint16 Unsigned; typedef qint16 Signed; }; template <> struct QIntegerForSize<4> { typedef quint32 Unsigned; typedef qint32 Signed; }; template <> struct QIntegerForSize<8> { typedef quint64 Unsigned; typedef qint64 Signed; }; +#if defined(Q_CC_GNU) && defined(__SIZEOF_INT128__) +template <> struct QIntegerForSize<16> { __extension__ typedef unsigned __int128 Unsigned; __extension__ typedef __int128 Signed; }; +#endif template struct QIntegerForSizeof: QIntegerForSize { }; typedef QIntegerForSize::Signed qregisterint; typedef QIntegerForSize::Unsigned qregisteruint; diff --git a/src/corelib/global/qnumeric_p.h b/src/corelib/global/qnumeric_p.h index 5fa0a881a3..e5f9d8e13e 100644 --- a/src/corelib/global/qnumeric_p.h +++ b/src/corelib/global/qnumeric_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Intel Corporation. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -47,6 +48,18 @@ #include "QtCore/qglobal.h" +#include + +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +# include +#elif defined(Q_CC_INTEL) +# include // for _addcarry_u +#endif + +#ifndef __has_builtin +# define __has_builtin(x) 0 +#endif + QT_BEGIN_NAMESPACE #if !defined(Q_CC_MIPS) @@ -188,6 +201,110 @@ static inline bool qt_is_finite(float d) } } +// +// Overflow math +// +namespace { +template inline typename QtPrivate::QEnableIf::value, bool>::Type +add_overflow(T v1, T v2, T *r) +{ + // unsigned additions are well-defined + *r = v1 + v2; + return v1 > T(v1 + v2); +} + +template inline typename QtPrivate::QEnableIf::value, bool>::Type +mul_overflow(T v1, T v2, T *r) +{ + // use the next biggest type + // Note: for 64-bit systems where __int128 isn't supported, this will cause an error. + // A fallback is present below. + typedef typename QIntegerForSize::Unsigned Larger; + Larger lr = Larger(v1) * Larger(v2); + *r = T(lr); + return lr > std::numeric_limits::max(); +} + +#if defined(__SIZEOF_INT128__) +# define HAVE_MUL64_OVERFLOW +#endif + +// GCC 5 and Clang have builtins to detect overflows +#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || __has_builtin(__builtin_uadd_overflow) +template <> inline bool add_overflow(unsigned v1, unsigned v2, unsigned *r) +{ return __builtin_uadd_overflow(v1, v2, r); } +#endif +#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || __has_builtin(__builtin_uaddl_overflow) +template <> inline bool add_overflow(unsigned long v1, unsigned long v2, unsigned long *r) +{ return __builtin_uaddl_overflow(v1, v2, r); } +#endif +#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || __has_builtin(__builtin_uaddll_overflow) +template <> inline bool add_overflow(unsigned long long v1, unsigned long long v2, unsigned long long *r) +{ return __builtin_uaddll_overflow(v1, v2, r); } +#endif + +#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || __has_builtin(__builtin_umul_overflow) +template <> inline bool mul_overflow(unsigned v1, unsigned v2, unsigned *r) +{ return __builtin_umul_overflow(v1, v2, r); } +#endif +#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || __has_builtin(__builtin_umull_overflow) +template <> inline bool mul_overflow(unsigned long v1, unsigned long v2, unsigned long *r) +{ return __builtin_umull_overflow(v1, v2, r); } +#endif +#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || __has_builtin(__builtin_umulll_overflow) +template <> inline bool mul_overflow(unsigned long long v1, unsigned long long v2, unsigned long long *r) +{ return __builtin_umulll_overflow(v1, v2, r); } +# define HAVE_MUL64_OVERFLOW +#endif + +#if ((defined(Q_CC_MSVC) && _MSC_VER >= 1800) || defined(Q_CC_INTEL)) && defined(Q_PROCESSOR_X86) +template <> inline bool add_overflow(unsigned v1, unsigned v2, unsigned *r) +{ return _addcarry_u32(0, v1, v2, r); } +# ifdef Q_CC_MSVC // longs are 32-bit +template <> inline bool add_overflow(unsigned long v1, unsigned long v2, unsigned long *r) +{ return _addcarry_u32(0, v1, v2, reinterpret_cast(r)); } +# endif +#endif +#if ((defined(Q_CC_MSVC) && _MSC_VER >= 1800) || defined(Q_CC_INTEL)) && defined(Q_PROCESSOR_X86_64) +template <> inline bool add_overflow(quint64 v1, quint64 v2, quint64 *r) +{ return _addcarry_u64(0, v1, v2, reinterpret_cast(r)); } +# ifndef Q_CC_MSVC // longs are 64-bit +template <> inline bool add_overflow(unsigned long v1, unsigned long v2, unsigned long *r) +{ return _addcarry_u64(0, v1, v2, reinterpret_cast(r)); } +# endif +#endif + +#if defined(Q_CC_MSVC) && (defined(Q_PROCESSOR_X86_64) || defined(Q_PROCESSOR_IA64)) +#pragma intrinsic(_umul128) +template <> inline bool mul_overflow(quint64 v1, quint64 v2, quint64 *r) +{ + // use 128-bit multiplication with the _umul128 intrinsic + // https://msdn.microsoft.com/en-us/library/3dayytw9.aspx + quint64 high; + *r = _umul128(v1, v2, &high); + return high; +} +# define HAVE_MUL64_OVERFLOW +#endif + +#if !defined(HAVE_MUL64_OVERFLOW) && defined(__LP64__) +// no 128-bit multiplication, we need to figure out with a slow division +template <> inline bool mul_overflow(quint64 v1, quint64 v2, quint64 *r) +{ + if (v2 && v1 > std::numeric_limits::max() / v2) + return true; + *r = v1 * v2; + return false; +} +template <> inline bool mul_overflow(unsigned long v1, unsigned long v2, unsigned long *r) +{ + return mul_overflow(v1, v2, reinterpret_cast(r)); +} +#else +# undef HAVE_MUL64_OVERFLOW +#endif +} + QT_END_NAMESPACE #endif // QNUMERIC_P_H -- cgit v1.2.3 From 68ea2f7e9bb2d4ea6182101521325dbfd9b74abb Mon Sep 17 00:00:00 2001 From: Romain Pokrzywka Date: Tue, 22 Sep 2015 11:38:09 -0700 Subject: Synchronize QInputDeviceManager touch device count with QTouchDevice This ensures that the values and signals reported by QInputDeviceManager for touch devices always have corresponding entries in the list returned by QTouchDevice::devices(). It also adds proper QTouchDevice unregistration when the underlying input device gets removed by the evdevtouch QPA plugin. Change-Id: I7bdf2f7435c775d15bddce8ba1e731afdc1d948a Reviewed-by: Friedemann Kleint Reviewed-by: Laszlo Agocs --- src/gui/kernel/qtouchdevice.cpp | 11 +++ src/gui/kernel/qtouchdevice_p.h | 1 + src/gui/kernel/qwindowsysteminterface.cpp | 7 +- src/gui/kernel/qwindowsysteminterface.h | 3 +- .../input/evdevtouch/qevdevtouchhandler.cpp | 83 ++++++++++++++++------ .../input/evdevtouch/qevdevtouchhandler_p.h | 20 +++++- .../input/evdevtouch/qevdevtouchmanager.cpp | 27 +++++-- .../input/evdevtouch/qevdevtouchmanager_p.h | 2 + 8 files changed, 120 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qtouchdevice.cpp b/src/gui/kernel/qtouchdevice.cpp index 9d19fa4b92..266b5308a2 100644 --- a/src/gui/kernel/qtouchdevice.cpp +++ b/src/gui/kernel/qtouchdevice.cpp @@ -237,6 +237,17 @@ void QTouchDevicePrivate::registerDevice(const QTouchDevice *dev) deviceList()->append(dev); } +/*! + \internal + */ +void QTouchDevicePrivate::unregisterDevice(const QTouchDevice *dev) +{ + QMutexLocker lock(&devicesMutex); + bool wasRemoved = deviceList()->removeOne(dev); + if (wasRemoved && deviceList()->isEmpty()) + qRemovePostRoutine(cleanupDevicesList); +} + #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug debug, const QTouchDevice *device) { diff --git a/src/gui/kernel/qtouchdevice_p.h b/src/gui/kernel/qtouchdevice_p.h index 4aff8f2f33..63b83d33ec 100644 --- a/src/gui/kernel/qtouchdevice_p.h +++ b/src/gui/kernel/qtouchdevice_p.h @@ -65,6 +65,7 @@ public: int maxTouchPoints; static void registerDevice(const QTouchDevice *dev); + static void unregisterDevice(const QTouchDevice *dev); static bool isRegistered(const QTouchDevice *dev); }; diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 91a935ad0f..faa1ff8068 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -486,11 +486,16 @@ bool QWindowSystemInterfacePrivate::handleWindowSystemEvent(QWindowSystemInterfa return accepted; } -void QWindowSystemInterface::registerTouchDevice(QTouchDevice *device) +void QWindowSystemInterface::registerTouchDevice(const QTouchDevice *device) { QTouchDevicePrivate::registerDevice(device); } +void QWindowSystemInterface::unregisterTouchDevice(const QTouchDevice *device) +{ + QTouchDevicePrivate::unregisterDevice(device); +} + void QWindowSystemInterface::handleTouchEvent(QWindow *w, QTouchDevice *device, const QList &points, Qt::KeyboardModifiers mods) { diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h index 99589e8aa1..97bd087b53 100644 --- a/src/gui/kernel/qwindowsysteminterface.h +++ b/src/gui/kernel/qwindowsysteminterface.h @@ -127,7 +127,8 @@ public: QVector rawPositions; // in screen coordinates }; - static void registerTouchDevice(QTouchDevice *device); + static void registerTouchDevice(const QTouchDevice *device); + static void unregisterTouchDevice(const QTouchDevice *device); static void handleTouchEvent(QWindow *w, QTouchDevice *device, const QList &points, Qt::KeyboardModifiers mods = Qt::NoModifier); static void handleTouchEvent(QWindow *w, ulong timestamp, QTouchDevice *device, diff --git a/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp b/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp index 5560d910ac..ad348cc083 100644 --- a/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp +++ b/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp @@ -107,9 +107,8 @@ public: int m_currentSlot; int findClosestContact(const QHash &contacts, int x, int y, int *dist); - void reportPoints(); - void registerDevice(); void addTouchPoint(const Contact &contact, Qt::TouchPointStates *combinedStates); + void reportPoints(); int hw_range_x_min; int hw_range_x_max; @@ -119,7 +118,6 @@ public: int hw_pressure_max; QString hw_name; bool m_forceToActiveWindow; - QTouchDevice *m_device; bool m_typeB; QTransform m_rotate; bool m_singleTouch; @@ -132,23 +130,11 @@ QEvdevTouchScreenData::QEvdevTouchScreenData(QEvdevTouchScreenHandler *q_ptr, co hw_range_x_min(0), hw_range_x_max(0), hw_range_y_min(0), hw_range_y_max(0), hw_pressure_min(0), hw_pressure_max(0), - m_device(0), m_typeB(false), m_singleTouch(false) + m_typeB(false), m_singleTouch(false) { m_forceToActiveWindow = args.contains(QLatin1String("force_window")); } -void QEvdevTouchScreenData::registerDevice() -{ - m_device = new QTouchDevice; - m_device->setName(hw_name); - m_device->setType(QTouchDevice::TouchScreen); - m_device->setCapabilities(QTouchDevice::Position | QTouchDevice::Area); - if (hw_pressure_max > hw_pressure_min) - m_device->setCapabilities(m_device->capabilities() | QTouchDevice::Pressure); - - QWindowSystemInterface::registerTouchDevice(m_device); -} - #define LONG_BITS (sizeof(long) << 3) #define NUM_LONGS(bits) (((bits) + LONG_BITS - 1) / LONG_BITS) @@ -160,9 +146,9 @@ static inline bool testBit(long bit, const long *array) #endif QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const QString &spec, QObject *parent) - : QObject(parent), m_notify(0), m_fd(-1), d(0) + : QObject(parent), m_notify(Q_NULLPTR), m_fd(-1), d(Q_NULLPTR), m_device(Q_NULLPTR) #if !defined(QT_NO_MTDEV) - , m_mtdev(0) + , m_mtdev(Q_NULLPTR) #endif { setObjectName(QLatin1String("Evdev Touch Handler")); @@ -299,7 +285,7 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const if (inverty) d->m_rotate *= QTransform::fromTranslate(0.5, 0.5).scale(1.0, -1.0).translate(-0.5, -0.5); - d->registerDevice(); + registerTouchDevice(); } QEvdevTouchScreenHandler::~QEvdevTouchScreenHandler() @@ -315,6 +301,13 @@ QEvdevTouchScreenHandler::~QEvdevTouchScreenHandler() QT_CLOSE(m_fd); delete d; + + unregisterTouchDevice(); +} + +QTouchDevice *QEvdevTouchScreenHandler::touchDevice() const +{ + return m_device; } void QEvdevTouchScreenHandler::readData() @@ -368,15 +361,44 @@ err: qErrnoWarning(errno, "evdevtouch: Could not read from input device"); if (errno == ENODEV) { // device got disconnected -> stop reading delete m_notify; - m_notify = 0; + m_notify = Q_NULLPTR; + QT_CLOSE(m_fd); m_fd = -1; + + unregisterTouchDevice(); } return; } } } +void QEvdevTouchScreenHandler::registerTouchDevice() +{ + if (m_device) + return; + + m_device = new QTouchDevice; + m_device->setName(d->hw_name); + m_device->setType(QTouchDevice::TouchScreen); + m_device->setCapabilities(QTouchDevice::Position | QTouchDevice::Area); + if (d->hw_pressure_max > d->hw_pressure_min) + m_device->setCapabilities(m_device->capabilities() | QTouchDevice::Pressure); + + QWindowSystemInterface::registerTouchDevice(m_device); +} + +void QEvdevTouchScreenHandler::unregisterTouchDevice() +{ + if (!m_device) + return; + + QWindowSystemInterface::unregisterTouchDevice(m_device); + + delete m_device; + m_device = Q_NULLPTR; +} + void QEvdevTouchScreenData::addTouchPoint(const Contact &contact, Qt::TouchPointStates *combinedStates) { QWindowSystemInterface::TouchPoint tp; @@ -639,12 +661,12 @@ void QEvdevTouchScreenData::reportPoints() tp.pressure = (tp.pressure - hw_pressure_min) / qreal(hw_pressure_max - hw_pressure_min); } - QWindowSystemInterface::handleTouchEvent(0, m_device, m_touchPoints); + QWindowSystemInterface::handleTouchEvent(Q_NULLPTR, q->touchDevice(), m_touchPoints); } QEvdevTouchScreenHandlerThread::QEvdevTouchScreenHandlerThread(const QString &device, const QString &spec, QObject *parent) - : QDaemonThread(parent), m_device(device), m_spec(spec), m_handler(0) + : QDaemonThread(parent), m_device(device), m_spec(spec), m_handler(Q_NULLPTR), m_touchDeviceRegistered(false) { start(); } @@ -658,9 +680,24 @@ QEvdevTouchScreenHandlerThread::~QEvdevTouchScreenHandlerThread() void QEvdevTouchScreenHandlerThread::run() { m_handler = new QEvdevTouchScreenHandler(m_device, m_spec); + // Report the registration to the parent thread by invoking the method asynchronously + QMetaObject::invokeMethod(this, "notifyTouchDeviceRegistered", Qt::QueuedConnection); + exec(); + delete m_handler; - m_handler = 0; + m_handler = Q_NULLPTR; +} + +bool QEvdevTouchScreenHandlerThread::isTouchDeviceRegistered() const +{ + return m_touchDeviceRegistered; +} + +void QEvdevTouchScreenHandlerThread::notifyTouchDeviceRegistered() +{ + m_touchDeviceRegistered = true; + emit touchDeviceRegistered(); } diff --git a/src/platformsupport/input/evdevtouch/qevdevtouchhandler_p.h b/src/platformsupport/input/evdevtouch/qevdevtouchhandler_p.h index 8e7dfe59bb..ca9756d5de 100644 --- a/src/platformsupport/input/evdevtouch/qevdevtouchhandler_p.h +++ b/src/platformsupport/input/evdevtouch/qevdevtouchhandler_p.h @@ -66,16 +66,22 @@ class QEvdevTouchScreenHandler : public QObject Q_OBJECT public: - explicit QEvdevTouchScreenHandler(const QString &device, const QString &spec = QString(), QObject *parent = 0); + explicit QEvdevTouchScreenHandler(const QString &device, const QString &spec = QString(), QObject *parent = Q_NULLPTR); ~QEvdevTouchScreenHandler(); + QTouchDevice *touchDevice() const; + private slots: void readData(); private: + void registerTouchDevice(); + void unregisterTouchDevice(); + QSocketNotifier *m_notify; int m_fd; QEvdevTouchScreenData *d; + QTouchDevice *m_device; #if !defined(QT_NO_MTDEV) mtdev *m_mtdev; #endif @@ -83,16 +89,24 @@ private: class QEvdevTouchScreenHandlerThread : public QDaemonThread { + Q_OBJECT public: - explicit QEvdevTouchScreenHandlerThread(const QString &device, const QString &spec, QObject *parent = 0); + explicit QEvdevTouchScreenHandlerThread(const QString &device, const QString &spec, QObject *parent = Q_NULLPTR); ~QEvdevTouchScreenHandlerThread(); void run() Q_DECL_OVERRIDE; - QEvdevTouchScreenHandler *handler() { return m_handler; } + + bool isTouchDeviceRegistered() const; + +signals: + void touchDeviceRegistered(); private: + Q_INVOKABLE void notifyTouchDeviceRegistered(); + QString m_device; QString m_spec; QEvdevTouchScreenHandler *m_handler; + bool m_touchDeviceRegistered; }; QT_END_NAMESPACE diff --git a/src/platformsupport/input/evdevtouch/qevdevtouchmanager.cpp b/src/platformsupport/input/evdevtouch/qevdevtouchmanager.cpp index 98fc83700c..35a685ff21 100644 --- a/src/platformsupport/input/evdevtouch/qevdevtouchmanager.cpp +++ b/src/platformsupport/input/evdevtouch/qevdevtouchmanager.cpp @@ -91,17 +91,17 @@ QEvdevTouchManager::QEvdevTouchManager(const QString &key, const QString &specif QEvdevTouchManager::~QEvdevTouchManager() { qDeleteAll(m_activeDevices); + updateInputDeviceCount(); } void QEvdevTouchManager::addDevice(const QString &deviceNode) { - qCDebug(qLcEvdevTouch) << "Adding device at" << deviceNode; + qCDebug(qLcEvdevTouch) << "evdevtouch: Adding device at" << deviceNode; QEvdevTouchScreenHandlerThread *handler; handler = new QEvdevTouchScreenHandlerThread(deviceNode, m_spec); if (handler) { m_activeDevices.insert(deviceNode, handler); - QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount( - QInputDeviceManager::DeviceTypeTouch, m_activeDevices.count()); + connect(handler, &QEvdevTouchScreenHandlerThread::touchDeviceRegistered, this, &QEvdevTouchManager::updateInputDeviceCount); } else { qWarning("evdevtouch: Failed to open touch device %s", qPrintable(deviceNode)); } @@ -110,13 +110,28 @@ void QEvdevTouchManager::addDevice(const QString &deviceNode) void QEvdevTouchManager::removeDevice(const QString &deviceNode) { if (m_activeDevices.contains(deviceNode)) { - qCDebug(qLcEvdevTouch) << "Removing device at" << deviceNode; + qCDebug(qLcEvdevTouch) << "evdevtouch: Removing device at" << deviceNode; QEvdevTouchScreenHandlerThread *handler = m_activeDevices.value(deviceNode); m_activeDevices.remove(deviceNode); - QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount( - QInputDeviceManager::DeviceTypeTouch, m_activeDevices.count()); delete handler; + + updateInputDeviceCount(); } } +void QEvdevTouchManager::updateInputDeviceCount() +{ + int registeredTouchDevices = 0; + Q_FOREACH (QEvdevTouchScreenHandlerThread *handler, m_activeDevices) { + if (handler->isTouchDeviceRegistered()) + ++registeredTouchDevices; + } + + qCDebug(qLcEvdevTouch) << "evdevtouch: Updating QInputDeviceManager device count:" << registeredTouchDevices << " touch devices," + << m_activeDevices.count() - registeredTouchDevices << "pending handler(s)" ; + + QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount( + QInputDeviceManager::DeviceTypeTouch, registeredTouchDevices); +} + QT_END_NAMESPACE diff --git a/src/platformsupport/input/evdevtouch/qevdevtouchmanager_p.h b/src/platformsupport/input/evdevtouch/qevdevtouchmanager_p.h index bf484fd88b..289c345ac4 100644 --- a/src/platformsupport/input/evdevtouch/qevdevtouchmanager_p.h +++ b/src/platformsupport/input/evdevtouch/qevdevtouchmanager_p.h @@ -65,6 +65,8 @@ private slots: void addDevice(const QString &deviceNode); void removeDevice(const QString &deviceNode); + void updateInputDeviceCount(); + private: QString m_spec; QDeviceDiscovery *m_deviceDiscovery; -- cgit v1.2.3 From d797a04adc5a76146ecff36e17b2a8658b0a5022 Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Tue, 22 Sep 2015 13:36:22 +0200 Subject: Speed up printing when drawing opaque primitives. We only need to merge the rectangles into a region if we are painting a non-opaque a primitive with alpha. Performance measurements QT_print_speed_bug.zip: Excluding patch: 244686 ms Including patch: 5070 ms This is an improvement of 48x (for debug build) Task-number: QTBUG-48334 Change-Id: I03684c6e7d8a5fb039ea6477ed1a860f09e1b08c Reviewed-by: Andy Shaw --- src/printsupport/kernel/qpaintengine_alpha.cpp | 10 +++++++++- src/printsupport/kernel/qpaintengine_alpha_p.h | 6 ++++-- 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/printsupport/kernel/qpaintengine_alpha.cpp b/src/printsupport/kernel/qpaintengine_alpha.cpp index 710691453a..0ae9464b69 100644 --- a/src/printsupport/kernel/qpaintengine_alpha.cpp +++ b/src/printsupport/kernel/qpaintengine_alpha.cpp @@ -376,6 +376,7 @@ QAlphaPaintEnginePrivate::QAlphaPaintEnginePrivate() m_pic(0), m_picengine(0), m_picpainter(0), + m_numberOfCachedRects(0), m_hasalpha(false), m_alphaPen(false), m_alphaBrush(false), @@ -426,7 +427,14 @@ void QAlphaPaintEnginePrivate::addAlphaRect(const QRectF &rect) bool QAlphaPaintEnginePrivate::canSeeTroughBackground(bool somethingInRectHasAlpha, const QRectF &rect) const { - return somethingInRectHasAlpha && m_dirtyrgn.intersects(rect.toAlignedRect()); + if (somethingInRectHasAlpha) { + if (m_dirtyRects.count() != m_numberOfCachedRects) { + m_cachedDirtyRgn.setRects(m_dirtyRects.constData(), m_dirtyRects.count()); + m_numberOfCachedRects = m_dirtyRects.count(); + } + return m_cachedDirtyRgn.intersects(rect.toAlignedRect()); + } + return false; } void QAlphaPaintEnginePrivate::drawAlphaImage(const QRectF &rect) diff --git a/src/printsupport/kernel/qpaintengine_alpha_p.h b/src/printsupport/kernel/qpaintengine_alpha_p.h index 2becad7379..49a9938e56 100644 --- a/src/printsupport/kernel/qpaintengine_alpha_p.h +++ b/src/printsupport/kernel/qpaintengine_alpha_p.h @@ -99,7 +99,9 @@ public: QRegion m_alphargn; QRegion m_cliprgn; - QRegion m_dirtyrgn; + mutable QRegion m_cachedDirtyRgn; + mutable int m_numberOfCachedRects; + QVector m_dirtyRects; bool m_hasalpha; bool m_alphaPen; @@ -115,7 +117,7 @@ public: QPen m_pen; void addAlphaRect(const QRectF &rect); - void addDirtyRect(const QRectF &rect) { m_dirtyrgn |= rect.toAlignedRect(); } + void addDirtyRect(const QRectF &rect) { m_dirtyRects.append(rect.toAlignedRect()); } bool canSeeTroughBackground(bool somethingInRectHasAlpha, const QRectF &rect) const; QRectF addPenWidth(const QPainterPath &path); -- cgit v1.2.3 From c6c930415b354583345b294dc50bb0172ec7db55 Mon Sep 17 00:00:00 2001 From: Serge Lysenko Date: Mon, 14 Sep 2015 14:11:55 +0300 Subject: Fix maximum size of .ico files in ICOReader::write() According to MSDN, a maximum icon size is 256 pixels. http://blogs.msdn.com/b/oldnewthing/archive/2010/10/18/10077133.aspx Change-Id: Id87c89a20c9cba6ef041b49f93f84c5e9c3eb79f Reviewed-by: Friedemann Kleint Reviewed-by: aavit --- src/plugins/imageformats/ico/qicohandler.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp index b9b51130b5..19525397fa 100644 --- a/src/plugins/imageformats/ico/qicohandler.cpp +++ b/src/plugins/imageformats/ico/qicohandler.cpp @@ -659,10 +659,11 @@ bool ICOReader::write(QIODevice *device, const QVector &images) for (int i=0; i 128 || image.height() > 128) + // Scale down the image if it is larger than 256 pixels in either width or height + // because this is a maximum size of image in the ICO file. + if (image.width() > 256 || image.height() > 256) { - image = image.scaled(128, 128, Qt::KeepAspectRatio, Qt::SmoothTransformation); + image = image.scaled(256, 256, Qt::KeepAspectRatio, Qt::SmoothTransformation); } QImage maskImage(image.width(), image.height(), QImage::Format_Mono); image = image.convertToFormat(QImage::Format_ARGB32); @@ -894,9 +895,10 @@ bool QtIcoHandler::jumpToImage(int imageNumber) { if (imageNumber < imageCount()) { m_currentIconIndex = imageNumber; + return true; } - return imageNumber < imageCount(); + return false; } /*! \reimp -- cgit v1.2.3 From c0c49b8df7a78736a4f2c41e3fd1737e94e2729f Mon Sep 17 00:00:00 2001 From: Louai Al-Khanji Date: Mon, 24 Aug 2015 14:13:47 +0300 Subject: Allow vertical resizing of wizard pages with water mark The current behavior has been observed to irritate a lot of users, for instance in the Qt online installer and the Boot2Qt flashing wizard. Change-Id: Icd7b819a0cbc9fd04b86b4777c5b9e829045d6df Reviewed-by: Friedemann Kleint --- src/widgets/dialogs/qwizard.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/widgets/dialogs/qwizard.cpp b/src/widgets/dialogs/qwizard.cpp index 6a1c0eb592..8b9ea95cf3 100644 --- a/src/widgets/dialogs/qwizard.cpp +++ b/src/widgets/dialogs/qwizard.cpp @@ -1347,7 +1347,6 @@ void QWizardPrivate::updateMinMaxSizes(const QWizardLayoutInfo &info) } if (info.watermark && !info.sideWidget) { minimumSize.setHeight(mainLayout->totalSizeHint().height()); - maximumSize.setHeight(mainLayout->totalSizeHint().height()); } if (q->minimumWidth() == minimumWidth) { minimumWidth = minimumSize.width(); -- cgit v1.2.3 From d53695501ac8fd8f99b9b1292dae41002ac6f3f2 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Mon, 21 Sep 2015 14:23:10 +0200 Subject: winphone: Obtain QLocale::uiLanguages properly The methods are supported on Windows Phone since 8.1 so that the simplified Windows Phone code isn't needed any more. Task-number: QTBUG-48140 Change-Id: I21c488fe1a1322e85bbe088fb47e81893fd12d40 Reviewed-by: Maurice Kalinowski Reviewed-by: Andrew Knight --- src/corelib/tools/qlocale_win.cpp | 6 ------ 1 file changed, 6 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qlocale_win.cpp b/src/corelib/tools/qlocale_win.cpp index 1cad9b32e3..4781bab172 100644 --- a/src/corelib/tools/qlocale_win.cpp +++ b/src/corelib/tools/qlocale_win.cpp @@ -51,9 +51,7 @@ #include #include #include -#ifndef Q_OS_WINPHONE #include -#endif #endif // Q_OS_WINRT QT_BEGIN_NAMESPACE @@ -639,7 +637,6 @@ QVariant QSystemLocalePrivate::uiLanguages() return QStringList(QString::fromLatin1(winLangCodeToIsoName(GetUserDefaultUILanguage()))); #else // !Q_OS_WINRT QStringList result; -#ifndef Q_OS_WINPHONE ComPtr appLanguagesStatics; if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Globalization_ApplicationLanguages).Get(), &appLanguagesStatics))) { qWarning("Could not obtain ApplicationLanguagesStatic"); @@ -661,9 +658,6 @@ QVariant QSystemLocalePrivate::uiLanguages() PCWSTR rawString = language.GetRawBuffer(&length); result << QString::fromWCharArray(rawString, length); } -#else // !Q_OS_WINPHONE - result << QString::fromWCharArray(lcName); -#endif // Q_OS_WINPHONE return result; #endif // Q_OS_WINRT -- cgit v1.2.3 From 1ddd33ae662d3fe14e4bd581815a7c3aa42d832e Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Fri, 11 Sep 2015 10:35:09 +0200 Subject: Doc: Fix QDoc warnings for QTextStream qtextstream.cpp:2825: warning: Can't link to 'left()' qtextstream.cpp:2825: warning: Can't link to 'right()' qtextstream.cpp:2797: warning: Can't link to 'right()' qtextstream.cpp:2797: warning: Can't link to 'center()' qtextstream.cpp:2811: warning: Can't link to 'left()' qtextstream.cpp:2811: warning: Can't link to 'center()' Change-Id: I613354ca8137030c9f121cb976fe3bc35e1a415b Reviewed-by: Venugopal Shivashankar --- src/corelib/io/qtextstream.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp index 64038695e3..ca3be9b7e0 100644 --- a/src/corelib/io/qtextstream.cpp +++ b/src/corelib/io/qtextstream.cpp @@ -2800,7 +2800,7 @@ QTextStream &scientific(QTextStream &stream) Calls QTextStream::setFieldAlignment(QTextStream::AlignLeft) on \a stream and returns \a stream. - \sa right(), center(), {QTextStream manipulators} + \sa {QTextStream::}{right()}, {QTextStream::}{center()}, {QTextStream manipulators} */ QTextStream &left(QTextStream &stream) { @@ -2814,7 +2814,7 @@ QTextStream &left(QTextStream &stream) Calls QTextStream::setFieldAlignment(QTextStream::AlignRight) on \a stream and returns \a stream. - \sa left(), center(), {QTextStream manipulators} + \sa {QTextStream::}{left()}, {QTextStream::}{center()}, {QTextStream manipulators} */ QTextStream &right(QTextStream &stream) { @@ -2828,7 +2828,7 @@ QTextStream &right(QTextStream &stream) Calls QTextStream::setFieldAlignment(QTextStream::AlignCenter) on \a stream and returns \a stream. - \sa left(), right(), {QTextStream manipulators} + \sa {QTextStream::}{left()}, {QTextStream::}{right()}, {QTextStream manipulators} */ QTextStream ¢er(QTextStream &stream) { -- cgit v1.2.3 From 7a8da57a637f7a0b94199bb0e19f97a53958a8f0 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Wed, 23 Sep 2015 12:43:41 +0200 Subject: Be more forgiving about arguments to QString::arg(double). The arguments for the width and precision parameters, that is. There's no reason to crash if a user sets e.g. a precision of -2. Task-number: QTBUG-46838 Change-Id: I4afc004a1b8aa1306fd996360b16117b2b643640 Reviewed-by: Thiago Macieira --- src/corelib/tools/qlocale.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index 703341cc36..181daa04e4 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -2742,9 +2742,9 @@ QString QLocaleData::doubleToString(const QChar _zero, const QChar plus, const Q const QChar exponential, const QChar group, const QChar decimal, double d, int precision, DoubleForm form, int width, unsigned flags) { - if (precision == -1) + if (precision < 0) precision = 6; - if (width == -1) + if (width < 0) width = 0; bool negative = false; -- cgit v1.2.3 From 61f2e9a9a72ba4daa96960bf3cb7a605c0b4634c Mon Sep 17 00:00:00 2001 From: Joni Poikelin Date: Wed, 23 Sep 2015 13:42:11 +0300 Subject: Fix QItemSelectionModel deselection range Left and right were swapped which caused invalid selection ranges to be emitted through selectionChanged. Task-number: QTBUG-48402 Change-Id: I18692c2b50c49ab39065f9b360b37b7615227ee9 Reviewed-by: Gabriel de Dietrich --- src/corelib/itemmodels/qitemselectionmodel.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/corelib/itemmodels/qitemselectionmodel.cpp b/src/corelib/itemmodels/qitemselectionmodel.cpp index ba97543c44..51c670f79e 100644 --- a/src/corelib/itemmodels/qitemselectionmodel.cpp +++ b/src/corelib/itemmodels/qitemselectionmodel.cpp @@ -729,11 +729,11 @@ void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &pare deselected.append(*it); it = ranges.erase(it); } else if (start <= it->top() && it->top() <= end) { // Top intersection - deselected.append(QItemSelectionRange(it->topLeft(), model->index(end, it->left(), it->parent()))); + deselected.append(QItemSelectionRange(it->topLeft(), model->index(end, it->right(), it->parent()))); *it = QItemSelectionRange(model->index(end + 1, it->left(), it->parent()), it->bottomRight()); ++it; } else if (start <= it->bottom() && it->bottom() <= end) { // Bottom intersection - deselected.append(QItemSelectionRange(model->index(start, it->right(), it->parent()), it->bottomRight())); + deselected.append(QItemSelectionRange(model->index(start, it->left(), it->parent()), it->bottomRight())); *it = QItemSelectionRange(it->topLeft(), model->index(start - 1, it->right(), it->parent())); ++it; } else if (it->top() < start && end < it->bottom()) { // Middle intersection @@ -741,8 +741,8 @@ void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &pare // and [4, 5] is removed, we need to split [3, 4, 5, 6] into [3], [4, 5] and [6]. // [4, 5] is appended to deselected, and [3] and [6] remain part of the selection // in ranges. - const QItemSelectionRange removedRange(model->index(start, it->right(), it->parent()), - model->index(end, it->left(), it->parent())); + const QItemSelectionRange removedRange(model->index(start, it->left(), it->parent()), + model->index(end, it->right(), it->parent())); deselected.append(removedRange); QItemSelection::split(*it, removedRange, &newParts); it = ranges.erase(it); -- cgit v1.2.3 From 9f779088f434901cd4b81f90fc00e3b34601e071 Mon Sep 17 00:00:00 2001 From: Joni Poikelin Date: Mon, 14 Sep 2015 07:52:05 +0300 Subject: Change indicator arrow direction in Fusion style [ChangeLog][Important Behavior Changes] Arrow indicator now consistent with platform styles Task-number: QTBUG-34611 Change-Id: If55e00a37a22288b2179e03fba299aeebad0ebcf Reviewed-by: J-P Nurmi --- src/widgets/styles/qfusionstyle.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index f87542ffa8..2fc52e9a32 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.cpp @@ -554,11 +554,19 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, QColor arrowColor = header->palette.foreground().color(); QPoint offset = QPoint(0, -1); +#if defined(Q_OS_LINUX) if (header->sortIndicator & QStyleOptionHeader::SortUp) { arrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor); } else if (header->sortIndicator & QStyleOptionHeader::SortDown) { arrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor, 180); } +#else + if (header->sortIndicator & QStyleOptionHeader::SortUp) { + arrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor, 180); + } else if (header->sortIndicator & QStyleOptionHeader::SortDown) { + arrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor); + } +#endif if (!arrow.isNull()) { r.setSize(QSize(arrow.width()/2, arrow.height()/2)); -- cgit v1.2.3 From 73b8cd879cd723fbcce42e63f21cc864d13cb91e Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Wed, 23 Sep 2015 08:45:08 +0200 Subject: QSettings: Special-case serialization of QDateTime. QDateTime values with a UTC offset are not correctly serialized with QDataStream::Qt_4_0. So use a newer QDataStream format for this type and mark it with "@DateTime" instead of "@Variant". Task-number: QTBUG-46551 Change-Id: I211c89e8cd0211c949ec993e6ffd5192d0eebbb3 Reviewed-by: Joerg Bornemann --- src/corelib/io/qsettings.cpp | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index da4a02e4e4..b9993c454e 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -453,14 +453,23 @@ QString QSettingsPrivate::variantToString(const QVariant &v) default: { #ifndef QT_NO_DATASTREAM + QDataStream::Version version; + const char *typeSpec; + if (v.type() == QVariant::DateTime) { + version = QDataStream::Qt_5_6; + typeSpec = "@DateTime("; + } else { + version = QDataStream::Qt_4_0; + typeSpec = "@Variant("; + } QByteArray a; { QDataStream s(&a, QIODevice::WriteOnly); - s.setVersion(QDataStream::Qt_4_0); + s.setVersion(version); s << v; } - result = QLatin1String("@Variant("); + result = QLatin1String(typeSpec); result += QString::fromLatin1(a.constData(), a.size()); result += QLatin1Char(')'); #else @@ -480,11 +489,21 @@ QVariant QSettingsPrivate::stringToVariant(const QString &s) if (s.endsWith(QLatin1Char(')'))) { if (s.startsWith(QLatin1String("@ByteArray("))) { return QVariant(s.toLatin1().mid(11, s.size() - 12)); - } else if (s.startsWith(QLatin1String("@Variant("))) { + } else if (s.startsWith(QLatin1String("@Variant(")) + || s.startsWith(QLatin1String("@DateTime("))) { #ifndef QT_NO_DATASTREAM - QByteArray a(s.toLatin1().mid(9)); + QDataStream::Version version; + int offset; + if (s.at(1) == QLatin1Char('D')) { + version = QDataStream::Qt_5_6; + offset = 10; + } else { + version = QDataStream::Qt_4_0; + offset = 9; + } + QByteArray a(s.toLatin1().mid(offset)); QDataStream stream(&a, QIODevice::ReadOnly); - stream.setVersion(QDataStream::Qt_4_0); + stream.setVersion(version); QVariant result; stream >> result; return result; -- cgit v1.2.3 From 17650467302819e1fd333f0682445d50fc52eb68 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 22 Sep 2015 17:22:22 +0200 Subject: Deliver mouse press and release events on X11 also when dragging We generally assume that for every mouse press we also get a mouse release eventually. The event filter installed by QBasicDrag broke this assumption as it didn't take care of filtering mouse press and mouse release events symmetrically. We cannot immediately pass on the release event as that would mean a release event is generated from a press event (via the blocking drag call), which breaks assumptions in other places. Change-Id: If7e48c7dc0ef5265bed4f9a9366a7606ec875d93 Task-number: QTBUG-46361 Reviewed-by: Friedemann Kleint Reviewed-by: Gatis Paeglis --- src/gui/kernel/qsimpledrag.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qsimpledrag.cpp b/src/gui/kernel/qsimpledrag.cpp index 6e574d82e4..b02f1dd8bd 100644 --- a/src/gui/kernel/qsimpledrag.cpp +++ b/src/gui/kernel/qsimpledrag.cpp @@ -149,7 +149,7 @@ bool QBasicDrag::eventFilter(QObject *o, QEvent *e) { QPoint nativePosition = getNativeMousePos(e, o); move(nativePosition); - return true; // Eat all mouse events + return true; // Eat all mouse move events } case QEvent::MouseButtonRelease: disableEventFilter(); @@ -160,8 +160,8 @@ bool QBasicDrag::eventFilter(QObject *o, QEvent *e) cancel(); } exitDndEventLoop(); - return true; // Eat all mouse events - case QEvent::MouseButtonPress: + QCoreApplication::postEvent(o, new QMouseEvent(*static_cast(e))); + return true; // defer mouse release events until drag event loop has returned case QEvent::MouseButtonDblClick: case QEvent::Wheel: return true; -- cgit v1.2.3 From e87df57abfdd2df821bfed54a5dc3f2380b36486 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Thu, 24 Sep 2015 13:59:48 +0200 Subject: qdoc: Document macro parameters QDoc has the ability to accept parameters for macros but it was never documented. Change-Id: Iaf9a629c906fbe1552717c7444a0fd52b5655a3f Reviewed-by: Martin Smith --- src/tools/qdoc/doc/qdoc-manual-qdocconf.qdoc | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src') diff --git a/src/tools/qdoc/doc/qdoc-manual-qdocconf.qdoc b/src/tools/qdoc/doc/qdoc-manual-qdocconf.qdoc index 01a0e7f578..d490f8549a 100644 --- a/src/tools/qdoc/doc/qdoc-manual-qdocconf.qdoc +++ b/src/tools/qdoc/doc/qdoc-manual-qdocconf.qdoc @@ -734,6 +734,18 @@ command to render a superscript asterisk, but only when generating HTML. + A macro can also take up to seven parameters: + + \badcode + macro.hello = "Hello \1!" + \endcode + + Parameters are passed to macros the same way as to other commands: + + \badcode + \hello World + \endcode + See also \l {alias-variable} {alias}. \target manifestmeta-variable -- cgit v1.2.3 From bf2c9fd2fdff2760f3798fd1584f2da330266c46 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 24 Sep 2015 08:42:06 +0200 Subject: Guard against empty keys in QPlatformInputContextFactory::create(). The code relied on QStringList::split() returning a list consisting of one empty string when passing an enpty string. Add a check to prevent the plugin loader from trying to load in this case. Change-Id: Iadb418d32fdea1d472d6c00726ad039b4afbf409 Reviewed-by: Andy Shaw Reviewed-by: Lars Knoll --- src/gui/kernel/qplatforminputcontextfactory.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qplatforminputcontextfactory.cpp b/src/gui/kernel/qplatforminputcontextfactory.cpp index 9d55b778ce..fedf940dda 100644 --- a/src/gui/kernel/qplatforminputcontextfactory.cpp +++ b/src/gui/kernel/qplatforminputcontextfactory.cpp @@ -65,15 +65,17 @@ QString QPlatformInputContextFactory::requested() QPlatformInputContext *QPlatformInputContextFactory::create(const QString& key) { #if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS) - QStringList paramList = key.split(QLatin1Char(':')); - const QString platform = paramList.takeFirst().toLower(); + if (!key.isEmpty()) { + QStringList paramList = key.split(QLatin1Char(':')); + const QString platform = paramList.takeFirst().toLower(); - QPlatformInputContext *ic = qLoadPlugin1 - (loader(), platform, paramList); - if (ic && ic->isValid()) - return ic; + QPlatformInputContext *ic = qLoadPlugin1 + (loader(), platform, paramList); + if (ic && ic->isValid()) + return ic; - delete ic; + delete ic; + } #endif return 0; } -- cgit v1.2.3 From b46ffbca0cfad41599873d4ca19dc79167c3955f Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 23 Sep 2015 17:40:27 +0200 Subject: Fix up QOpenGLWidget transparency support The glColorMask call was troublesome. In addition, the Qt::WA_TranslucentBackground was misinterpreted and recommended misleadingly in the documentation. The hellogl2 example's --transparent argument was disfunctional in practice. Replace glColorMask with glBlendFuncSeparate. The hellogl2 example and the docs are now corrected wrt enabling semi-transparency in a QOpenGLWidget that is not a top-level (which is the most common case). Task-number: QTBUG-47276 Change-Id: I6f40e732d455f5efcf158649ac9a52ff9f240e85 Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Gunnar Sletta --- src/gui/painting/qplatformbackingstore.cpp | 7 +------ src/widgets/kernel/qopenglwidget.cpp | 22 +++++++++++++--------- 2 files changed, 14 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp index e765a9e402..c86fdebea5 100644 --- a/src/gui/painting/qplatformbackingstore.cpp +++ b/src/gui/painting/qplatformbackingstore.cpp @@ -300,11 +300,7 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i } funcs->glEnable(GL_BLEND); - funcs->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - // Do not write out alpha. We need blending, but only for RGB. The toplevel may have - // alpha enabled in which case blending (writing out < 1.0 alpha values) would lead to - // semi-transparency even when it is not wanted. - funcs->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); + funcs->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); // Backingstore texture with the normal widgets. GLuint textureId = 0; @@ -364,7 +360,6 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i blit(textures, i, window, deviceWindowRect, d_ptr->blitter); } - funcs->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); funcs->glDisable(GL_BLEND); d_ptr->blitter->release(); diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp index b98e8a6a66..92f6066936 100644 --- a/src/widgets/kernel/qopenglwidget.cpp +++ b/src/widgets/kernel/qopenglwidget.cpp @@ -425,7 +425,12 @@ QT_BEGIN_NAMESPACE Note that this does not apply when there are no other widgets underneath and the intention is to have a semi-transparent window. In that case the - traditional approach of setting Qt::WA_TranslucentBackground is sufficient. + traditional approach of setting Qt::WA_TranslucentBackground + on the top-level window is sufficient. Note that if the transparent areas are + only desired in the QOpenGLWidget, then Qt::WA_NoSystemBackground will need + to be turned back to \c false after enabling Qt::WA_TranslucentBackground. + Additionally, requesting an alpha channel for the QOpenGLWidget's context via + setFormat() may be necessary too, depending on the system. QOpenGLWidget supports multiple update behaviors, just like QOpenGLWindow. In preserved mode the rendered content from the previous paintGL() call is @@ -607,7 +612,7 @@ void QOpenGLWidgetPaintDevicePrivate::beginPaint() // with the palette's background color. if (w->autoFillBackground()) { QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); - if (w->testAttribute(Qt::WA_TranslucentBackground)) { + if (w->format().hasAlpha()) { f->glClearColor(0, 0, 0, 0); } else { QColor c = w->palette().brush(w->backgroundRole()).color(); @@ -955,13 +960,12 @@ QOpenGLWidget::UpdateBehavior QOpenGLWidget::updateBehavior() const OpenGL widgets, individual calls to this function can be replaced by one single call to QSurfaceFormat::setDefaultFormat() before creating the first widget. - \note Requesting an alpha buffer via this function, or by setting - Qt::WA_TranslucentBackground, will not lead to the desired results when the intention is - to make other widgets beneath visible. Instead, use Qt::WA_AlwaysStackOnTop to enable - semi-transparent QOpenGLWidget instances with other widgets visible underneath. Keep in - mind however that this breaks the stacking order, so it will no longer be possible to - have other widgets on top of the QOpenGLWidget. When the intention is to have a - semi-transparent top-level window, Qt::WA_TranslucentBackground is sufficient. + \note Requesting an alpha buffer via this function will not lead to the + desired results when the intention is to make other widgets beneath visible. + Instead, use Qt::WA_AlwaysStackOnTop to enable semi-transparent QOpenGLWidget + instances with other widgets visible underneath. Keep in mind however that + this breaks the stacking order, so it will no longer be possible to have + other widgets on top of the QOpenGLWidget. \sa format(), Qt::WA_AlwaysStackOnTop, QSurfaceFormat::setDefaultFormat() */ -- cgit v1.2.3 From 231199798ab3eff88ab87511af1dd87630173adb Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Thu, 24 Sep 2015 10:42:43 +0300 Subject: Build ANGLE dynamically under static builds which have dynamic GL enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-46814 Change-Id: I8108bcd6f8badbb135f593dcf280470e03b11bff Reviewed-by: Jan Arve Sæther Reviewed-by: Laszlo Agocs Reviewed-by: Friedemann Kleint --- src/angle/src/common/common.pri | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/angle/src/common/common.pri b/src/angle/src/common/common.pri index 57f92f1089..8e2333d2ba 100644 --- a/src/angle/src/common/common.pri +++ b/src/angle/src/common/common.pri @@ -48,4 +48,10 @@ winrt|if(msvc:!win32-msvc2005:!win32-msvc2008:!win32-msvc2010) { } } +# static builds should still link ANGLE dynamically when dynamic GL is enabled +static:contains(QT_CONFIG, dynamicgl) { + CONFIG -= static + CONFIG += shared +} + static: DEFINES *= LIBGLESV2_EXPORT_H_ ANGLE_EXPORT= -- cgit v1.2.3 From 3bcb3c64e278ba27d2d9dbeb8ef1eed5aff6b8ae Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 17 Jul 2015 21:29:20 -0700 Subject: Use QTypeInfo::isRelocatable in QVariant Change-Id: Ib306f8f647014b399b87ffff13f1f01c40dc3ef7 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qmetatype.h | 2 +- src/corelib/kernel/qvariant_p.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index b7f01ca5ca..3b8f8e7166 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -1627,7 +1627,7 @@ namespace QtPrivate { template struct QMetaTypeTypeFlags { - enum { Flags = (!QTypeInfo::isStatic ? QMetaType::MovableType : 0) + enum { Flags = (QTypeInfoQuery::isRelocatable ? QMetaType::MovableType : 0) | (QTypeInfo::isComplex ? QMetaType::NeedsConstruction : 0) | (QTypeInfo::isComplex ? QMetaType::NeedsDestruction : 0) | (IsPointerToTypeDerivedFromQObject::Value ? QMetaType::PointerToQObject : 0) diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h index 3b30b1286d..d84d702982 100644 --- a/src/corelib/kernel/qvariant_p.h +++ b/src/corelib/kernel/qvariant_p.h @@ -58,7 +58,7 @@ template struct QVariantIntegrator { static const bool CanUseInternalSpace = sizeof(T) <= sizeof(QVariant::Private::Data) - && ((!QTypeInfo::isStatic) || Q_IS_ENUM(T)); + && ((QTypeInfoQuery::isRelocatable) || Q_IS_ENUM(T)); }; Q_STATIC_ASSERT(QVariantIntegrator::CanUseInternalSpace); Q_STATIC_ASSERT(QVariantIntegrator::CanUseInternalSpace); -- cgit v1.2.3 From c61aaa28df461857b756b9415861cd2d6579c908 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 3 Apr 2015 17:14:11 -0700 Subject: QtDBus: update debugging info (QDBUS_DEBUG=1) Change-Id: I9a75ad8521ae4e5cbbe5ffff13d1a740643ec22e Reviewed-by: Alex Blasche --- src/dbus/qdbusintegrator.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index ec9a88a210..7203f05a9b 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -94,12 +94,7 @@ static inline QDebug operator<<(QDebug dbg, const QDBusConnectionPrivate *conn) << "ptr=" << (const void*)conn << ", name=" << conn->name << ", baseService=" << conn->baseService - << ", thread="; - if (conn->thread() == QThread::currentThread()) - dbg.nospace() << "same thread"; - else - dbg.nospace() << conn->thread(); - dbg.nospace() << ')'; + << ')'; return dbg; } @@ -1017,6 +1012,7 @@ QDBusConnectionPrivate::~QDBusConnectionPrivate() void QDBusConnectionPrivate::closeConnection() { QDBusWriteLocker locker(CloseConnectionAction, this); + qDBusDebug() << this << "Disconnected"; ConnectionMode oldMode = mode; mode = InvalidMode; // prevent reentrancy baseService.clear(); @@ -1036,8 +1032,6 @@ void QDBusConnectionPrivate::closeConnection() } qDeleteAll(pendingCalls); - - qDBusDebug() << this << "Disconnected"; } void QDBusConnectionPrivate::checkThread() @@ -2098,7 +2092,7 @@ void QDBusConnectionPrivate::addSignalHook(const QString &key, const SignalHook if (connection) { if (mode != QDBusConnectionPrivate::PeerMode) { - qDBusDebug("Adding rule: %s", hook.matchRule.constData()); + qDBusDebug() << this << "Adding rule:" << hook.matchRule; q_dbus_bus_add_match(connection, hook.matchRule, NULL); // Successfully connected the signal @@ -2186,7 +2180,7 @@ QDBusConnectionPrivate::removeSignalHookNoLock(SignalHookHash::Iterator it) // we don't care about errors here if (connection && erase) { if (mode != QDBusConnectionPrivate::PeerMode) { - qDBusDebug("Removing rule: %s", hook.matchRule.constData()); + qDBusDebug() << this << "Removing rule:" << hook.matchRule; q_dbus_bus_remove_match(connection, hook.matchRule, NULL); // Successfully disconnected the signal -- cgit v1.2.3 From d427417c744b9035a2d28622a369908c6d347d84 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 24 Sep 2015 09:36:15 -0700 Subject: Print one warning for the new high DPI variables, not four For people with non-empty QT_MESSAGE_PATTERNS, the multiple lines would be unreadable. This is what it showed for me when starting Qt Creator: [1442136.587] qtcreator(82762 82762)(?libQt5Gui.so.5?|QGuiApplicationPrivate::createPlatformIntegration|QGuiApplicationPrivate::createEventDispatcher|QCoreApplication::init|QCoreApplication::QCoreApplication|QGuiApplication::QGuiApplication|QApplication::QApplication|?qtcreator?|?qtcreator?|__libc_start_main): Warning: QT_DEVICE_PIXEL_RATIO is deprecated. Instead use: [1442136.592] qtcreator(82762 82762)(?libQt5Gui.so.5?|QGuiApplicationPrivate::createPlatformIntegration|QGuiApplicationPrivate::createEventDispatcher|QCoreApplication::init|QCoreApplication::QCoreApplication|QGuiApplication::QGuiApplication|QApplication::QApplication|?qtcreator?|?qtcreator?|__libc_start_main): QT_AUTO_SCREEN_SCALE_FACTOR to enable platform plugin controlled per-screen factors. [1442136.592] qtcreator(82762 82762)(?libQt5Gui.so.5?|QGuiApplicationPrivate::createPlatformIntegration|QGuiApplicationPrivate::createEventDispatcher|QCoreApplication::init|QCoreApplication::QCoreApplication|QGuiApplication::QGuiApplication|QApplication::QApplication|?qtcreator?|?qtcreator?|__libc_start_main): QT_SCREEN_SCALE_FACTORS to set per-screen factors. [1442136.593] qtcreator(82762 82762)(?libQt5Gui.so.5?|QGuiApplicationPrivate::createPlatformIntegration|QGuiApplicationPrivate::createEventDispatcher|QCoreApplication::init|QCoreApplication::QCoreApplication|QGuiApplication::QGuiApplication|QApplication::QApplication|?qtcreator?|?qtcreator?|__libc_start_main): QT_SCALE_FACTOR to set the application global scale factor. (and imagine it line-broken in a terminal 140 columns wide) Change-Id: I42e7ef1a481840699a8dffff1406f73dc4d44a41 Reviewed-by: Friedemann Kleint --- src/gui/kernel/qhighdpiscaling.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp index de586ac46c..daba9f94a1 100644 --- a/src/gui/kernel/qhighdpiscaling.cpp +++ b/src/gui/kernel/qhighdpiscaling.cpp @@ -62,10 +62,10 @@ static inline qreal initialScaleFactor() } } else { if (qEnvironmentVariableIsSet(legacyDevicePixelEnvVar)) { - qWarning() << "Warning:" << legacyDevicePixelEnvVar << "is deprecated. Instead use:"; - qWarning() << " " << autoScreenEnvVar << "to enable platform plugin controlled per-screen factors."; - qWarning() << " " << screenFactorsEnvVar << "to set per-screen factors."; - qWarning() << " " << scaleFactorEnvVar << "to set the application global scale factor."; + qWarning() << "Warning:" << legacyDevicePixelEnvVar << "is deprecated. Instead use:" << endl + << " " << autoScreenEnvVar << "to enable platform plugin controlled per-screen factors." << endl + << " " << screenFactorsEnvVar << "to set per-screen factors." << endl + << " " << scaleFactorEnvVar << "to set the application global scale factor."; int dpr = qEnvironmentVariableIntValue(legacyDevicePixelEnvVar); if (dpr > 0) -- cgit v1.2.3 From d0ca16eae15e83a64a1e2a5b5fac53bb2bc919bb Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 21 Sep 2015 12:15:02 +0200 Subject: xcb: get Genius/Waltop tablets working again It was working at some point, but not in 5.5.0. Task-number: QTBUG-48370 Change-Id: I8a0e09d4dfa9ace3d69c10c5f88129958d226a9a Reviewed-by: Laszlo Agocs --- src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index e78ae8fa35..c295a52bae 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -216,6 +216,12 @@ void QXcbConnection::xi2SetupDevices() isTablet = true; tabletData.pointerType = QTabletEvent::Pen; dbgType = QLatin1String("pen"); + } else if (name.contains("waltop") && name.contains("tablet")) { + // other "Genius" tablets + // WALTOP International Corp. Slim Tablet + isTablet = true; + tabletData.pointerType = QTabletEvent::Pen; + dbgType = QLatin1String("pen"); } else { isTablet = false; } -- cgit v1.2.3 From d72da0b4b2ee089156d1bd614523838b1635bbf5 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 4 Sep 2015 13:27:48 +0200 Subject: xcb: fix yet another crash when screens are disconnected Can't assume that m_screens is not an empty list. Task-number: QTBUG-42985 Change-Id: I6f9422638c219123dc898813910d03c7afbd1450 Reviewed-by: Uli Schlachter Reviewed-by: Laszlo Agocs --- src/plugins/platforms/xcb/qxcbconnection.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index f65437fd43..c35b019f7e 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -1300,10 +1300,12 @@ void QXcbConnection::sendConnectionEvent(QXcbAtom::Atom a, uint id) memset(&event, 0, sizeof(event)); const xcb_window_t eventListener = xcb_generate_id(m_connection); + xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup); + xcb_screen_t *screen = it.data; Q_XCB_CALL(xcb_create_window(m_connection, XCB_COPY_FROM_PARENT, - eventListener, m_screens.at(0)->root(), + eventListener, screen->root, 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY, - m_screens.at(0)->screen()->root_visual, 0, 0)); + screen->root_visual, 0, 0)); event.response_type = XCB_CLIENT_MESSAGE; event.format = 32; -- cgit v1.2.3 From c9697677f4bd8e94f5367deab540b90e60e898a5 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 18 Sep 2015 13:49:49 +0200 Subject: Use a power of two division factor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a power of 2 instead of power of 10 means the result of the division can be accurately represented as a floating point instead of being an approximation that could lead to rounding errors. Change-Id: I8910c06113ec6b69c60ff95d59894bfb56133186 Reviewed-by: Morten Johan Sørvig --- src/gui/painting/qpaintdevice.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/painting/qpaintdevice.h b/src/gui/painting/qpaintdevice.h index c360573e78..72a6ca4cb3 100644 --- a/src/gui/painting/qpaintdevice.h +++ b/src/gui/painting/qpaintdevice.h @@ -81,7 +81,7 @@ public: int colorCount() const { return metric(PdmNumColors); } int depth() const { return metric(PdmDepth); } - static inline qreal devicePixelRatioFScale() {return 10000000.0; } + static inline qreal devicePixelRatioFScale() { return 0x10000; } protected: QPaintDevice() Q_DECL_NOEXCEPT; virtual int metric(PaintDeviceMetric metric) const; -- cgit v1.2.3 From 58d9b42c03672a21b4976b69b06915af1352d78a Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 23 Sep 2015 14:08:52 -0700 Subject: Fix deadlock on disconnectNotify() called from ~QObject Normally, disconnectNotify() is called at the end of QObject::disconnect and all the locks have been dropped. That is not the case for the QObject destructor, so we need to deal with the fact that it there may be some locks held. I didn't catch this issue during testing because it depends on the pointer addresses of the object being destroyed and that of the QDBusAbstractInterface sender object, as we use one global, non- recursive mutex pool. For the same reason, this patch is not testable. The fix is simple: we don't need to remove the relay rules immediately. It's ok for them to happen later, since the worst case scenario is that we'll receive a few more signals than we have objects to deliver them to. If that happens, we'll do a little more work than we have to. But in the normal case, the amount of work is the same and we get the benefit of returning more quickly from the destructor. What's more, if the QDBusAbstractInterface object also gets destroyed, the events are deleted and QDBusConnectionPrivate will clean everything up. Task-number: QTBUG-48410 Change-Id: I42e7ef1a481840699a8dffff1406b789ba5217b3 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/dbus/qdbusabstractinterface.cpp | 64 ++++++++++++++++++++++++++++++------- src/dbus/qdbusabstractinterface_p.h | 2 ++ src/dbus/qdbusintegrator.cpp | 2 +- 3 files changed, 55 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/dbus/qdbusabstractinterface.cpp b/src/dbus/qdbusabstractinterface.cpp index 0f097517b7..d63a317612 100644 --- a/src/dbus/qdbusabstractinterface.cpp +++ b/src/dbus/qdbusabstractinterface.cpp @@ -35,6 +35,7 @@ #include "qdbusabstractinterface.h" #include "qdbusabstractinterface_p.h" +#include #include #include "qdbusargument.h" @@ -51,6 +52,29 @@ QT_BEGIN_NAMESPACE +namespace { +// ### Qt6: change to a regular QEvent (customEvent) +// We need to use a QMetaCallEvent here because we can't override customEvent() in +// Qt 5. Since QDBusAbstractInterface is meant to be derived from, the vtables of +// classes in generated code will have a pointer to QObject::customEvent instead +// of to QDBusAbstractInterface::customEvent. +// See solution in Patch Set 1 of this change in the Qt Gerrit servers. +// (https://codereview.qt-project.org/#/c/126384/1) +class DisconnectRelayEvent : public QMetaCallEvent +{ +public: + DisconnectRelayEvent(QObject *sender, const QMetaMethod &m) + : QMetaCallEvent(0, 0, Q_NULLPTR, sender, m.methodIndex()) + {} + + void placeMetaCall(QObject *object) Q_DECL_OVERRIDE + { + QDBusAbstractInterface *iface = static_cast(object); + QDBusAbstractInterfacePrivate::finishDisconnectNotify(iface, signalId()); + } +}; +} + static QDBusError checkIfValid(const QString &service, const QString &path, const QString &interface, bool isDynamic, bool isPeer) { @@ -604,22 +628,38 @@ void QDBusAbstractInterface::disconnectNotify(const QMetaMethod &signal) if (!d->isValid) return; + // disconnection is just resource freeing, so it can be delayed; + // let's do that later, after all the QObject mutexes have been unlocked. + QCoreApplication::postEvent(this, new DisconnectRelayEvent(this, signal)); +} + +/*! + \internal + Continues the disconnect notification from above. +*/ +void QDBusAbstractInterfacePrivate::finishDisconnectNotify(QDBusAbstractInterface *ptr, int signalId) +{ + QDBusAbstractInterfacePrivate *d = ptr->d_func(); QDBusConnectionPrivate *conn = d->connectionPrivate(); - if (conn && signal.isValid() && !isSignalConnected(signal)) - return conn->disconnectRelay(d->service, d->path, d->interface, - this, signal); if (!conn) return; - // wildcard disconnecting, we need to figure out which of our signals are - // no longer connected to anything - const QMetaObject *mo = metaObject(); - int midx = QObject::staticMetaObject.methodCount(); - const int end = mo->methodCount(); - for ( ; midx < end; ++midx) { - QMetaMethod mm = mo->method(midx); - if (mm.methodType() == QMetaMethod::Signal && !isSignalConnected(mm)) - conn->disconnectRelay(d->service, d->path, d->interface, this, mm); + const QMetaObject *mo = ptr->metaObject(); + QMetaMethod signal = signalId >= 0 ? mo->method(signalId) : QMetaMethod(); + if (signal.isValid()) { + if (!ptr->isSignalConnected(signal)) + return conn->disconnectRelay(d->service, d->path, d->interface, + ptr, signal); + } else { + // wildcard disconnecting, we need to figure out which of our signals are + // no longer connected to anything + int midx = QObject::staticMetaObject.methodCount(); + const int end = mo->methodCount(); + for ( ; midx < end; ++midx) { + QMetaMethod mm = mo->method(midx); + if (mm.methodType() == QMetaMethod::Signal && !ptr->isSignalConnected(mm)) + conn->disconnectRelay(d->service, d->path, d->interface, ptr, mm); + } } } diff --git a/src/dbus/qdbusabstractinterface_p.h b/src/dbus/qdbusabstractinterface_p.h index 1ce457d94b..1d9290b746 100644 --- a/src/dbus/qdbusabstractinterface_p.h +++ b/src/dbus/qdbusabstractinterface_p.h @@ -91,6 +91,8 @@ public: { return QDBusConnectionPrivate::d(connection); } void _q_serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner); + + static void finishDisconnectNotify(QDBusAbstractInterface *iface, int signalId); }; QT_END_NAMESPACE diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 7203f05a9b..c465706913 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -2278,7 +2278,7 @@ void QDBusConnectionPrivate::disconnectRelay(const QString &service, sig.append(signal.methodSignature()); if (!prepareHook(hook, key, service, path, interface, QString(), QStringList(), receiver, sig, QDBusAbstractInterface::staticMetaObject.methodCount(), true)) - return; // don't connect + return; // don't disconnect Q_ASSERT(thread() != QThread::currentThread()); emit signalNeedsDisconnecting(key, hook); -- cgit v1.2.3 From f7338d86af68b7979d30f444d68e9a67009a2587 Mon Sep 17 00:00:00 2001 From: Tim Blechmann Date: Mon, 14 Sep 2015 13:56:13 +0200 Subject: tools: StringBuilder - silence clang warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit warning: implicit conversion loses integer precision: 'long' to 'int' [-Wshorten-64-to-32] a.resize(it - a.constData()); ~ ~~~^~~~~~~~~~~~~~~ Change-Id: I8c199d69f2e0d41d1c288d452b9d621b201fa98e Reviewed-by: Jan Arve Sæther Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/tools/qstringbuilder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h index 1dbc005bca..3d41aeee18 100644 --- a/src/corelib/tools/qstringbuilder.h +++ b/src/corelib/tools/qstringbuilder.h @@ -421,7 +421,7 @@ QString &operator+=(QString &a, const QStringBuilder &b) a.reserve(len); QChar *it = a.data() + a.size(); QConcatenable< QStringBuilder >::appendTo(b, it); - a.resize(it - a.constData()); //may be smaller than len if there was conversion from utf8 + a.resize(int(it - a.constData())); //may be smaller than len if there was conversion from utf8 return a; } -- cgit v1.2.3 From 20918435b6255c119148c0d2e482aa65235ed4a1 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Thu, 24 Sep 2015 15:11:16 +0200 Subject: qdoc: Fix write to invalid memory Before deleting the children of an Aggregate, we must clear its internal collections first. This prevents removeChild() (called from ~Node) from accessing already deleted siblings. Change-Id: Ic657b1d57fe4c766daa2bd4b791c3840099de709 Task-number: QTBUG-47751 Reviewed-by: Martin Smith --- src/tools/qdoc/node.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp index eec08e3c72..c1cf076f47 100644 --- a/src/tools/qdoc/node.cpp +++ b/src/tools/qdoc/node.cpp @@ -121,10 +121,12 @@ void Node::removeRelates() if (!relatesTo_) return; - if (relatesTo_->isDocumentNode() && !relatesTo_->parent()) + if (relatesTo_->isDocumentNode() && !relatesTo_->parent()) { delete relatesTo_; - else + relatesTo_ = 0; + } else { relatesTo_->removeRelated(this); + } } /*! @@ -739,8 +741,8 @@ void Node::setLocation(const Location& t) */ Aggregate::~Aggregate() { - deleteChildren(); removeFromRelated(); + deleteChildren(); } /*! @@ -1062,7 +1064,13 @@ void Aggregate::removeFromRelated() */ void Aggregate::deleteChildren() { - NodeList childrenCopy = children_; // `children_` will be changed in ~Node() + NodeList childrenCopy = children_; + // Clear internal collections before deleting child nodes + children_.clear(); + childMap_.clear(); + enumChildren_.clear(); + primaryFunctionMap_.clear(); + secondaryFunctionMap_.clear(); qDeleteAll(childrenCopy); } -- cgit v1.2.3 From 2d6f9b6148a9aa9937c293212e6e7c454cc022a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Fri, 11 Sep 2015 13:05:17 +0200 Subject: Cocoa: Don't send duplicate close events. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the presence of a platform window to detect if the QWindow has already been closed. Change-Id: Ieedf231cc5b805ed6383e55a82ca137087805a4f Task-number: QTBUG-43344 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm index cac50825af..caa8884661 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm +++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm @@ -221,12 +221,8 @@ QT_END_NAMESPACE const QWindowList topLevels = QGuiApplication::topLevelWindows(); for (int i = 0; i < topLevels.size(); ++i) { QWindow *topLevelWindow = topLevels.at(i); - // Widgets have alreay received a CloseEvent from the QApplication - // QCloseEvent handler. (see canQuit above). Prevent running the - // CloseEvent logic twice, call close() directly. - if (topLevelWindow->inherits("QWidgetWindow")) - topLevelWindow->close(); - else + // Already closed windows will not have a platform window, skip those + if (topLevelWindow->handle()) QWindowSystemInterface::handleCloseEvent(topLevelWindow); } QWindowSystemInterface::flushWindowSystemEvents(); -- cgit v1.2.3 From 462f355e4fb16cc7a1838fa2dda0f763eee58c84 Mon Sep 17 00:00:00 2001 From: Wolfgang Bremer Date: Tue, 15 Sep 2015 01:52:06 +0200 Subject: xcb: fix touchscreen input with certain capabilities only Touch screens without the "Abs MT Position X" but "Abs X" capability weren't detected correctly so far. This patch fixes the detection and enables these tochscreens. Change-Id: I32fdb4d56c106717c90904a6632c2838bd55a255 Task-number: QTBUG-48279 Reviewed-by: Laszlo Agocs Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index c295a52bae..8097cce709 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -419,8 +419,10 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id) hasRelativeCoords = true; dev->size.setHeight((vci->max - vci->min) * 1000.0 / vci->resolution); } else if (vci->label == atom(QXcbAtom::AbsX)) { + caps |= QTouchDevice::Position; dev->size.setHeight((vci->max - vci->min) * 1000.0 / vci->resolution); } else if (vci->label == atom(QXcbAtom::AbsY)) { + caps |= QTouchDevice::Position; dev->size.setWidth((vci->max - vci->min) * 1000.0 / vci->resolution); } break; -- cgit v1.2.3