diff options
author | Liang Qi <liang.qi@qt.io> | 2016-05-06 09:07:18 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2016-05-06 15:36:44 +0200 |
commit | dbef41f43ece97d8ac4d6b63f7a36afcb7e7b7f7 (patch) | |
tree | 334ebaec198a7f31d1e3a4639c70fbb8bb116af2 /src | |
parent | 52d30e2850769d589772576e4714a14241c7da6e (diff) | |
parent | f57d8f1341587e6b2aa84b8404aa218432584206 (diff) |
Merge remote-tracking branch 'origin/5.6' into 5.7
Conflicts:
examples/qtestlib/tutorial5/containers.cpp
examples/widgets/tools/tools.pro
src/corelib/io/qprocess.cpp
src/corelib/io/qprocess_unix.cpp
src/corelib/io/qprocess_win.cpp
src/network/kernel/qdnslookup_unix.cpp
src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
src/testlib/qtestcase.cpp
tools/configure/configureapp.cpp
Change-Id: I838ae7f082535a67a4a53aa13a21ba5580758be8
Diffstat (limited to 'src')
41 files changed, 296 insertions, 190 deletions
diff --git a/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentmap.cpp b/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentmap.cpp index 277cbbcc5e..91e76be0db 100644 --- a/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentmap.cpp +++ b/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentmap.cpp @@ -170,7 +170,7 @@ QImage scaledToWith(const QImage &image) //! [13] QList<QImage> images = ...; -QFuture<QImage> thumbnails = QtConcurrent::mapped(images, std::bind(&QImage::scaledToWidth, 100 Qt::SmoothTransformation)); +QFuture<QImage> thumbnails = QtConcurrent::mapped(images, std::bind(&QImage::scaledToWidth, 100, Qt::SmoothTransformation)); //! [13] //! [14] diff --git a/src/corelib/global/qglobalstatic.h b/src/corelib/global/qglobalstatic.h index 4fb3c4f91f..7a6dea9b92 100644 --- a/src/corelib/global/qglobalstatic.h +++ b/src/corelib/global/qglobalstatic.h @@ -116,7 +116,7 @@ QT_BEGIN_NAMESPACE guard.store(QtGlobalStatic::Destroyed); \ } \ } cleanup; \ - guard.store(QtGlobalStatic::Initialized); \ + guard.storeRelease(QtGlobalStatic::Initialized); \ } \ } \ return d; \ diff --git a/src/corelib/io/qfilesystemengine.cpp b/src/corelib/io/qfilesystemengine.cpp index 2dad56befd..fd8f251ccb 100644 --- a/src/corelib/io/qfilesystemengine.cpp +++ b/src/corelib/io/qfilesystemengine.cpp @@ -264,7 +264,7 @@ void QFileSystemMetaData::fillFromStatBuf(const QT_STATBUF &statBuffer) entryFlags |= QFileSystemMetaData::FileType; else if ((statBuffer.st_mode & S_IFMT) == S_IFDIR) entryFlags |= QFileSystemMetaData::DirectoryType; - else + else if ((statBuffer.st_mode & S_IFMT) != S_IFBLK) entryFlags |= QFileSystemMetaData::SequentialType; // Attributes @@ -347,6 +347,18 @@ void QFileSystemMetaData::fillFromDirEnt(const QT_DIRENT &entry) break; case DT_BLK: + knownFlagsMask = QFileSystemMetaData::LinkType + | QFileSystemMetaData::FileType + | QFileSystemMetaData::DirectoryType + | QFileSystemMetaData::BundleType + | QFileSystemMetaData::AliasType + | QFileSystemMetaData::SequentialType + | QFileSystemMetaData::ExistsAttribute; + + entryFlags = QFileSystemMetaData::ExistsAttribute; + + break; + case DT_CHR: case DT_FIFO: case DT_SOCK: diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp index 0829bbc6e8..115b31dd2e 100644 --- a/src/corelib/io/qfilesystemengine_win.cpp +++ b/src/corelib/io/qfilesystemengine_win.cpp @@ -1422,8 +1422,9 @@ bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSyst COPYFILE2_EXTENDED_PARAMETERS copyParams = { sizeof(copyParams), COPY_FILE_FAIL_IF_EXISTS, NULL, NULL, NULL }; - bool ret = ::CopyFile2((const wchar_t*)source.nativeFilePath().utf16(), - (const wchar_t*)target.nativeFilePath().utf16(), ©Params) != 0; + HRESULT hres = ::CopyFile2((const wchar_t*)source.nativeFilePath().utf16(), + (const wchar_t*)target.nativeFilePath().utf16(), ©Params); + bool ret = SUCCEEDED(hres); #endif // Q_OS_WINRT if(!ret) error = QSystemError(::GetLastError(), QSystemError::NativeError); diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 854db31a79..a9d3e0bfe8 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -1103,7 +1103,6 @@ bool QProcessPrivate::_q_canReadStandardError() */ bool QProcessPrivate::_q_canWrite() { - Q_Q(QProcess); if (stdinChannel.notifier) stdinChannel.notifier->setEnabled(false); @@ -1114,31 +1113,13 @@ bool QProcessPrivate::_q_canWrite() return false; } - qint64 written = writeToStdin(writeBuffer.readPointer(), writeBuffer.nextDataBlockSize()); - if (written < 0) { - closeChannel(&stdinChannel); - setErrorAndEmit(QProcess::WriteError); - return false; - } + const bool writeSucceeded = writeToStdin(); -#if defined QPROCESS_DEBUG - qDebug("QProcessPrivate::canWrite(), wrote %d bytes to the process input", int(written)); -#endif - - if (written != 0) { - writeBuffer.free(written); - if (!emittedBytesWritten) { - emittedBytesWritten = true; - emit q->bytesWritten(written); - emittedBytesWritten = false; - } - emit q->channelBytesWritten(0, written); - } if (stdinChannel.notifier && !writeBuffer.isEmpty()) stdinChannel.notifier->setEnabled(true); if (writeBuffer.isEmpty() && stdinChannel.closed) closeWriteChannel(); - return true; + return writeSucceeded; } /*! diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index 1f88c3a043..ae236c8c60 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -379,7 +379,7 @@ public: qint64 bytesAvailableInChannel(const Channel *channel) const; qint64 readFromChannel(const Channel *channel, char *data, qint64 maxlen); - qint64 writeToStdin(const char *data, qint64 maxlen); + bool writeToStdin(); void cleanup(); void setError(QProcess::ProcessError error, const QString &description = QString()); diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index a5b7692fc9..8c5589538d 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -681,21 +681,36 @@ qint64 QProcessPrivate::readFromChannel(const Channel *channel, char *data, qint return bytesRead; } -qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen) +bool QProcessPrivate::writeToStdin() { - qint64 written = qt_safe_write_nosignal(stdinChannel.pipe[1], data, maxlen); + const char *data = writeBuffer.readPointer(); + const qint64 bytesToWrite = writeBuffer.nextDataBlockSize(); + + qint64 written = qt_safe_write_nosignal(stdinChannel.pipe[1], data, bytesToWrite); #if defined QPROCESS_DEBUG - qDebug("QProcessPrivate::writeToStdin(%p \"%s\", %lld) == %lld", - data, qt_prettyDebug(data, maxlen, 16).constData(), maxlen, written); + qDebug("QProcessPrivate::writeToStdin(), write(%p \"%s\", %lld) == %lld", + data, qt_prettyDebug(data, bytesToWrite, 16).constData(), bytesToWrite, written); if (written == -1) qDebug("QProcessPrivate::writeToStdin(), failed to write (%s)", qPrintable(qt_error_string(errno))); #endif - // If the O_NONBLOCK flag is set and If some data can be written without blocking - // the process, write() will transfer what it can and return the number of bytes written. - // Otherwise, it will return -1 and set errno to EAGAIN - if (written == -1 && errno == EAGAIN) - written = 0; - return written; + if (written == -1) { + // If the O_NONBLOCK flag is set and If some data can be written without blocking + // the process, write() will transfer what it can and return the number of bytes written. + // Otherwise, it will return -1 and set errno to EAGAIN + if (errno == EAGAIN) + return true; + + closeChannel(&stdinChannel); + setErrorAndEmit(QProcess::WriteError); + return false; + } + writeBuffer.free(written); + if (!emittedBytesWritten && written != 0) { + emittedBytesWritten = true; + emit q_func()->bytesWritten(written); + emittedBytesWritten = false; + } + return true; } void QProcessPrivate::terminateProcess() diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index ed540f9e5b..96b39efe3a 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -805,17 +805,23 @@ qint64 QProcessPrivate::pipeWriterBytesToWrite() const return stdinChannel.writer ? stdinChannel.writer->bytesToWrite() : qint64(0); } -qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen) +bool QProcessPrivate::writeToStdin() { Q_Q(QProcess); if (!stdinChannel.writer) { stdinChannel.writer = new QWindowsPipeWriter(stdinChannel.pipe[1], q); + QObject::connect(stdinChannel.writer, &QWindowsPipeWriter::bytesWritten, + q, &QProcess::bytesWritten); QObjectPrivate::connect(stdinChannel.writer, &QWindowsPipeWriter::canWrite, this, &QProcessPrivate::_q_canWrite); + } else { + if (stdinChannel.writer->isWriteOperationActive()) + return true; } - return stdinChannel.writer->write(data, maxlen); + stdinChannel.writer->write(writeBuffer.read()); + return true; } // Use ShellExecuteEx() to trigger an UAC prompt when CreateProcess()fails diff --git a/src/corelib/io/qprocess_wince.cpp b/src/corelib/io/qprocess_wince.cpp index 564b3f520d..824a6158dc 100644 --- a/src/corelib/io/qprocess_wince.cpp +++ b/src/corelib/io/qprocess_wince.cpp @@ -271,11 +271,9 @@ qint64 QProcessPrivate::pipeWriterBytesToWrite() const return 0; } -qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen) +bool QProcessPrivate::writeToStdin() { - Q_UNUSED(data); - Q_UNUSED(maxlen); - return -1; + return false; } bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDir, qint64 *pid) diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp index 79e7d13eb5..ab179641f8 100644 --- a/src/corelib/io/qwindowspipewriter.cpp +++ b/src/corelib/io/qwindowspipewriter.cpp @@ -79,21 +79,19 @@ QWindowsPipeWriter::~QWindowsPipeWriter() bool QWindowsPipeWriter::waitForWrite(int msecs) { - if (!writeSequenceStarted) - return false; - if (bytesWrittenPending) { - if (!inBytesWritten) - emitPendingBytesWrittenValue(); + emitPendingBytesWrittenValue(); return true; } + if (!writeSequenceStarted) + return false; + if (!waitForNotification(msecs)) return false; if (bytesWrittenPending) { - if (!inBytesWritten) - emitPendingBytesWrittenValue(); + emitPendingBytesWrittenValue(); return true; } @@ -102,20 +100,24 @@ bool QWindowsPipeWriter::waitForWrite(int msecs) qint64 QWindowsPipeWriter::bytesToWrite() const { - return numberOfBytesToWrite; + return numberOfBytesToWrite + pendingBytesWrittenValue; } void QWindowsPipeWriter::emitPendingBytesWrittenValue() { if (bytesWrittenPending) { + // Reset the state even if we don't emit bytesWritten(). + // It's a defined behavior to not re-emit this signal recursively. bytesWrittenPending = false; const qint64 bytes = pendingBytesWrittenValue; pendingBytesWrittenValue = 0; - inBytesWritten = true; - emit bytesWritten(bytes); - inBytesWritten = false; emit canWrite(); + if (!inBytesWritten) { + inBytesWritten = true; + emit bytesWritten(bytes); + inBytesWritten = false; + } } } @@ -135,6 +137,8 @@ void QWindowsPipeWriter::notified(DWORD errorCode, DWORD numberOfBytesWritten) notifiedCalled = true; writeSequenceStarted = false; numberOfBytesToWrite = 0; + Q_ASSERT(errorCode != ERROR_SUCCESS || numberOfBytesWritten == DWORD(buffer.size())); + buffer.clear(); switch (errorCode) { case ERROR_SUCCESS: @@ -179,21 +183,26 @@ bool QWindowsPipeWriter::waitForNotification(int timeout) return notifiedCalled; } -qint64 QWindowsPipeWriter::write(const char *ptr, qint64 maxlen) +bool QWindowsPipeWriter::write(const QByteArray &ba) { if (writeSequenceStarted) - return 0; + return false; overlapped.clear(); - numberOfBytesToWrite = maxlen; + buffer = ba; + numberOfBytesToWrite = buffer.size(); stopped = false; writeSequenceStarted = true; - if (!WriteFileEx(handle, ptr, maxlen, &overlapped, &writeFileCompleted)) { + if (!WriteFileEx(handle, buffer.constData(), numberOfBytesToWrite, + &overlapped, &writeFileCompleted)) { writeSequenceStarted = false; + numberOfBytesToWrite = 0; + buffer.clear(); qErrnoWarning("QWindowsPipeWriter::write failed."); + return false; } - return maxlen; + return true; } void QWindowsPipeWriter::stop() diff --git a/src/corelib/io/qwindowspipewriter_p.h b/src/corelib/io/qwindowspipewriter_p.h index 59f20edae0..3c641670b6 100644 --- a/src/corelib/io/qwindowspipewriter_p.h +++ b/src/corelib/io/qwindowspipewriter_p.h @@ -53,6 +53,7 @@ #include <qelapsedtimer.h> #include <qobject.h> +#include <qbytearray.h> #include <qt_windows.h> QT_BEGIN_NAMESPACE @@ -112,7 +113,7 @@ public: explicit QWindowsPipeWriter(HANDLE pipeWriteEnd, QObject *parent = 0); ~QWindowsPipeWriter(); - qint64 write(const char *data, qint64 maxlen); + bool write(const QByteArray &ba); void stop(); bool waitForWrite(int msecs); bool isWriteOperationActive() const { return writeSequenceStarted; } @@ -142,6 +143,7 @@ private: HANDLE handle; Overlapped overlapped; + QByteArray buffer; qint64 numberOfBytesToWrite; qint64 pendingBytesWrittenValue; bool stopped; diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 04ec713522..9b421d6a78 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1130,7 +1130,7 @@ QObjectPrivate::Connection::~Connection() RTTI support and it works across dynamic library boundaries. qobject_cast() can also be used in conjunction with interfaces; - see the \l{tools/plugandpaint}{Plug & Paint} example for details. + see the \l{tools/plugandpaint/app}{Plug & Paint} example for details. \warning If T isn't declared with the Q_OBJECT macro, this function's return value is undefined. @@ -4160,11 +4160,11 @@ QDebug operator<<(QDebug dbg, const QObject *o) Example: - \snippet ../widgets/tools/plugandpaintplugins/basictools/basictoolsplugin.h 1 + \snippet ../widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.h 1 \dots - \snippet ../widgets/tools/plugandpaintplugins/basictools/basictoolsplugin.h 3 + \snippet ../widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.h 3 - See the \l{tools/plugandpaintplugins/basictools}{Plug & Paint + See the \l{tools/plugandpaint/plugins/basictools}{Plug & Paint Basic Tools} example for details. \sa Q_DECLARE_INTERFACE(), Q_PLUGIN_METADATA(), {How to Create Qt Plugins} diff --git a/src/corelib/plugin/qplugin.qdoc b/src/corelib/plugin/qplugin.qdoc index 5dcc14b64b..968fb4820a 100644 --- a/src/corelib/plugin/qplugin.qdoc +++ b/src/corelib/plugin/qplugin.qdoc @@ -44,11 +44,11 @@ to the interface class called \a ClassName. The \a Identifier must be unique. For example: - \snippet plugandpaint/interfaces.h 3 + \snippet plugandpaint/app/interfaces.h 3 This macro is normally used right after the class definition for \a ClassName, in a header file. See the - \l{tools/plugandpaint}{Plug & Paint} example for details. + \l{tools/plugandpaint/app}{Plug & Paint} example for details. If you want to use Q_DECLARE_INTERFACE with interface classes declared in a namespace then you have to make sure the Q_DECLARE_INTERFACE @@ -76,7 +76,7 @@ \snippet code/doc_src_qplugin.cpp 1 - See the \l{tools/plugandpaint}{Plug & Paint} example for details. + See the \l{tools/plugandpaint/app}{Plug & Paint} example for details. Note that the class this macro appears on must be default-constructible. diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index 8a797772fc..4aac24f454 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -149,16 +149,12 @@ QThreadPrivate::QThreadPrivate(QThreadData *d) exited(false), returnCode(-1), stackSize(0), priority(QThread::InheritPriority), data(d) { -#if defined (Q_OS_UNIX) - thread_id = 0; -#elif defined (Q_OS_WIN) +#if defined (Q_OS_WIN) handle = 0; # ifndef Q_OS_WINRT id = 0; # endif waiters = 0; -#endif -#if defined (Q_OS_WIN) terminationEnabled = true; terminatePending = false; #endif diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h index adcd98b609..37eca9c612 100644 --- a/src/corelib/thread/qthread_p.h +++ b/src/corelib/thread/qthread_p.h @@ -176,7 +176,6 @@ public: static QThread *threadForId(int id); #ifdef Q_OS_UNIX - pthread_t thread_id; QWaitCondition thread_done; static void *start(void *arg); diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index f456e56a9c..e7a31e0b70 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -110,6 +110,8 @@ QT_BEGIN_NAMESPACE #ifndef QT_NO_THREAD +Q_STATIC_ASSERT(sizeof(pthread_t) == sizeof(Qt::HANDLE)); + enum { ThreadPriorityResetFlag = 0x80000000 }; #if defined(Q_OS_LINUX) && defined(__GLIBC__) && (defined(Q_CC_GNU) || defined(Q_CC_INTEL)) && !defined(QT_LINUXBASE) @@ -239,8 +241,6 @@ QThreadData *QThreadData::current(bool createIfNecessary) void QAdoptedThread::init() { - Q_D(QThread); - d->thread_id = pthread_self(); } /* @@ -328,10 +328,11 @@ void *QThreadPrivate::start(void *arg) // sets the name of the current thread. QString objectName = thr->objectName(); + pthread_t thread_id = reinterpret_cast<pthread_t>(data->threadId); if (Q_LIKELY(objectName.isEmpty())) - setCurrentThreadName(thr->d_func()->thread_id, thr->metaObject()->className()); + setCurrentThreadName(thread_id, thr->metaObject()->className()); else - setCurrentThreadName(thr->d_func()->thread_id, objectName.toLocal8Bit()); + setCurrentThreadName(thread_id, objectName.toLocal8Bit()); } #endif @@ -372,7 +373,6 @@ void QThreadPrivate::finish(void *arg) locker.relock(); } - d->thread_id = 0; d->running = false; d->finished = true; d->interruptionRequested = false; @@ -618,15 +618,16 @@ void QThread::start(Priority priority) } int code = - pthread_create(&d->thread_id, &attr, QThreadPrivate::start, this); + pthread_create(reinterpret_cast<pthread_t *>(&d->data->threadId), &attr, + QThreadPrivate::start, this); if (code == EPERM) { // caller does not have permission to set the scheduling // parameters/policy #if defined(QT_HAS_THREAD_PRIORITY_SCHEDULING) pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED); #endif - code = - pthread_create(&d->thread_id, &attr, QThreadPrivate::start, this); + code = pthread_create(reinterpret_cast<pthread_t *>(&d->data->threadId), &attr, + QThreadPrivate::start, this); } pthread_attr_destroy(&attr); @@ -636,7 +637,7 @@ void QThread::start(Priority priority) d->running = false; d->finished = false; - d->thread_id = 0; + d->data->threadId = 0; } } @@ -646,10 +647,10 @@ void QThread::terminate() Q_D(QThread); QMutexLocker locker(&d->mutex); - if (!d->thread_id) + if (!d->data->threadId) return; - int code = pthread_cancel(d->thread_id); + int code = pthread_cancel(reinterpret_cast<pthread_t>(d->data->threadId)); if (code) { qWarning("QThread::start: Thread termination error: %s", qPrintable(qt_error_string((code)))); @@ -662,7 +663,7 @@ bool QThread::wait(unsigned long time) Q_D(QThread); QMutexLocker locker(&d->mutex); - if (d->thread_id == pthread_self()) { + if (reinterpret_cast<pthread_t>(d->data->threadId) == pthread_self()) { qWarning("QThread::wait: Thread tried to wait on itself"); return false; } @@ -704,7 +705,7 @@ void QThreadPrivate::setPriority(QThread::Priority threadPriority) int sched_policy; sched_param param; - if (pthread_getschedparam(thread_id, &sched_policy, ¶m) != 0) { + if (pthread_getschedparam(reinterpret_cast<pthread_t>(data->threadId), &sched_policy, ¶m) != 0) { // failed to get the scheduling policy, don't bother setting // the priority qWarning("QThread::setPriority: Cannot get scheduler parameters"); @@ -720,15 +721,15 @@ void QThreadPrivate::setPriority(QThread::Priority threadPriority) } param.sched_priority = prio; - int status = pthread_setschedparam(thread_id, sched_policy, ¶m); + int status = pthread_setschedparam(reinterpret_cast<pthread_t>(data->threadId), sched_policy, ¶m); # ifdef SCHED_IDLE // were we trying to set to idle priority and failed? if (status == -1 && sched_policy == SCHED_IDLE && errno == EINVAL) { // reset to lowest priority possible - pthread_getschedparam(thread_id, &sched_policy, ¶m); + pthread_getschedparam(reinterpret_cast<pthread_t>(data->threadId), &sched_policy, ¶m); param.sched_priority = sched_get_priority_min(sched_policy); - pthread_setschedparam(thread_id, sched_policy, ¶m); + pthread_setschedparam(reinterpret_cast<pthread_t>(data->threadId), sched_policy, ¶m); } # else Q_UNUSED(status); diff --git a/src/dbus/qdbus_symbols.cpp b/src/dbus/qdbus_symbols.cpp index b16be6637e..f91a8d2176 100644 --- a/src/dbus/qdbus_symbols.cpp +++ b/src/dbus/qdbus_symbols.cpp @@ -43,7 +43,6 @@ #include <QtCore/qlibrary.h> #endif #include <QtCore/qmutex.h> -#include <private/qmutexpool_p.h> #ifndef QT_NO_DBUS @@ -81,8 +80,10 @@ bool qdbus_loadLibDBus() static bool triedToLoadLibrary = false; #ifndef QT_NO_THREAD - QMutexLocker locker(QMutexPool::globalInstanceGet((void *)&qdbus_resolve_me)); + static QBasicMutex mutex; + QMutexLocker locker(&mutex); #endif + QLibrary *&lib = qdbus_libdbus; if (triedToLoadLibrary) return lib && lib->isLoaded(); diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp index cddb7dfb95..bd25d8a6bf 100644 --- a/src/dbus/qdbusconnection.cpp +++ b/src/dbus/qdbusconnection.cpp @@ -69,6 +69,10 @@ QT_BEGIN_NAMESPACE +#ifdef Q_OS_WIN +static void preventDllUnload(); +#endif + Q_GLOBAL_STATIC(QDBusConnectionManager, _q_manager) // can be replaced with a lambda in Qt 5.7 @@ -157,6 +161,10 @@ QDBusConnectionManager::QDBusConnectionManager() this, &QDBusConnectionManager::createServer, Qt::BlockingQueuedConnection); moveToThread(this); // ugly, don't do this in other projects +#ifdef Q_OS_WIN + // prevent the library from being unloaded on Windows. See comments in the function. + preventDllUnload(); +#endif defaultBuses[0] = defaultBuses[1] = Q_NULLPTR; start(); } @@ -1282,4 +1290,31 @@ QT_END_NAMESPACE #include "qdbusconnection.moc" +#ifdef Q_OS_WIN +# include <qt_windows.h> + +QT_BEGIN_NAMESPACE +static void preventDllUnload() +{ + // Thread termination is really wacky on Windows. For some reason we don't + // understand, exiting from the thread may try to unload the DLL. Since the + // QDBusConnectionManager thread runs until the DLL is unloaded, we've got + // a deadlock: the main thread is waiting for the manager thread to exit, + // but the manager thread is attempting to acquire a lock to unload the DLL. + // + // We work around the issue by preventing the unload from happening in the + // first place. + // + // For this trick, see + // https://blogs.msdn.microsoft.com/oldnewthing/20131105-00/?p=2733 + + static HMODULE self; + GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | + GET_MODULE_HANDLE_EX_FLAG_PIN, + reinterpret_cast<const wchar_t *>(&self), // any address in this DLL + &self); +} +QT_END_NAMESPACE +#endif + #endif // QT_NO_DBUS diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 107ea73a56..81310ae2a2 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -2146,6 +2146,17 @@ bool QWindow::event(QEvent *ev) break; } + case QEvent::PlatformSurface: { + if ((static_cast<QPlatformSurfaceEvent *>(ev))->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed) { +#ifndef QT_NO_OPENGL + QOpenGLContext *context = QOpenGLContext::currentContext(); + if (context && context->surface() == static_cast<QSurface *>(this)) + context->doneCurrent(); +#endif + } + break; + } + default: return QObject::event(ev); } diff --git a/src/gui/opengl/qopenglcustomshaderstage.cpp b/src/gui/opengl/qopenglcustomshaderstage.cpp index a0386bd5f3..baa44f86b0 100644 --- a/src/gui/opengl/qopenglcustomshaderstage.cpp +++ b/src/gui/opengl/qopenglcustomshaderstage.cpp @@ -69,6 +69,7 @@ QOpenGLCustomShaderStage::~QOpenGLCustomShaderStage() d->m_manager->removeCustomStage(); d->m_manager->sharedShaders->cleanupCustomStage(this); } + delete d_ptr; } void QOpenGLCustomShaderStage::setUniformsDirty() diff --git a/src/gui/opengl/qopenglcustomshaderstage_p.h b/src/gui/opengl/qopenglcustomshaderstage_p.h index 099e6aadf8..2342991e5e 100644 --- a/src/gui/opengl/qopenglcustomshaderstage_p.h +++ b/src/gui/opengl/qopenglcustomshaderstage_p.h @@ -52,6 +52,7 @@ // #include <QOpenGLShaderProgram> +#include <QtGlobal> QT_BEGIN_NAMESPACE @@ -78,6 +79,8 @@ protected: private: QOpenGLCustomShaderStagePrivate* d_ptr; + + Q_DISABLE_COPY(QOpenGLCustomShaderStage) }; diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 0b205b8b0e..1b947154ef 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -6255,9 +6255,6 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const painter->setRenderHint(QPainter::Qt4CompatiblePainting, false); const qreal underlineOffset = fe->underlinePosition().toReal(); - // deliberately ceil the offset to avoid the underline coming too close to - // the text above it. - const qreal underlinePos = pos.y() + qCeil(underlineOffset) + 0.5; if (underlineStyle == QTextCharFormat::SpellCheckUnderline) { QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme(); @@ -6282,6 +6279,12 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave); painter->restore(); } else if (underlineStyle != QTextCharFormat::NoUnderline) { + // Deliberately ceil the offset to avoid the underline coming too close to + // the text above it, but limit it to stay within descent. + qreal adjustedUnderlineOffset = std::ceil(underlineOffset) + 0.5; + if (underlineOffset <= fe->descent().toReal()) + adjustedUnderlineOffset = qMin(adjustedUnderlineOffset, fe->descent().toReal() - 0.5); + const qreal underlinePos = pos.y() + adjustedUnderlineOffset; QColor uc = charFormat.underlineColor(); if (uc.isValid()) pen.setColor(uc); diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp index a756549f3e..e2130a09d9 100644 --- a/src/gui/text/qtextobject.cpp +++ b/src/gui/text/qtextobject.cpp @@ -418,9 +418,12 @@ QTextFrame::QTextFrame(QTextDocument *doc) { } -// ### DOC: What does this do to child frames? /*! - Destroys the frame, and removes it from the document's layout. + Destroys the text frame. + + \warning Text frames are owned by the document, so you should + never destroy them yourself. In order to remove a frame from + its document, remove its contents using a \c QTextCursor. */ QTextFrame::~QTextFrame() { diff --git a/src/network/kernel/qdnslookup_unix.cpp b/src/network/kernel/qdnslookup_unix.cpp index d2c5542139..35981a2f2c 100644 --- a/src/network/kernel/qdnslookup_unix.cpp +++ b/src/network/kernel/qdnslookup_unix.cpp @@ -42,7 +42,6 @@ #include <qlibrary.h> #include <qscopedpointer.h> #include <qurl.h> -#include <private/qmutexpool_p.h> #include <private/qnativesocketengine_p.h> #include <sys/types.h> @@ -78,7 +77,7 @@ struct QDnsLookupStateDeleter } }; -static void resolveLibrary() +static bool resolveLibraryInternal() { QLibrary lib; #ifdef LIBRESOLV_SO @@ -88,7 +87,7 @@ static void resolveLibrary() { lib.setFileName(QLatin1String("resolv")); if (!lib.load()) - return; + return false; } local_dn_expand = dn_expand_proto(lib.resolve("__dn_expand")); @@ -112,19 +111,15 @@ static void resolveLibrary() local_res_nquery = res_nquery_proto(lib.resolve("res_9_nquery")); if (!local_res_nquery) local_res_nquery = res_nquery_proto(lib.resolve("res_nquery")); + + return true; } +Q_GLOBAL_STATIC_WITH_ARGS(bool, resolveLibrary, (resolveLibraryInternal())) void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestName, const QHostAddress &nameserver, QDnsLookupReply *reply) { // Load dn_expand, res_ninit and res_nquery on demand. - static QBasicAtomicInt triedResolve = Q_BASIC_ATOMIC_INITIALIZER(false); - if (!triedResolve.loadAcquire()) { - QMutexLocker locker(QMutexPool::globalInstanceGet(&local_res_ninit)); - if (!triedResolve.load()) { - resolveLibrary(); - triedResolve.storeRelease(true); - } - } + resolveLibrary(); // If dn_expand, res_ninit or res_nquery is missing, fail. if (!local_dn_expand || !local_res_nclose || !local_res_ninit || !local_res_nquery) { diff --git a/src/network/kernel/qhostinfo_unix.cpp b/src/network/kernel/qhostinfo_unix.cpp index 8a3f3fa5c9..7af8db73e0 100644 --- a/src/network/kernel/qhostinfo_unix.cpp +++ b/src/network/kernel/qhostinfo_unix.cpp @@ -49,7 +49,6 @@ #include <qbasicatomic.h> #include <qurl.h> #include <qfile.h> -#include <private/qmutexpool_p.h> #include <private/qnet_unix_p.h> #include <sys/types.h> @@ -92,7 +91,7 @@ typedef void (*res_nclose_proto)(res_state_ptr); static res_nclose_proto local_res_nclose = 0; static res_state_ptr local_res = 0; -static void resolveLibrary() +static bool resolveLibraryInternal() { #if !defined(QT_NO_LIBRARY) && !defined(Q_OS_QNX) QLibrary lib; @@ -103,7 +102,7 @@ static void resolveLibrary() { lib.setFileName(QLatin1String("resolv")); if (!lib.load()) - return; + return false; } local_res_init = res_init_proto(lib.resolve("__res_init")); @@ -125,7 +124,10 @@ static void resolveLibrary() local_res_ninit = 0; } #endif + + return true; } +Q_GLOBAL_STATIC_WITH_ARGS(bool, resolveLibrary, (resolveLibraryInternal())) QHostInfo QHostInfoAgent::fromName(const QString &hostName) { @@ -137,14 +139,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) #endif // Load res_init on demand. - static QBasicAtomicInt triedResolve = Q_BASIC_ATOMIC_INITIALIZER(false); - if (!triedResolve.loadAcquire()) { - QMutexLocker locker(QMutexPool::globalInstanceGet(&local_res_init)); - if (!triedResolve.load()) { - resolveLibrary(); - triedResolve.storeRelease(true); - } - } + resolveLibrary(); // If res_init is available, poll it. if (local_res_init) diff --git a/src/network/kernel/qhostinfo_win.cpp b/src/network/kernel/qhostinfo_win.cpp index cc6102a713..b98f36a612 100644 --- a/src/network/kernel/qhostinfo_win.cpp +++ b/src/network/kernel/qhostinfo_win.cpp @@ -45,7 +45,6 @@ #include <qmutex.h> #include <qbasicatomic.h> #include <qurl.h> -#include <private/qmutexpool_p.h> QT_BEGIN_NAMESPACE @@ -78,7 +77,7 @@ static getnameinfoProto local_getnameinfo = 0; static getaddrinfoProto local_getaddrinfo = 0; static freeaddrinfoProto local_freeaddrinfo = 0; -static void resolveLibrary() +static bool resolveLibraryInternal() { // Attempt to resolve getaddrinfo(); without it we'll have to fall // back to gethostbyname(), which has no IPv6 support. @@ -95,7 +94,9 @@ static void resolveLibrary() local_freeaddrinfo = (freeaddrinfoProto) QSystemLibrary::resolve(QLatin1String("ws2_32"), "freeaddrinfo"); local_getnameinfo = (getnameinfoProto) QSystemLibrary::resolve(QLatin1String("ws2_32"), "getnameinfo"); #endif + return true; } +Q_GLOBAL_STATIC_WITH_ARGS(bool, resolveLibrary, (resolveLibraryInternal())) static void translateWSAError(int error, QHostInfo *results) { @@ -123,14 +124,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) QSysInfo::machineHostName(); // this initializes ws2_32.dll // Load res_init on demand. - static QBasicAtomicInt triedResolve = Q_BASIC_ATOMIC_INITIALIZER(false); - if (!triedResolve.loadAcquire()) { - QMutexLocker locker(QMutexPool::globalInstanceGet(&local_getaddrinfo)); - if (!triedResolve.load()) { - resolveLibrary(); - triedResolve.storeRelease(true); - } - } + resolveLibrary(); QHostInfo results; diff --git a/src/network/socket/qlocalsocket.h b/src/network/socket/qlocalsocket.h index da91ef0e85..0eecab206b 100644 --- a/src/network/socket/qlocalsocket.h +++ b/src/network/socket/qlocalsocket.h @@ -130,7 +130,7 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_stateChanged(QAbstractSocket::SocketState)) Q_PRIVATE_SLOT(d_func(), void _q_error(QAbstractSocket::SocketError)) #elif defined(Q_OS_WIN) - Q_PRIVATE_SLOT(d_func(), void _q_bytesWritten(qint64)) + Q_PRIVATE_SLOT(d_func(), void _q_canWrite()) Q_PRIVATE_SLOT(d_func(), void _q_pipeClosed()) Q_PRIVATE_SLOT(d_func(), void _q_winError(ulong, const QString &)) #else diff --git a/src/network/socket/qlocalsocket_p.h b/src/network/socket/qlocalsocket_p.h index 0f84aeea3e..cf36887e92 100644 --- a/src/network/socket/qlocalsocket_p.h +++ b/src/network/socket/qlocalsocket_p.h @@ -130,8 +130,7 @@ public: ~QLocalSocketPrivate(); void destroyPipeHandles(); void setErrorString(const QString &function); - void startNextWrite(); - void _q_bytesWritten(qint64 bytes); + void _q_canWrite(); void _q_pipeClosed(); void _q_winError(ulong windowsError, const QString &function); HANDLE handle; diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp index 5fc34c3ed6..66b461522b 100644 --- a/src/network/socket/qlocalsocket_win.cpp +++ b/src/network/socket/qlocalsocket_win.cpp @@ -218,11 +218,12 @@ qint64 QLocalSocket::writeData(const char *data, qint64 len) memcpy(dest, data, len); if (!d->pipeWriter) { d->pipeWriter = new QWindowsPipeWriter(d->handle, this); - QObjectPrivate::connect(d->pipeWriter, &QWindowsPipeWriter::bytesWritten, - d, &QLocalSocketPrivate::_q_bytesWritten); + connect(d->pipeWriter, &QWindowsPipeWriter::bytesWritten, + this, &QLocalSocket::bytesWritten); + QObjectPrivate::connect(d->pipeWriter, &QWindowsPipeWriter::canWrite, + d, &QLocalSocketPrivate::_q_canWrite); } - if (!d->pipeWriter->isWriteOperationActive()) - d->startNextWrite(); + d->_q_canWrite(); return len; } @@ -275,7 +276,7 @@ qint64 QLocalSocket::bytesAvailable() const qint64 QLocalSocket::bytesToWrite() const { Q_D(const QLocalSocket); - return d->writeBuffer.size(); + return d->writeBuffer.size() + (d->pipeWriter ? d->pipeWriter->bytesToWrite() : 0); } bool QLocalSocket::canReadLine() const @@ -358,7 +359,7 @@ bool QLocalSocket::setSocketDescriptor(qintptr socketDescriptor, return true; } -void QLocalSocketPrivate::startNextWrite() +void QLocalSocketPrivate::_q_canWrite() { Q_Q(QLocalSocket); if (writeBuffer.isEmpty()) { @@ -366,18 +367,11 @@ void QLocalSocketPrivate::startNextWrite() q->close(); } else { Q_ASSERT(pipeWriter); - pipeWriter->write(writeBuffer.readPointer(), writeBuffer.nextDataBlockSize()); + if (!pipeWriter->isWriteOperationActive()) + pipeWriter->write(writeBuffer.read()); } } -void QLocalSocketPrivate::_q_bytesWritten(qint64 bytes) -{ - Q_Q(QLocalSocket); - writeBuffer.free(bytes); - startNextWrite(); - emit q->bytesWritten(bytes); -} - qintptr QLocalSocket::socketDescriptor() const { Q_D(const QLocalSocket); diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 6ff5c884f7..5ffe7b11b8 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -574,6 +574,19 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters() } } + // Some Windows kernels return a v4-mapped QHostAddress::AnyIPv4 as a + // local address of the socket which bound on both IPv4 and IPv6 interfaces. + // This address does not match to any special address and should not be used + // to send the data. So, replace it with QHostAddress::Any. + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + bool ok = false; + const quint32 localIPv4 = localAddress.toIPv4Address(&ok); + if (ok && localIPv4 == INADDR_ANY) { + socketProtocol = QAbstractSocket::AnyIPProtocol; + localAddress = QHostAddress::Any; + } + } + memset(&sa, 0, sizeof(sa)); if (::getpeername(socketDescriptor, &sa.a, &sockAddrSize) == 0) { qt_socket_getPortAndAddress(socketDescriptor, &sa, &peerPort, &peerAddress); @@ -1186,7 +1199,7 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const #endif #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEnginePrivate::nativePendingDatagramSize() == %li", ret); + qDebug("QNativeSocketEnginePrivate::nativePendingDatagramSize() == %lli", ret); #endif return ret; @@ -1292,10 +1305,11 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxL } #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %li, %s, %i) == %li", + bool printSender = (ret != -1 && (options & QNativeSocketEngine::WantDatagramSender) != 0); + qDebug("QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %lli, %s, %i) == %lli", data, qt_prettyDebug(data, qMin<qint64>(ret, 16), ret).data(), maxLength, - address ? address->toString().toLatin1().constData() : "(nil)", - port ? *port : 0, ret); + printSender ? header->senderAddress.toString().toLatin1().constData() : "(unknown)", + printSender ? header->senderPort : 0, ret); #endif return ret; @@ -1407,9 +1421,10 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l } #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEnginePrivate::nativeSendDatagram(%p \"%s\", %li, \"%s\", %i) == %li", data, - qt_prettyDebug(data, qMin<qint64>(len, 16), len).data(), 0, address.toString().toLatin1().constData(), - port, ret); + qDebug("QNativeSocketEnginePrivate::nativeSendDatagram(%p \"%s\", %lli, \"%s\", %i) == %lli", data, + qt_prettyDebug(data, qMin<qint64>(len, 16), len).data(), len, + header.destinationAddress.toString().toLatin1().constData(), + header.destinationPort, ret); #endif return ret; diff --git a/src/plugins/bearer/android/jar/jar.pri b/src/plugins/bearer/android/jar/jar.pri index 6d9aac3bb3..e43dbf0711 100644 --- a/src/plugins/bearer/android/jar/jar.pri +++ b/src/plugins/bearer/android/jar/jar.pri @@ -9,5 +9,3 @@ JAVASOURCES += $$PWD/src/org/qtproject/qt5/android/bearer/QtNetworkReceiver.java # install target.path = $$[QT_INSTALL_PREFIX]/jar INSTALLS += target - -OTHER_FILES += $$JAVASOURCES diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 697cece77f..3115db2b83 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -75,6 +75,8 @@ static QTouchDevice *touchDevice = 0; // ### HACK Remove once 10.8 is unsupported static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; +static bool _q_dontOverrideCtrlLMB = false; + @interface NSEvent (Qt_Compile_Leopard_DeviceDelta) - (CGFloat)deviceDeltaX; - (CGFloat)deviceDeltaY; @@ -135,6 +137,8 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; NSString **notificationNameVar = (NSString **)dlsym(RTLD_NEXT, "NSWindowDidChangeOcclusionStateNotification"); if (notificationNameVar) _q_NSWindowDidChangeOcclusionStateNotification = *notificationNameVar; + + _q_dontOverrideCtrlLMB = qt_mac_resolveOption(false, "QT_MAC_DONT_OVERRIDE_CTRL_LMB"); } - (id) init @@ -969,7 +973,7 @@ QT_WARNING_POP if ([self hasMarkedText]) { [[NSTextInputContext currentInputContext] handleEvent:theEvent]; } else { - if ([QNSView convertKeyModifiers:[theEvent modifierFlags]] & Qt::MetaModifier) { + if (!_q_dontOverrideCtrlLMB && [QNSView convertKeyModifiers:[theEvent modifierFlags]] & Qt::MetaModifier) { m_buttons |= Qt::RightButton; m_sendUpAsRightButton = true; } else { diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp index 8536e2c239..d96c3964df 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp @@ -107,8 +107,10 @@ QEglFSKmsGbmCursor::~QEglFSKmsGbmCursor() drmModeMoveCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0); } - gbm_bo_destroy(m_bo); - m_bo = Q_NULLPTR; + if (m_bo) { + gbm_bo_destroy(m_bo); + m_bo = Q_NULLPTR; + } } void QEglFSKmsGbmCursor::pointerEvent(const QMouseEvent &event) @@ -121,6 +123,9 @@ void QEglFSKmsGbmCursor::changeCursor(QCursor *windowCursor, QWindow *window) { Q_UNUSED(window); + if (!m_bo) + return; + if (!m_visible) return; diff --git a/src/plugins/platforms/ios/qiosscreen.h b/src/plugins/platforms/ios/qiosscreen.h index 461298269d..56a0874bb4 100644 --- a/src/plugins/platforms/ios/qiosscreen.h +++ b/src/plugins/platforms/ios/qiosscreen.h @@ -79,7 +79,7 @@ private: QRect m_geometry; QRect m_availableGeometry; int m_depth; - uint m_pixelDensity; + uint m_physicalDpi; QSizeF m_physicalSize; QIOSOrientationListener *m_orientationListener; }; diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index 29cb5876af..bfd22abaa4 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -186,18 +186,18 @@ QIOSScreen::QIOSScreen(UIScreen *screen) if (deviceIdentifier.contains(QRegularExpression("^iPhone(7,1|8,2)$"))) { // iPhone 6 Plus or iPhone 6S Plus - m_pixelDensity = 401; + m_physicalDpi = 401; } else if (deviceIdentifier.contains(QRegularExpression("^iPad(1,1|2,[1-4]|3,[1-6]|4,[1-3]|5,[3-4]|6,[7-8])$"))) { // All iPads except the iPad Mini series - m_pixelDensity = 132 * devicePixelRatio(); + m_physicalDpi = 132 * devicePixelRatio(); } else { // All non-Plus iPhones, and iPad Minis - m_pixelDensity = 163 * devicePixelRatio(); + m_physicalDpi = 163 * devicePixelRatio(); } } else { // External display, hard to say m_depth = 24; - m_pixelDensity = 96; + m_physicalDpi = 96; } for (UIWindow *existingWindow in [[UIApplication sharedApplication] windows]) { @@ -259,8 +259,23 @@ void QIOSScreen::updateProperties() } if (m_geometry != previousGeometry) { - const qreal millimetersPerInch = 25.4; - m_physicalSize = QSizeF(m_geometry.size() * devicePixelRatio()) / m_pixelDensity * millimetersPerInch; + QRectF physicalGeometry; + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_8_0) { + // We can't use the primaryOrientation of screen(), as we haven't reported the new geometry yet + Qt::ScreenOrientation primaryOrientation = m_geometry.width() >= m_geometry.height() ? + Qt::LandscapeOrientation : Qt::PortraitOrientation; + + // On iPhone 6+ devices, or when display zoom is enabled, the render buffer is scaled + // before being output on the physical display. We have to take this into account when + // computing the physical size. Note that unlike the native bounds, the physical size + // follows the primary orientation of the screen. + physicalGeometry = mapBetween(nativeOrientation(), primaryOrientation, fromCGRect(m_uiScreen.nativeBounds).toRect()); + } else { + physicalGeometry = QRectF(0, 0, m_geometry.width() * devicePixelRatio(), m_geometry.height() * devicePixelRatio()); + } + + static const qreal millimetersPerInch = 25.4; + m_physicalSize = physicalGeometry.size() / m_physicalDpi * millimetersPerInch; } // At construction time, we don't yet have an associated QScreen, but we still want diff --git a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp index d123bdf82d..321e124eee 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp +++ b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp @@ -263,15 +263,15 @@ static int openTtyDevice(const QString &device) return fd; } -static bool switchToGraphicsMode(int ttyfd, int *oldMode) +static void switchToGraphicsMode(int ttyfd, bool doSwitch, int *oldMode) { - ioctl(ttyfd, KDGETMODE, oldMode); - if (*oldMode != KD_GRAPHICS) { - if (ioctl(ttyfd, KDSETMODE, KD_GRAPHICS) != 0) - return false; + // Do not warn if the switch fails: the ioctl fails when launching from a + // remote console and there is nothing we can do about it. The matching + // call in resetTty should at least fail then, too, so we do no harm. + if (ioctl(ttyfd, KDGETMODE, oldMode) == 0) { + if (doSwitch && *oldMode != KD_GRAPHICS) + ioctl(ttyfd, KDSETMODE, KD_GRAPHICS); } - - return true; } static void resetTty(int ttyfd, int oldMode) @@ -287,14 +287,16 @@ static void blankScreen(int fd, bool on) } QLinuxFbScreen::QLinuxFbScreen(const QStringList &args) - : mArgs(args), mFbFd(-1), mBlitter(0) + : mArgs(args), mFbFd(-1), mTtyFd(-1), mBlitter(0) { + mMmap.data = 0; } QLinuxFbScreen::~QLinuxFbScreen() { if (mFbFd != -1) { - munmap(mMmap.data - mMmap.offset, mMmap.size); + if (mMmap.data) + munmap(mMmap.data - mMmap.offset, mMmap.size); close(mFbFd); } @@ -394,11 +396,7 @@ bool QLinuxFbScreen::initialize() if (mTtyFd == -1) qErrnoWarning(errno, "Failed to open tty"); - if (doSwitchToGraphicsMode) - switchToGraphicsMode(mTtyFd, &mOldTtyMode); - // Do not warn if the switch fails: the ioctl fails when launching from - // a remote console and there is nothing we can do about it. - + switchToGraphicsMode(mTtyFd, doSwitchToGraphicsMode, &mOldTtyMode); blankScreen(mFbFd, false); return true; diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 2126c271f9..87b4c7b91f 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -1638,8 +1638,13 @@ bool QXcbConnection::compressEvent(xcb_generic_event_t *event, int currentIndex, if (!m_xi2Enabled) return false; - // compress XI_Motion + // compress XI_Motion, but not from tablet devices if (isXIType(event, m_xiOpCode, XI_Motion)) { +#ifndef QT_NO_TABLETEVENT + xXIDeviceEvent *xdev = reinterpret_cast<xXIDeviceEvent *>(event); + if (const_cast<QXcbConnection *>(this)->tabletDataForDevice(xdev->sourceid)) + return false; +#endif // QT_NO_TABLETEVENT for (int j = nextIndex; j < eventqueue->size(); ++j) { xcb_generic_event_t *next = eventqueue->at(j); if (!isValid(next)) diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 68d7b5622f..891f0fbcb5 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -584,6 +584,7 @@ private: bool xi2HandleTabletEvent(const void *event, TabletData *tabletData); void xi2ReportTabletEvent(const void *event, TabletData *tabletData); QVector<TabletData> m_tabletData; + TabletData *tabletDataForDevice(int id); #endif // !QT_NO_TABLETEVENT struct ScrollingDevice { ScrollingDevice() : deviceId(0), verticalIndex(0), horizontalIndex(0), orientations(0), legacyOrientations(0) { } diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 836761c9b9..5b7f45fb6c 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -119,7 +119,7 @@ void QXcbConnection::xi2SetupDevices() // Only non-master pointing devices are relevant here. if (devices[i].use != XISlavePointer) continue; - qCDebug(lcQpaXInputDevices) << "input device "<< devices[i].name; + qCDebug(lcQpaXInputDevices) << "input device " << devices[i].name << "ID" << devices[i].deviceid; #ifndef QT_NO_TABLETEVENT TabletData tabletData; #endif @@ -537,12 +537,9 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) #ifndef QT_NO_TABLETEVENT if (!xiEnterEvent) { - for (int i = 0; i < m_tabletData.count(); ++i) { - if (m_tabletData.at(i).deviceId == sourceDeviceId) { - if (xi2HandleTabletEvent(xiEvent, &m_tabletData[i])) - return; - } - } + QXcbConnection::TabletData *tablet = tabletDataForDevice(sourceDeviceId); + if (tablet && xi2HandleTabletEvent(xiEvent, tablet)) + return; } #endif // QT_NO_TABLETEVENT @@ -1195,6 +1192,16 @@ void QXcbConnection::xi2ReportTabletEvent(const void *event, TabletData *tabletD xTilt, yTilt, tangentialPressure, rotation, 0, tabletData->serialId); } + +QXcbConnection::TabletData *QXcbConnection::tabletDataForDevice(int id) +{ + for (int i = 0; i < m_tabletData.count(); ++i) { + if (m_tabletData.at(i).deviceId == id) + return &m_tabletData[i]; + } + return Q_NULLPTR; +} + #endif // QT_NO_TABLETEVENT #endif // XCB_USE_XINPUT2 diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index 1c9faa17ea..b55fbd8f03 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -1140,10 +1140,10 @@ void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event at = findTransactionByWindow(event->requestor); } - if (at == -1 && event->time == XCB_CURRENT_TIME) { + if (at == -1) { xcb_window_t target = findXdndAwareParent(connection(), event->requestor); if (target) { - if (current_target == target) + if (event->time == XCB_CURRENT_TIME && current_target == target) at = -2; else at = findTransactionByWindow(target); diff --git a/src/widgets/widgets/qsplitter.cpp b/src/widgets/widgets/qsplitter.cpp index e3ca6b0a79..17b7a9ebb3 100644 --- a/src/widgets/widgets/qsplitter.cpp +++ b/src/widgets/widgets/qsplitter.cpp @@ -1099,6 +1099,8 @@ void QSplitter::resizeEvent(QResizeEvent *) If \a widget is already in the splitter, it will be moved to the new position. + \note The splitter takes ownership of the widget. + \sa insertWidget(), widget(), indexOf() */ void QSplitter::addWidget(QWidget *widget) @@ -1113,7 +1115,9 @@ void QSplitter::addWidget(QWidget *widget) If \a widget is already in the splitter, it will be moved to the new position. - if \a index is an invalid index, then the widget will be inserted at the end. + If \a index is an invalid index, then the widget will be inserted at the end. + + \note The splitter takes ownership of the widget. \sa addWidget(), indexOf(), widget() */ |