summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/forkfd/forkfd.c6
-rw-r--r--src/3rdparty/forkfd/forkfd.h4
-rw-r--r--src/corelib/arch/qatomic_ia64.h8
-rw-r--r--src/corelib/doc/qtcore.qdocconf3
-rw-r--r--src/corelib/doc/src/statemachine.qdoc2
-rw-r--r--src/corelib/global/qnamespace.qdoc11
-rw-r--r--src/corelib/io/qiodevice.cpp6
-rw-r--r--src/corelib/io/qlockfile_unix.cpp24
-rw-r--r--src/corelib/io/qstandardpaths_win.cpp2
-rw-r--r--src/corelib/io/qtextstream.cpp2
-rw-r--r--src/corelib/io/qwindowspipereader.cpp2
-rw-r--r--src/corelib/io/qwindowspipewriter.cpp54
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp12
-rw-r--r--src/corelib/kernel/qcoreapplication_p.h2
-rw-r--r--src/corelib/kernel/qeventdispatcher_win.cpp112
-rw-r--r--src/corelib/kernel/qeventdispatcher_win_p.h11
-rw-r--r--src/corelib/kernel/qmetaobject.cpp5
-rw-r--r--src/corelib/kernel/qobject.cpp2
-rw-r--r--src/corelib/kernel/qsocketnotifier.cpp36
-rw-r--r--src/corelib/mimetypes/qmimedatabase.cpp1
-rw-r--r--src/corelib/mimetypes/qmimedatabase.h1
-rw-r--r--src/corelib/mimetypes/qmimedatabase_p.h1
-rw-r--r--src/corelib/mimetypes/qmimemagicrule.cpp68
-rw-r--r--src/corelib/mimetypes/qmimemagicrule_p.h3
-rw-r--r--src/corelib/mimetypes/qmimeprovider.cpp1
-rw-r--r--src/corelib/mimetypes/qmimeprovider_p.h1
-rw-r--r--src/corelib/mimetypes/qmimetype.cpp1
-rw-r--r--src/corelib/mimetypes/qmimetype.h1
-rw-r--r--src/corelib/mimetypes/qmimetypeparser.cpp40
-rw-r--r--src/corelib/mimetypes/qmimetypeparser_p.h2
-rw-r--r--src/corelib/plugin/qelfparser_p.cpp2
-rw-r--r--src/corelib/thread/qmutex.cpp15
-rw-r--r--src/corelib/thread/qthread_p.h2
-rw-r--r--src/corelib/thread/qthread_unix.cpp2
-rw-r--r--src/corelib/thread/qthread_win.cpp2
-rw-r--r--src/corelib/thread/qthreadstorage.cpp6
-rw-r--r--src/corelib/tools/qdatetime.cpp1
-rw-r--r--src/corelib/tools/qstring.h8
-rw-r--r--src/corelib/tools/qstringalgorithms_p.h2
-rw-r--r--src/gui/image/qimagereader.cpp2
-rw-r--r--src/gui/image/qppmhandler.cpp3
-rw-r--r--src/gui/kernel/qcursor.cpp10
-rw-r--r--src/gui/kernel/qcursor_p.h3
-rw-r--r--src/gui/kernel/qguiapplication.cpp4
-rw-r--r--src/gui/kernel/qwindow.cpp6
-rw-r--r--src/gui/kernel/qwindowsysteminterface.cpp1
-rw-r--r--src/gui/math3d/qmatrix4x4.cpp2
-rw-r--r--src/gui/opengl/qopenglframebufferobject.cpp17
-rw-r--r--src/gui/painting/qcosmeticstroker.cpp3
-rw-r--r--src/gui/painting/qpdfwriter.cpp3
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp9
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp22
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel_p.h1
-rw-r--r--src/network/access/qhttpnetworkreply.cpp11
-rw-r--r--src/network/access/qhttpnetworkreply_p.h6
-rw-r--r--src/network/access/qhttpthreaddelegate.cpp1
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp70
-rw-r--r--src/network/access/qnetworkaccessmanager_p.h14
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp19
-rw-r--r--src/network/access/qnetworkreplyhttpimpl_p.h2
-rw-r--r--src/network/access/qnetworkreplyimpl.cpp15
-rw-r--r--src/network/access/qnetworkreplyimpl_p.h2
-rw-r--r--src/network/kernel/qauthenticator.cpp39
-rw-r--r--src/network/socket/qabstractsocket.cpp12
-rw-r--r--src/network/socket/qlocalserver_unix.cpp22
-rw-r--r--src/network/socket/qlocalsocket_unix.cpp7
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp2
-rw-r--r--src/network/socket/qnativesocketengine_win.cpp37
-rw-r--r--src/network/socket/qnativesocketengine_winrt.cpp89
-rw-r--r--src/network/socket/qnativesocketengine_winrt_p.h4
-rw-r--r--src/network/ssl/qsslellipticcurve.cpp5
-rw-r--r--src/network/ssl/qsslpresharedkeyauthenticator.cpp2
-rw-r--r--src/platformsupport/dbusmenu/qdbusplatformmenu.cpp6
-rw-r--r--src/platformsupport/dbusmenu/qdbusplatformmenu_p.h1
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcontext.cpp12
-rw-r--r--src/platformsupport/themes/genericunix/qgenericunixthemes.cpp7
-rw-r--r--src/plugins/platforms/cocoa/qcocoacursor.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm12
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.mm41
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm10
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm8
-rw-r--r--src/plugins/platforms/ios/qiosmenu.h4
-rw-r--r--src/plugins/platforms/ios/qiosmenu.mm39
-rw-r--r--src/plugins/platforms/ios/qiostextresponder.mm187
-rw-r--r--src/plugins/platforms/ios/qiostheme.mm2
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.mm9
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.cpp4
-rw-r--r--src/printsupport/dialogs/qprintdialog_unix.cpp2
-rw-r--r--src/printsupport/kernel/qpaintengine_alpha.cpp10
-rw-r--r--src/printsupport/kernel/qprintengine_win.cpp7
-rw-r--r--src/tools/qdoc/doc/examples/examples.qdoc6
-rw-r--r--src/widgets/accessible/accessible.pri12
-rw-r--r--src/widgets/accessible/complexwidgets.cpp2
-rw-r--r--src/widgets/accessible/complexwidgets_p.h (renamed from src/widgets/accessible/complexwidgets.h)11
-rw-r--r--src/widgets/accessible/itemviews.cpp2
-rw-r--r--src/widgets/accessible/itemviews_p.h (renamed from src/widgets/accessible/itemviews.h)11
-rw-r--r--src/widgets/accessible/qaccessiblemenu.cpp2
-rw-r--r--src/widgets/accessible/qaccessiblemenu_p.h (renamed from src/widgets/accessible/qaccessiblemenu.h)11
-rw-r--r--src/widgets/accessible/qaccessiblewidgetfactory.cpp12
-rw-r--r--src/widgets/accessible/qaccessiblewidgets.cpp2
-rw-r--r--src/widgets/accessible/qaccessiblewidgets_p.h (renamed from src/widgets/accessible/qaccessiblewidgets.h)11
-rw-r--r--src/widgets/accessible/rangecontrols.cpp4
-rw-r--r--src/widgets/accessible/rangecontrols_p.h (renamed from src/widgets/accessible/rangecontrols.h)11
-rw-r--r--src/widgets/accessible/simplewidgets.cpp2
-rw-r--r--src/widgets/accessible/simplewidgets_p.h (renamed from src/widgets/accessible/simplewidgets.h)11
-rw-r--r--src/widgets/dialogs/qfiledialog.cpp13
-rw-r--r--src/widgets/doc/images/filedialogurls.pngbin29132 -> 26724 bytes
-rw-r--r--src/widgets/doc/qtwidgets.qdocconf2
-rw-r--r--src/widgets/doc/snippets/filedialogurls.cpp4
-rw-r--r--src/widgets/kernel/qgesturemanager.cpp5
-rw-r--r--src/widgets/kernel/qgesturemanager_p.h2
-rw-r--r--src/widgets/kernel/qwidget.cpp5
115 files changed, 1025 insertions, 396 deletions
diff --git a/src/3rdparty/forkfd/forkfd.c b/src/3rdparty/forkfd/forkfd.c
index 51223aef1f..e55ef47683 100644
--- a/src/3rdparty/forkfd/forkfd.c
+++ b/src/3rdparty/forkfd/forkfd.c
@@ -45,12 +45,12 @@
#ifdef __linux__
# define HAVE_WAIT4 1
# if defined(__BIONIC__) || (defined(__GLIBC__) && (__GLIBC__ << 8) + __GLIBC_MINOR__ >= 0x207 && \
- (!defined(__UCLIBC__) || ((__UCLIBC_MAJOR__ << 16) + (__UCLIBC_MINOR__ << 8) + __UCLIBC_SUBLEVEL__ > 0x921)))
+ (!defined(__UCLIBC__) || ((__UCLIBC_MAJOR__ << 16) + (__UCLIBC_MINOR__ << 8) + __UCLIBC_SUBLEVEL__ > 0x90201)))
# include <sys/eventfd.h>
# define HAVE_EVENTFD 1
# endif
# if defined(__BIONIC__) || (defined(__GLIBC__) && (__GLIBC__ << 8) + __GLIBC_MINOR__ >= 0x209 && \
- (!defined(__UCLIBC__) || ((__UCLIBC_MAJOR__ << 16) + (__UCLIBC_MINOR__ << 8) + __UCLIBC_SUBLEVEL__ > 0x921)))
+ (!defined(__UCLIBC__) || ((__UCLIBC_MAJOR__ << 16) + (__UCLIBC_MINOR__ << 8) + __UCLIBC_SUBLEVEL__ > 0x90201)))
# define HAVE_PIPE2 1
# endif
#endif
@@ -721,7 +721,7 @@ err_free:
}
#endif // FORKFD_NO_FORKFD
-#if defined(_POSIX_SPAWN) && !defined(FORKFD_NO_SPAWNFD)
+#if _POSIX_SPAWN > 0 && !defined(FORKFD_NO_SPAWNFD)
int spawnfd(int flags, pid_t *ppid, const char *path, const posix_spawn_file_actions_t *file_actions,
posix_spawnattr_t *attrp, char *const argv[], char *const envp[])
{
diff --git a/src/3rdparty/forkfd/forkfd.h b/src/3rdparty/forkfd/forkfd.h
index dcb36f9f33..38858c00fe 100644
--- a/src/3rdparty/forkfd/forkfd.h
+++ b/src/3rdparty/forkfd/forkfd.h
@@ -29,7 +29,7 @@
#include <stdint.h>
#include <unistd.h> // to get the POSIX flags
-#ifdef _POSIX_SPAWN
+#if _POSIX_SPAWN > 0
# include <spawn.h>
#endif
@@ -51,7 +51,7 @@ int forkfd(int flags, pid_t *ppid);
int forkfd_wait(int ffd, forkfd_info *info, struct rusage *rusage);
int forkfd_close(int ffd);
-#ifdef _POSIX_SPAWN
+#if _POSIX_SPAWN > 0
/* only for spawnfd: */
# define FFD_SPAWN_SEARCH_PATH O_RDWR
diff --git a/src/corelib/arch/qatomic_ia64.h b/src/corelib/arch/qatomic_ia64.h
index c880e85209..2ba6d127d9 100644
--- a/src/corelib/arch/qatomic_ia64.h
+++ b/src/corelib/arch/qatomic_ia64.h
@@ -1035,16 +1035,16 @@ bool QBasicAtomicOps<size>::deref(T &_q_value) Q_DECL_NOTHROW
}
template<int size> template <typename T> inline
-bool QBasicAtomicOps<size>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW
+bool QBasicAtomicOps<size>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW
{
- return testAndSetAcquire(_q_value, expectedValue, newValue);
+ return testAndSetAcquire(_q_value, expectedValue, newValue, currentValue);
}
template<int size> template <typename T> inline
-bool QBasicAtomicOps<size>::testAndSetOrdered(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW
+bool QBasicAtomicOps<size>::testAndSetOrdered(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW
{
orderedMemoryFence(_q_value);
- return testAndSetAcquire(_q_value, expectedValue, newValue);
+ return testAndSetAcquire(_q_value, expectedValue, newValue, currentValue);
}
template<int size> template <typename T> inline
diff --git a/src/corelib/doc/qtcore.qdocconf b/src/corelib/doc/qtcore.qdocconf
index 502689e4c2..3d64708def 100644
--- a/src/corelib/doc/qtcore.qdocconf
+++ b/src/corelib/doc/qtcore.qdocconf
@@ -25,8 +25,7 @@ qhp.QtCore.subprojects.classes.sortPages = true
tagfile = ../../../doc/qtcore/qtcore.tags
-depends += activeqt qtdbus qtgui qtwidgets qtnetwork qtdoc qtmacextras qtquick qtlinguist qtdesigner qtconcurrent qtxml qmake qtwinextras
-# depends += qtqml # Qt namespace collides with QtQml::Qt, see QTBUG-38630
+depends += activeqt qtdbus qtgui qtwidgets qtnetwork qtdoc qtmacextras qtquick qtlinguist qtdesigner qtconcurrent qtxml qmake qtwinextras qtqml
headerdirs += ..
diff --git a/src/corelib/doc/src/statemachine.qdoc b/src/corelib/doc/src/statemachine.qdoc
index e44a603959..d50851d816 100644
--- a/src/corelib/doc/src/statemachine.qdoc
+++ b/src/corelib/doc/src/statemachine.qdoc
@@ -71,6 +71,8 @@
which are currently active. All the states in a valid configuration of the state machine will
have a common ancestor.
+ \sa {The Declarative State Machine Framework}
+
\section1 Classes in the State Machine Framework
These classes are provided by qt for creating event-driven state machines.
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index 3dc791397c..443eae5a11 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -1714,6 +1714,17 @@
\value Key_Zoom
\value Key_Exit
\value Key_Cancel
+ \value Key_MicVolumeUp
+ \value Key_Find
+ \value Key_Open
+ \value Key_MicVolumeDown
+ \value Key_New
+ \value Key_Settings
+ \value Key_Redo
+ \value Key_Exit
+ \value Key_Info
+ \value Key_Undo
+ \value Key_Guide
\sa QKeyEvent::key()
*/
diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp
index 84a6a1d9cb..c80c78bd3b 100644
--- a/src/corelib/io/qiodevice.cpp
+++ b/src/corelib/io/qiodevice.cpp
@@ -83,6 +83,7 @@ void debugBinaryString(const char *data, qint64 maxlen)
static void checkWarnMessage(const QIODevice *device, const char *function, const char *what)
{
+#ifndef QT_NO_WARNING_OUTPUT
QDebug d = qWarning();
d.noquote();
d.nospace();
@@ -98,6 +99,11 @@ static void checkWarnMessage(const QIODevice *device, const char *function, cons
Q_UNUSED(device)
#endif // !QT_NO_QOBJECT
d << ": " << what;
+#else
+ Q_UNUSED(device);
+ Q_UNUSED(function);
+ Q_UNUSED(what);
+#endif // QT_NO_WARNING_OUTPUT
}
#define CHECK_MAXLEN(function, returnType) \
diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp
index b298b08939..019059917a 100644
--- a/src/corelib/io/qlockfile_unix.cpp
+++ b/src/corelib/io/qlockfile_unix.cpp
@@ -56,7 +56,13 @@
# include <cstdio>
#elif defined(Q_OS_BSD4) && !defined(Q_OS_IOS)
# include <sys/user.h>
+# if defined(__GLIBC__) && defined(__FreeBSD_kernel__)
+# include <sys/cdefs.h>
+# include <sys/param.h>
+# include <sys/sysctl.h>
+# else
# include <libutil.h>
+# endif
#endif
QT_BEGIN_NAMESPACE
@@ -241,9 +247,27 @@ QString QLockFilePrivate::processNameByPid(qint64 pid)
buf[len] = 0;
return QFileInfo(QFile::decodeName(buf)).fileName();
#elif defined(Q_OS_BSD4) && !defined(Q_OS_IOS)
+# if defined(__GLIBC__) && defined(__FreeBSD_kernel__)
+ int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid };
+ size_t len = 0;
+ if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0)
+ return QString();
+ kinfo_proc *proc = static_cast<kinfo_proc *>(malloc(len));
+# else
kinfo_proc *proc = kinfo_getproc(pid);
+# endif
if (!proc)
return QString();
+# if defined(__GLIBC__) && defined(__FreeBSD_kernel__)
+ if (sysctl(mib, 4, proc, &len, NULL, 0) < 0) {
+ free(proc);
+ return QString();
+ }
+ if (proc->ki_pid != pid) {
+ free(proc);
+ return QString();
+ }
+# endif
QString name = QFile::decodeName(proc->ki_comm);
free(proc);
return name;
diff --git a/src/corelib/io/qstandardpaths_win.cpp b/src/corelib/io/qstandardpaths_win.cpp
index 0a13f94f05..ed1c14ad8a 100644
--- a/src/corelib/io/qstandardpaths_win.cpp
+++ b/src/corelib/io/qstandardpaths_win.cpp
@@ -200,7 +200,7 @@ QStringList QStandardPaths::standardLocations(StandardLocation type)
case AppDataLocation:
case AppLocalDataLocation:
case GenericDataLocation:
- if (SHGetSpecialFolderPath(0, path, clsidForAppDataLocation(type), FALSE)) {
+ if (SHGetSpecialFolderPath(0, path, CSIDL_COMMON_APPDATA, FALSE)) {
QString result = convertCharArray(path);
if (type != GenericDataLocation && type != GenericConfigLocation) {
#ifndef QT_BOOTSTRAPPED
diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp
index ca3be9b7e0..ccf832e2e8 100644
--- a/src/corelib/io/qtextstream.cpp
+++ b/src/corelib/io/qtextstream.cpp
@@ -2858,7 +2858,7 @@ QTextStream &endl(QTextStream &stream)
/*!
\relates QTextStream
- Calls \l{QTextStream::flush()}{flush()} on \a stream and returns \a stream.
+ Calls QTextStream::flush() on \a stream and returns \a stream.
\sa endl(), reset(), {QTextStream manipulators}
*/
diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp
index 2cc5741250..a49fcdaf9f 100644
--- a/src/corelib/io/qwindowspipereader.cpp
+++ b/src/corelib/io/qwindowspipereader.cpp
@@ -187,7 +187,7 @@ void QWindowsPipeReader::notified(quint32 numberOfBytesRead, quint32 errorCode,
pipeBroken = true;
break;
default:
- emit winError(errorCode, QLatin1String("QWindowsPipeReader::completeAsyncRead"));
+ emit winError(errorCode, QLatin1String("QWindowsPipeReader::notified"));
pipeBroken = true;
break;
}
diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp
index 57053f129a..fd14523d45 100644
--- a/src/corelib/io/qwindowspipewriter.cpp
+++ b/src/corelib/io/qwindowspipewriter.cpp
@@ -90,11 +90,38 @@ qint64 QWindowsPipeWriter::write(const char *ptr, qint64 maxlen)
return maxlen;
}
+class QPipeWriterOverlapped
+{
+public:
+ QPipeWriterOverlapped()
+ {
+ overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ }
+
+ ~QPipeWriterOverlapped()
+ {
+ CloseHandle(overlapped.hEvent);
+ }
+
+ void prepare()
+ {
+ const HANDLE hEvent = overlapped.hEvent;
+ ZeroMemory(&overlapped, sizeof overlapped);
+ overlapped.hEvent = hEvent;
+ }
+
+ OVERLAPPED *operator&()
+ {
+ return &overlapped;
+ }
+
+private:
+ OVERLAPPED overlapped;
+};
+
void QWindowsPipeWriter::run()
{
- OVERLAPPED overl;
- memset(&overl, 0, sizeof overl);
- overl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ QPipeWriterOverlapped overl;
forever {
lock.lock();
while(data.isEmpty() && (!quitNow)) {
@@ -115,26 +142,24 @@ void QWindowsPipeWriter::run()
const char *ptrData = copy.data();
qint64 maxlen = copy.size();
qint64 totalWritten = 0;
- overl.Offset = 0;
- overl.OffsetHigh = 0;
+ overl.prepare();
while ((!quitNow) && totalWritten < maxlen) {
DWORD written = 0;
if (!WriteFile(writePipe, ptrData + totalWritten,
maxlen - totalWritten, &written, &overl)) {
-
- if (GetLastError() == 0xE8/*NT_STATUS_INVALID_USER_BUFFER*/) {
+ const DWORD writeError = GetLastError();
+ if (writeError == 0xE8/*NT_STATUS_INVALID_USER_BUFFER*/) {
// give the os a rest
msleep(100);
continue;
}
#ifndef Q_OS_WINCE
- if (GetLastError() == ERROR_IO_PENDING) {
- if (!GetOverlappedResult(writePipe, &overl, &written, TRUE)) {
- CloseHandle(overl.hEvent);
- return;
- }
- } else {
- CloseHandle(overl.hEvent);
+ if (writeError != ERROR_IO_PENDING) {
+ qErrnoWarning(writeError, "QWindowsPipeWriter: async WriteFile failed.");
+ return;
+ }
+ if (!GetOverlappedResult(writePipe, &overl, &written, TRUE)) {
+ qErrnoWarning(GetLastError(), "QWindowsPipeWriter: GetOverlappedResult failed.");
return;
}
#else
@@ -154,7 +179,6 @@ void QWindowsPipeWriter::run()
emit bytesWritten(totalWritten);
emit canWrite();
}
- CloseHandle(overl.hEvent);
}
#endif //QT_NO_THREAD
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 8f4774a1e0..2719019d30 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -455,8 +455,8 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint
qt_application_thread_id = QThread::currentThreadId();
# endif
- // note: this call to QThread::currentThread() may end up setting theMainThread!
- if (QThread::currentThread() != theMainThread)
+ QThread *cur = QThread::currentThread(); // note: this may end up setting theMainThread!
+ if (cur != theMainThread)
qWarning("WARNING: QApplication was not created in the main() thread.");
#endif
}
@@ -526,11 +526,11 @@ void QCoreApplicationPrivate::eventDispatcherReady()
{
}
-QThread *QCoreApplicationPrivate::theMainThread = 0;
+QBasicAtomicPointer<QThread> QCoreApplicationPrivate::theMainThread = Q_BASIC_ATOMIC_INITIALIZER(0);
QThread *QCoreApplicationPrivate::mainThread()
{
- Q_ASSERT(theMainThread != 0);
- return theMainThread;
+ Q_ASSERT(theMainThread.load() != 0);
+ return theMainThread.load();
}
bool QCoreApplicationPrivate::threadRequiresCoreApplication()
@@ -2759,7 +2759,7 @@ bool QCoreApplication::hasPendingEvents()
QAbstractEventDispatcher *QCoreApplication::eventDispatcher()
{
if (QCoreApplicationPrivate::theMainThread)
- return QCoreApplicationPrivate::theMainThread->eventDispatcher();
+ return QCoreApplicationPrivate::theMainThread.load()->eventDispatcher();
return 0;
}
diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h
index 21f59d8197..9a9e8dd09a 100644
--- a/src/corelib/kernel/qcoreapplication_p.h
+++ b/src/corelib/kernel/qcoreapplication_p.h
@@ -105,7 +105,7 @@ public:
}
void maybeQuit();
- static QThread *theMainThread;
+ static QBasicAtomicPointer<QThread> theMainThread;
static QThread *mainThread();
static bool threadRequiresCoreApplication();
diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp
index e8ff8a7936..ecaa78cbbc 100644
--- a/src/corelib/kernel/qeventdispatcher_win.cpp
+++ b/src/corelib/kernel/qeventdispatcher_win.cpp
@@ -390,6 +390,8 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
QSockNot *sn = dict ? dict->value(wp) : 0;
if (sn) {
+ d->doWsaAsyncSelect(sn->fd, 0);
+ d->active_fd[sn->fd].selected = false;
if (type < 3) {
QEvent event(QEvent::SockAct);
QCoreApplication::sendEvent(sn->obj, &event);
@@ -632,19 +634,12 @@ void QEventDispatcherWin32Private::sendTimerEvent(int timerId)
}
}
-void QEventDispatcherWin32Private::doWsaAsyncSelect(int socket)
+void QEventDispatcherWin32Private::doWsaAsyncSelect(int socket, long event)
{
Q_ASSERT(internalHwnd);
- int sn_event = 0;
- if (sn_read.contains(socket))
- sn_event |= FD_READ | FD_CLOSE | FD_ACCEPT;
- if (sn_write.contains(socket))
- sn_event |= FD_WRITE | FD_CONNECT;
- if (sn_except.contains(socket))
- sn_event |= FD_OOB;
- // BoundsChecker may emit a warning for WSAAsyncSelect when sn_event == 0
+ // BoundsChecker may emit a warning for WSAAsyncSelect when event == 0
// This is a BoundsChecker bug and not a Qt bug
- WSAAsyncSelect(socket, internalHwnd, sn_event ? int(WM_QT_SOCKETNOTIFIER) : 0, sn_event);
+ WSAAsyncSelect(socket, internalHwnd, event ? int(WM_QT_SOCKETNOTIFIER) : 0, event);
}
void QEventDispatcherWin32::createInternalHwnd()
@@ -657,13 +652,6 @@ void QEventDispatcherWin32::createInternalHwnd()
installMessageHook();
- // register all socket notifiers
- QList<int> sockets = (d->sn_read.keys().toSet()
- + d->sn_write.keys().toSet()
- + d->sn_except.keys().toSet()).toList();
- for (int i = 0; i < sockets.count(); ++i)
- d->doWsaAsyncSelect(sockets.at(i));
-
// start all normal timers
for (int i = 0; i < d->timerVec.count(); ++i)
d->registerTimer(d->timerVec.at(i));
@@ -748,28 +736,40 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
msg = d->queuedSocketEvents.takeFirst();
} else {
haveMessage = PeekMessage(&msg, 0, 0, 0, PM_REMOVE);
- if (haveMessage && (flags & QEventLoop::ExcludeUserInputEvents)
- && ((msg.message >= WM_KEYFIRST
- && msg.message <= WM_KEYLAST)
- || (msg.message >= WM_MOUSEFIRST
- && msg.message <= WM_MOUSELAST)
- || msg.message == WM_MOUSEWHEEL
- || msg.message == WM_MOUSEHWHEEL
- || msg.message == WM_TOUCH
+ if (haveMessage) {
+ if ((flags & QEventLoop::ExcludeUserInputEvents)
+ && ((msg.message >= WM_KEYFIRST
+ && msg.message <= WM_KEYLAST)
+ || (msg.message >= WM_MOUSEFIRST
+ && msg.message <= WM_MOUSELAST)
+ || msg.message == WM_MOUSEWHEEL
+ || msg.message == WM_MOUSEHWHEEL
+ || msg.message == WM_TOUCH
#ifndef QT_NO_GESTURES
- || msg.message == WM_GESTURE
- || msg.message == WM_GESTURENOTIFY
+ || msg.message == WM_GESTURE
+ || msg.message == WM_GESTURENOTIFY
#endif
- || msg.message == WM_CLOSE)) {
- // queue user input events for later processing
- haveMessage = false;
- d->queuedUserInputEvents.append(msg);
- }
- if (haveMessage && (flags & QEventLoop::ExcludeSocketNotifiers)
- && (msg.message == WM_QT_SOCKETNOTIFIER && msg.hwnd == d->internalHwnd)) {
- // queue socket events for later processing
- haveMessage = false;
- d->queuedSocketEvents.append(msg);
+ || msg.message == WM_CLOSE)) {
+ // queue user input events for later processing
+ d->queuedUserInputEvents.append(msg);
+ continue;
+ }
+ if ((flags & QEventLoop::ExcludeSocketNotifiers)
+ && (msg.message == WM_QT_SOCKETNOTIFIER && msg.hwnd == d->internalHwnd)) {
+ // queue socket events for later processing
+ d->queuedSocketEvents.append(msg);
+ continue;
+ }
+ } else if (!(flags & QEventLoop::ExcludeSocketNotifiers)) {
+ // register all socket notifiers
+ for (QSFDict::iterator it = d->active_fd.begin(), end = d->active_fd.end();
+ it != end; ++it) {
+ QSockFd &sd = it.value();
+ if (!sd.selected) {
+ d->doWsaAsyncSelect(it.key(), sd.event);
+ sd.selected = true;
+ }
+ }
}
}
if (!haveMessage) {
@@ -895,8 +895,25 @@ void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier)
sn->fd = sockfd;
dict->insert(sn->fd, sn);
- if (d->internalHwnd)
- d->doWsaAsyncSelect(sockfd);
+ long event = 0;
+ if (d->sn_read.contains(sockfd))
+ event |= FD_READ | FD_CLOSE | FD_ACCEPT;
+ if (d->sn_write.contains(sockfd))
+ event |= FD_WRITE | FD_CONNECT;
+ if (d->sn_except.contains(sockfd))
+ event |= FD_OOB;
+
+ QSFDict::iterator it = d->active_fd.find(sockfd);
+ if (it != d->active_fd.end()) {
+ QSockFd &sd = it.value();
+ if (sd.selected) {
+ d->doWsaAsyncSelect(sockfd, 0);
+ sd.selected = false;
+ }
+ sd.event |= event;
+ } else {
+ d->active_fd.insert(sockfd, QSockFd(event));
+ }
}
void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier)
@@ -915,6 +932,19 @@ void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier)
#endif
Q_D(QEventDispatcherWin32);
+ QSFDict::iterator it = d->active_fd.find(sockfd);
+ if (it != d->active_fd.end()) {
+ QSockFd &sd = it.value();
+ if (sd.selected)
+ d->doWsaAsyncSelect(sockfd, 0);
+ const long event[3] = { FD_READ | FD_CLOSE | FD_ACCEPT, FD_WRITE | FD_CONNECT, FD_OOB };
+ sd.event ^= event[type];
+ if (sd.event == 0)
+ d->active_fd.erase(it);
+ else
+ sd.selected = false;
+ }
+
QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except };
QSNDict *dict = sn_vec[type];
QSockNot *sn = dict->value(sockfd);
@@ -923,9 +953,6 @@ void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier)
dict->remove(sockfd);
delete sn;
-
- if (d->internalHwnd)
- d->doWsaAsyncSelect(sockfd);
}
void QEventDispatcherWin32::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object)
@@ -1163,6 +1190,7 @@ void QEventDispatcherWin32::closingDown()
unregisterSocketNotifier((*(d->sn_write.begin()))->obj);
while (!d->sn_except.isEmpty())
unregisterSocketNotifier((*(d->sn_except.begin()))->obj);
+ Q_ASSERT(d->active_fd.isEmpty());
// clean up any timers
for (int i = 0; i < d->timerVec.count(); ++i)
diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h
index e59e29f1ff..8578110ee4 100644
--- a/src/corelib/kernel/qeventdispatcher_win_p.h
+++ b/src/corelib/kernel/qeventdispatcher_win_p.h
@@ -115,6 +115,14 @@ struct QSockNot {
};
typedef QHash<int, QSockNot *> QSNDict;
+struct QSockFd {
+ long event;
+ bool selected;
+
+ explicit inline QSockFd(long ev = 0) : event(ev), selected(false) { }
+};
+typedef QHash<int, QSockFd> QSFDict;
+
struct WinTimerInfo { // internal timer info
QObject *dispatcher;
int timerId;
@@ -169,7 +177,8 @@ public:
QSNDict sn_read;
QSNDict sn_write;
QSNDict sn_except;
- void doWsaAsyncSelect(int socket);
+ QSFDict active_fd;
+ void doWsaAsyncSelect(int socket, long event);
QList<QWinEventNotifier *> winEventNotifierList;
void activateEventNotifier(QWinEventNotifier * wen);
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index 7ae9fef622..f1ad74efb4 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -1547,12 +1547,13 @@ bool QMetaObject::invokeMethod(QObject *obj,
/*!
\fn QMetaObject::Connection &QMetaObject::Connection::operator=(Connection &&other)
- Move-assigns \a other to this object.
+ Move-assigns \a other to this object, and returns a reference.
*/
/*!
\fn QMetaObject::Connection::Connection(Connection &&o)
- Move-constructs a Connection instance, making it point to the same object that \a o was pointing to.
+ Move-constructs a Connection instance, making it point to the same object
+ that \a o was pointing to.
*/
/*!
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index d324b6f150..4bd8b4b662 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -1485,7 +1485,7 @@ void QObject::moveToThread(QThread *targetThread)
} else if (d->threadData != currentData) {
qWarning("QObject::moveToThread: Current thread (%p) is not the object's thread (%p).\n"
"Cannot move to target thread (%p)\n",
- currentData->thread, d->threadData->thread, targetData ? targetData->thread : Q_NULLPTR);
+ currentData->thread.load(), d->threadData->thread.load(), targetData ? targetData->thread.load() : Q_NULLPTR);
#ifdef Q_OS_MAC
qWarning("You might be loading two sets of Qt binaries into the same process. "
diff --git a/src/corelib/kernel/qsocketnotifier.cpp b/src/corelib/kernel/qsocketnotifier.cpp
index d789af2fd9..3a5eff0c19 100644
--- a/src/corelib/kernel/qsocketnotifier.cpp
+++ b/src/corelib/kernel/qsocketnotifier.cpp
@@ -98,42 +98,6 @@ public:
QTcpSocket and QUdpSocket provide notification through signals, so
there is normally no need to use a QSocketNotifier on them.
- \section1 Notes for Windows Users
-
- The socket passed to QSocketNotifier will become non-blocking, even if
- it was created as a blocking socket.
- The activated() signal is sometimes triggered by high general activity
- on the host, even if there is nothing to read. A subsequent read from
- the socket can then fail, the error indicating that there is no data
- available (e.g., \c{WSAEWOULDBLOCK}). This is an operating system
- limitation, and not a bug in QSocketNotifier.
-
- To ensure that the socket notifier handles read notifications correctly,
- follow these steps when you receive a notification:
-
- \list 1
- \li Disable the notifier.
- \li Read data from the socket.
- \li Re-enable the notifier if you are interested in more data (such as after
- having written a new command to a remote server).
- \endlist
-
- To ensure that the socket notifier handles write notifications correctly,
- follow these steps when you receive a notification:
-
- \list 1
- \li Disable the notifier.
- \li Write as much data as you can (before \c EWOULDBLOCK is returned).
- \li Re-enable notifier if you have more data to write.
- \endlist
-
- \b{Further information:}
- On Windows, Qt always disables the notifier after getting a notification,
- and only re-enables it if more data is expected. For example, if data is
- read from the socket and it can be used to read more, or if reading or
- writing is not possible because the socket would block, in which case
- it is necessary to wait before attempting to read or write again.
-
\sa QFile, QProcess, QTcpSocket, QUdpSocket
*/
diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp
index 133933f9af..c1e17b9fc4 100644
--- a/src/corelib/mimetypes/qmimedatabase.cpp
+++ b/src/corelib/mimetypes/qmimedatabase.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
diff --git a/src/corelib/mimetypes/qmimedatabase.h b/src/corelib/mimetypes/qmimedatabase.h
index 912d9b8443..fd19636e27 100644
--- a/src/corelib/mimetypes/qmimedatabase.h
+++ b/src/corelib/mimetypes/qmimedatabase.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
diff --git a/src/corelib/mimetypes/qmimedatabase_p.h b/src/corelib/mimetypes/qmimedatabase_p.h
index 1308907b9b..1ac7264a9e 100644
--- a/src/corelib/mimetypes/qmimedatabase_p.h
+++ b/src/corelib/mimetypes/qmimedatabase_p.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
diff --git a/src/corelib/mimetypes/qmimemagicrule.cpp b/src/corelib/mimetypes/qmimemagicrule.cpp
index c8508ac0d2..6a3a429179 100644
--- a/src/corelib/mimetypes/qmimemagicrule.cpp
+++ b/src/corelib/mimetypes/qmimemagicrule.cpp
@@ -38,6 +38,7 @@
#ifndef QT_NO_MIMETYPE
+#include "qmimetypeparser_p.h"
#include <QtCore/QList>
#include <QtCore/QDebug>
#include <qendian.h>
@@ -231,26 +232,53 @@ static inline QByteArray makePattern(const QByteArray &value)
return pattern;
}
-QMimeMagicRule::QMimeMagicRule(QMimeMagicRule::Type theType,
+// Evaluate a magic match rule like
+// <match value="must be converted with BinHex" type="string" offset="11"/>
+// <match value="0x9501" type="big16" offset="0:64"/>
+
+QMimeMagicRule::QMimeMagicRule(const QString &typeStr,
const QByteArray &theValue,
- int theStartPos,
- int theEndPos,
- const QByteArray &theMask) :
+ const QString &offsets,
+ const QByteArray &theMask,
+ QString *errorString) :
d(new QMimeMagicRulePrivate)
{
- Q_ASSERT(!theValue.isEmpty());
-
- d->type = theType;
d->value = theValue;
- d->startPos = theStartPos;
- d->endPos = theEndPos;
d->mask = theMask;
d->matchFunction = 0;
+ d->type = QMimeMagicRule::type(typeStr.toLatin1());
+ if (d->type == Invalid) {
+ *errorString = QStringLiteral("Type %s is not supported").arg(typeStr);
+ }
+
+ // Parse for offset as "1" or "1:10"
+ const int colonIndex = offsets.indexOf(QLatin1Char(':'));
+ const QString startPosStr = colonIndex == -1 ? offsets : offsets.mid(0, colonIndex);
+ const QString endPosStr = colonIndex == -1 ? offsets : offsets.mid(colonIndex + 1);
+ if (!QMimeTypeParserBase::parseNumber(startPosStr, &d->startPos, errorString) ||
+ !QMimeTypeParserBase::parseNumber(endPosStr, &d->endPos, errorString)) {
+ d->type = Invalid;
+ return;
+ }
+
+ if (d->value.isEmpty()) {
+ d->type = Invalid;
+ if (errorString)
+ *errorString = QLatin1String("Invalid empty magic rule value");
+ return;
+ }
+
if (d->type >= Host16 && d->type <= Byte) {
bool ok;
d->number = d->value.toUInt(&ok, 0); // autodetect
- Q_ASSERT(ok);
+ if (!ok) {
+ d->type = Invalid;
+ if (errorString)
+ *errorString = QString::fromLatin1("Invalid magic rule value \"%1\"").arg(
+ QString::fromLatin1(d->value));
+ return;
+ }
d->numberMask = !d->mask.isEmpty() ? d->mask.toUInt(&ok, 0) : 0; // autodetect
}
@@ -259,9 +287,23 @@ QMimeMagicRule::QMimeMagicRule(QMimeMagicRule::Type theType,
d->pattern = makePattern(d->value);
d->pattern.squeeze();
if (!d->mask.isEmpty()) {
- Q_ASSERT(d->mask.size() >= 4 && d->mask.startsWith("0x"));
- d->mask = QByteArray::fromHex(QByteArray::fromRawData(d->mask.constData() + 2, d->mask.size() - 2));
- Q_ASSERT(d->mask.size() == d->pattern.size());
+ if (d->mask.size() < 4 || !d->mask.startsWith("0x")) {
+ d->type = Invalid;
+ if (errorString)
+ *errorString = QString::fromLatin1("Invalid magic rule mask \"%1\"").arg(
+ QString::fromLatin1(d->mask));
+ return;
+ }
+ const QByteArray &tempMask = QByteArray::fromHex(QByteArray::fromRawData(
+ d->mask.constData() + 2, d->mask.size() - 2));
+ if (tempMask.size() != d->pattern.size()) {
+ d->type = Invalid;
+ if (errorString)
+ *errorString = QString::fromLatin1("Invalid magic rule mask size \"%1\"").arg(
+ QString::fromLatin1(d->mask));
+ return;
+ }
+ d->mask = tempMask;
} else {
d->mask.fill(char(-1), d->pattern.size());
}
diff --git a/src/corelib/mimetypes/qmimemagicrule_p.h b/src/corelib/mimetypes/qmimemagicrule_p.h
index 03ac1d1de9..6b64bfcc10 100644
--- a/src/corelib/mimetypes/qmimemagicrule_p.h
+++ b/src/corelib/mimetypes/qmimemagicrule_p.h
@@ -61,7 +61,8 @@ class QMimeMagicRule
public:
enum Type { Invalid = 0, String, Host16, Host32, Big16, Big32, Little16, Little32, Byte };
- QMimeMagicRule(Type type, const QByteArray &value, int startPos, int endPos, const QByteArray &mask = QByteArray());
+ QMimeMagicRule(const QString &typeStr, const QByteArray &value, const QString &offsets,
+ const QByteArray &mask, QString *errorString);
QMimeMagicRule(const QMimeMagicRule &other);
~QMimeMagicRule();
diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp
index fa40b743d3..a8a1331053 100644
--- a/src/corelib/mimetypes/qmimeprovider.cpp
+++ b/src/corelib/mimetypes/qmimeprovider.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
diff --git a/src/corelib/mimetypes/qmimeprovider_p.h b/src/corelib/mimetypes/qmimeprovider_p.h
index eaf95942f7..c0517d69a4 100644
--- a/src/corelib/mimetypes/qmimeprovider_p.h
+++ b/src/corelib/mimetypes/qmimeprovider_p.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
diff --git a/src/corelib/mimetypes/qmimetype.cpp b/src/corelib/mimetypes/qmimetype.cpp
index 3206ff66e3..e3b01bbb89 100644
--- a/src/corelib/mimetypes/qmimetype.cpp
+++ b/src/corelib/mimetypes/qmimetype.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
diff --git a/src/corelib/mimetypes/qmimetype.h b/src/corelib/mimetypes/qmimetype.h
index 054a5841c4..6a00541ebc 100644
--- a/src/corelib/mimetypes/qmimetype.h
+++ b/src/corelib/mimetypes/qmimetype.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
diff --git a/src/corelib/mimetypes/qmimetypeparser.cpp b/src/corelib/mimetypes/qmimetypeparser.cpp
index 9610162c4f..8a8b97655a 100644
--- a/src/corelib/mimetypes/qmimetypeparser.cpp
+++ b/src/corelib/mimetypes/qmimetypeparser.cpp
@@ -153,8 +153,8 @@ QMimeTypeParserBase::ParseState QMimeTypeParserBase::nextState(ParseState curren
return ParseError;
}
-// Parse int number from an (attribute) string)
-static bool parseNumber(const QString &n, int *target, QString *errorMessage)
+// Parse int number from an (attribute) string
+bool QMimeTypeParserBase::parseNumber(const QString &n, int *target, QString *errorMessage)
{
bool ok;
*target = n.toInt(&ok);
@@ -165,37 +165,14 @@ static bool parseNumber(const QString &n, int *target, QString *errorMessage)
return true;
}
-// Evaluate a magic match rule like
-// <match value="must be converted with BinHex" type="string" offset="11"/>
-// <match value="0x9501" type="big16" offset="0:64"/>
#ifndef QT_NO_XMLSTREAMREADER
-static bool createMagicMatchRule(const QXmlStreamAttributes &atts,
- QString *errorMessage, QMimeMagicRule *&rule)
+static QMimeMagicRule *createMagicMatchRule(const QXmlStreamAttributes &atts, QString *errorMessage)
{
const QString type = atts.value(QLatin1String(matchTypeAttributeC)).toString();
- QMimeMagicRule::Type magicType = QMimeMagicRule::type(type.toLatin1());
- if (magicType == QMimeMagicRule::Invalid) {
- qWarning("%s: match type %s is not supported.", Q_FUNC_INFO, type.toUtf8().constData());
- return true;
- }
const QString value = atts.value(QLatin1String(matchValueAttributeC)).toString();
- if (value.isEmpty()) {
- *errorMessage = QString::fromLatin1("Empty match value detected.");
- return false;
- }
- // Parse for offset as "1" or "1:10"
- int startPos, endPos;
- const QString offsetS = atts.value(QLatin1String(matchOffsetAttributeC)).toString();
- const int colonIndex = offsetS.indexOf(QLatin1Char(':'));
- const QString startPosS = colonIndex == -1 ? offsetS : offsetS.mid(0, colonIndex);
- const QString endPosS = colonIndex == -1 ? offsetS : offsetS.mid(colonIndex + 1);
- if (!parseNumber(startPosS, &startPos, errorMessage) || !parseNumber(endPosS, &endPos, errorMessage))
- return false;
+ const QString offsets = atts.value(QLatin1String(matchOffsetAttributeC)).toString();
const QString mask = atts.value(QLatin1String(matchMaskAttributeC)).toString();
-
- rule = new QMimeMagicRule(magicType, value.toUtf8(), startPos, endPos, mask.toLatin1());
-
- return true;
+ return new QMimeMagicRule(type, value.toUtf8(), offsets, mask.toLatin1(), errorMessage);
}
#endif
@@ -283,9 +260,10 @@ bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString
}
break;
case ParseMagicMatchRule: {
- QMimeMagicRule *rule = 0;
- if (!createMagicMatchRule(atts, errorMessage, rule))
- return false;
+ QString magicErrorMessage;
+ QMimeMagicRule *rule = createMagicMatchRule(atts, &magicErrorMessage);
+ if (!rule->isValid())
+ qWarning("QMimeDatabase: Error parsing %s\n%s", qPrintable(fileName), qPrintable(magicErrorMessage));
QList<QMimeMagicRule> *ruleList;
if (currentRules.isEmpty())
ruleList = &rules;
diff --git a/src/corelib/mimetypes/qmimetypeparser_p.h b/src/corelib/mimetypes/qmimetypeparser_p.h
index 2be4380cee..3a2e6b8a14 100644
--- a/src/corelib/mimetypes/qmimetypeparser_p.h
+++ b/src/corelib/mimetypes/qmimetypeparser_p.h
@@ -66,6 +66,8 @@ public:
bool parse(QIODevice *dev, const QString &fileName, QString *errorMessage);
+ static bool parseNumber(const QString &n, int *target, QString *errorMessage);
+
protected:
virtual bool process(const QMimeType &t, QString *errorMessage) = 0;
virtual bool process(const QMimeGlobPattern &t, QString *errorMessage) = 0;
diff --git a/src/corelib/plugin/qelfparser_p.cpp b/src/corelib/plugin/qelfparser_p.cpp
index d93be439e0..3798231383 100644
--- a/src/corelib/plugin/qelfparser_p.cpp
+++ b/src/corelib/plugin/qelfparser_p.cpp
@@ -148,7 +148,7 @@ int QElfParser::parse(const char *dataStart, ulong fdlen, const QString &library
#endif
ElfSectionHeader strtab;
- qulonglong soff = e_shoff + e_shentsize * (e_shtrndx);
+ qulonglong soff = e_shoff + qelfword_t(e_shentsize) * qelfword_t(e_shtrndx);
if ((soff + e_shentsize) > fdlen || soff % 4 || soff == 0) {
if (lib)
diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp
index 3269ee3ae8..742a572bef 100644
--- a/src/corelib/thread/qmutex.cpp
+++ b/src/corelib/thread/qmutex.cpp
@@ -571,19 +571,26 @@ FreeList *freelist()
return &list;
}
#else
+static QBasicAtomicPointer<FreeList> freeListPtr;
+
FreeList *freelist()
{
- static QAtomicPointer<FreeList> list;
- FreeList *local = list.loadAcquire();
+ FreeList *local = freeListPtr.loadAcquire();
if (!local) {
local = new FreeList;
- if (!list.testAndSetRelease(0, local)) {
+ if (!freeListPtr.testAndSetRelease(0, local)) {
delete local;
- local = list.loadAcquire();
+ local = freeListPtr.loadAcquire();
}
}
return local;
}
+
+static void qFreeListDeleter()
+{
+ delete freeListPtr.load();
+}
+Q_DESTRUCTOR_FUNCTION(qFreeListDeleter)
#endif
}
diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h
index ffefe0b1d1..a0d354acdc 100644
--- a/src/corelib/thread/qthread_p.h
+++ b/src/corelib/thread/qthread_p.h
@@ -276,7 +276,7 @@ public:
QStack<QEventLoop *> eventLoops;
QPostEventList postEventList;
- QThread *thread;
+ QAtomicPointer<QThread> thread;
Qt::HANDLE threadId;
QAtomicPointer<QAbstractEventDispatcher> eventDispatcher;
QVector<void *> tls;
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp
index 4b50936958..c340915d35 100644
--- a/src/corelib/thread/qthread_unix.cpp
+++ b/src/corelib/thread/qthread_unix.cpp
@@ -222,7 +222,7 @@ QThreadData *QThreadData::current(bool createIfNecessary)
data->isAdopted = true;
data->threadId = (Qt::HANDLE)pthread_self();
if (!QCoreApplicationPrivate::theMainThread)
- QCoreApplicationPrivate::theMainThread = data->thread;
+ QCoreApplicationPrivate::theMainThread = data->thread.load();
}
return data;
}
diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp
index 72f04ff7af..1a4b41fee4 100644
--- a/src/corelib/thread/qthread_win.cpp
+++ b/src/corelib/thread/qthread_win.cpp
@@ -121,7 +121,7 @@ QThreadData *QThreadData::current(bool createIfNecessary)
threadData->threadId = reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId()));
if (!QCoreApplicationPrivate::theMainThread) {
- QCoreApplicationPrivate::theMainThread = threadData->thread;
+ QCoreApplicationPrivate::theMainThread = threadData->thread.load();
// TODO: is there a way to reflect the branch's behavior using
// WinRT API?
} else {
diff --git a/src/corelib/thread/qthreadstorage.cpp b/src/corelib/thread/qthreadstorage.cpp
index 05ab01cc54..37892233f3 100644
--- a/src/corelib/thread/qthreadstorage.cpp
+++ b/src/corelib/thread/qthreadstorage.cpp
@@ -121,7 +121,7 @@ void **QThreadStorageData::get() const
DEBUG_MSG("QThreadStorageData: Returning storage %d, data %p, for thread %p",
id,
*v,
- data->thread);
+ data->thread.load());
return *v ? v : 0;
}
@@ -143,7 +143,7 @@ void **QThreadStorageData::set(void *p)
DEBUG_MSG("QThreadStorageData: Deleting previous storage %d, data %p, for thread %p",
id,
value,
- data->thread);
+ data->thread.load());
QMutexLocker locker(&destructorsMutex);
DestructorMap *destr = destructors();
@@ -159,7 +159,7 @@ void **QThreadStorageData::set(void *p)
// store new data
value = p;
- DEBUG_MSG("QThreadStorageData: Set storage %d for thread %p to %p", id, data->thread, p);
+ DEBUG_MSG("QThreadStorageData: Set storage %d for thread %p to %p", id, data->thread.load(), p);
return &value;
}
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index 0d7225eea0..4854ceb5ca 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -3123,6 +3123,7 @@ QTimeZone QDateTime::timeZone() const
case Qt::UTC:
return QTimeZone::utc();
case Qt::OffsetFromUTC:
+ return QTimeZone(d->m_offsetFromUtc);
case Qt::TimeZone:
Q_ASSERT(d->m_timeZone.isValid());
return d->m_timeZone;
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 643378a7bd..7829317d1f 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -1244,13 +1244,13 @@ inline bool QByteArray::operator==(const QString &s) const
inline bool QByteArray::operator!=(const QString &s) const
{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) != 0; }
inline bool QByteArray::operator<(const QString &s) const
-{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) < 0; }
-inline bool QByteArray::operator>(const QString &s) const
{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) > 0; }
+inline bool QByteArray::operator>(const QString &s) const
+{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) < 0; }
inline bool QByteArray::operator<=(const QString &s) const
-{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) <= 0; }
-inline bool QByteArray::operator>=(const QString &s) const
{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) >= 0; }
+inline bool QByteArray::operator>=(const QString &s) const
+{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) <= 0; }
#endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
#ifndef QT_NO_CAST_TO_ASCII
diff --git a/src/corelib/tools/qstringalgorithms_p.h b/src/corelib/tools/qstringalgorithms_p.h
index 65901b0286..a12874f567 100644
--- a/src/corelib/tools/qstringalgorithms_p.h
+++ b/src/corelib/tools/qstringalgorithms_p.h
@@ -101,8 +101,6 @@ template <typename StringType> struct QStringAlgorithms
if (begin == str.cbegin() && end == str.cend())
return str;
- if (begin == end)
- return StringType();
if (!isConst && str.isDetached())
return trimmed_helper_inplace(str, begin, end);
return StringType(begin, end - begin);
diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp
index 618352d363..0ef587f333 100644
--- a/src/gui/image/qimagereader.cpp
+++ b/src/gui/image/qimagereader.cpp
@@ -1171,7 +1171,7 @@ QImageIOHandler::Transformations QImageReader::transformation() const
Determines that images returned by read() should have transformation metadata automatically
applied if \a enabled is \c true.
- \sa autoTransform(), read()
+ \sa autoTransform(), transformation(), read()
*/
void QImageReader::setAutoTransform(bool enabled)
{
diff --git a/src/gui/image/qppmhandler.cpp b/src/gui/image/qppmhandler.cpp
index 0f4256b740..f460431c2b 100644
--- a/src/gui/image/qppmhandler.cpp
+++ b/src/gui/image/qppmhandler.cpp
@@ -182,7 +182,8 @@ static bool read_pbm_body(QIODevice *device, char type, int w, int h, int mcc, Q
} else { // read ascii data
uchar *p;
int n;
- for (y=0; y<h; y++) {
+ char buf;
+ for (y = 0; (y < h) && (device->peek(&buf, 1) == 1); y++) {
p = outImage->scanLine(y);
n = pbm_bpl;
if (nbits == 1) {
diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp
index dbf2b3c21f..c25f3c2665 100644
--- a/src/gui/kernel/qcursor.cpp
+++ b/src/gui/kernel/qcursor.cpp
@@ -393,7 +393,7 @@ QCursor::QCursor(const QPixmap &pixmap, int hotX, int hotY)
bmm.fill(Qt::color1);
}
- d = QCursorData::setBitmap(bm, bmm, hotX, hotY);
+ d = QCursorData::setBitmap(bm, bmm, hotX, hotY, pixmap.devicePixelRatio());
d->pixmap = pixmap;
}
@@ -436,7 +436,7 @@ QCursor::QCursor(const QPixmap &pixmap, int hotX, int hotY)
QCursor::QCursor(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY)
: d(0)
{
- d = QCursorData::setBitmap(bitmap, mask, hotX, hotY);
+ d = QCursorData::setBitmap(bitmap, mask, hotX, hotY, 1.0);
}
/*!
@@ -656,7 +656,7 @@ void QCursorData::initialize()
QCursorData::initialized = true;
}
-QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY)
+QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY, qreal devicePixelRatio)
{
if (!QCursorData::initialized)
QCursorData::initialize();
@@ -670,8 +670,8 @@ QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask,
d->bm = new QBitmap(bitmap);
d->bmm = new QBitmap(mask);
d->cshape = Qt::BitmapCursor;
- d->hx = hotX >= 0 ? hotX : bitmap.width() / 2;
- d->hy = hotY >= 0 ? hotY : bitmap.height() / 2;
+ d->hx = hotX >= 0 ? hotX : bitmap.width() / 2 / devicePixelRatio;
+ d->hy = hotY >= 0 ? hotY : bitmap.height() / 2 / devicePixelRatio;
return d;
}
diff --git a/src/gui/kernel/qcursor_p.h b/src/gui/kernel/qcursor_p.h
index 0aaa62b891..188ea387b3 100644
--- a/src/gui/kernel/qcursor_p.h
+++ b/src/gui/kernel/qcursor_p.h
@@ -70,7 +70,8 @@ public:
short hx, hy;
static bool initialized;
void update();
- static QCursorData *setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY);
+ static QCursorData *setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY,
+ qreal devicePixelRatio);
};
extern QCursorData *qt_cursorTable[Qt::LastCursor + 1]; // qcursor.cpp
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 710aa714b7..b309f67866 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -1131,7 +1131,7 @@ void QGuiApplicationPrivate::createPlatformIntegration()
QHighDpiScaling::initHighDpiScaling();
// Load the platform integration
- QString platformPluginPath = QLatin1String(qgetenv("QT_QPA_PLATFORM_PLUGIN_PATH"));
+ QString platformPluginPath = QString::fromLocal8Bit(qgetenv("QT_QPA_PLATFORM_PLUGIN_PATH"));
QByteArray platformName;
@@ -1161,7 +1161,7 @@ void QGuiApplicationPrivate::createPlatformIntegration()
arg.remove(0, 1);
if (arg == "-platformpluginpath") {
if (++i < argc)
- platformPluginPath = QLatin1String(argv[i]);
+ platformPluginPath = QString::fromLocal8Bit(argv[i]);
} else if (arg == "-platform") {
if (++i < argc)
platformName = argv[i];
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index 89bd119564..d4edc0fca1 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -1271,8 +1271,11 @@ void QWindow::setMinimumSize(const QSize &size)
*/
void QWindow::setX(int arg)
{
+ Q_D(QWindow);
if (x() != arg)
setGeometry(QRect(arg, y(), width(), height()));
+ else
+ d->positionAutomatic = false;
}
/*!
@@ -1281,8 +1284,11 @@ void QWindow::setX(int arg)
*/
void QWindow::setY(int arg)
{
+ Q_D(QWindow);
if (y() != arg)
setGeometry(QRect(x(), arg, width(), height()));
+ else
+ d->positionAutomatic = false;
}
/*!
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
index faa1ff8068..09e6e2deb8 100644
--- a/src/gui/kernel/qwindowsysteminterface.cpp
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
@@ -232,6 +232,7 @@ bool QWindowSystemInterface::tryHandleShortcutOverrideEvent(QWindow *w, QKeyEven
{
#ifndef QT_NO_SHORTCUT
Q_ASSERT(ev->type() == QKeyEvent::ShortcutOverride);
+ QGuiApplicationPrivate::modifier_buttons = ev->modifiers();
QObject *focus = w->focusObject();
if (!focus)
diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp
index eb7c7f4b7a..9d363dc895 100644
--- a/src/gui/math3d/qmatrix4x4.cpp
+++ b/src/gui/math3d/qmatrix4x4.cpp
@@ -148,8 +148,6 @@ QMatrix4x4::QMatrix4x4(const float *values)
top-most 4 rows of \a matrix. If \a matrix has less than 4 columns
or rows, the remaining elements are filled with elements from the
identity matrix.
-
- \sa QMatrix4x4(const QGenericMatrix &)
*/
/*!
diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp
index 0e162713ce..e0ef7c52a5 100644
--- a/src/gui/opengl/qopenglframebufferobject.cpp
+++ b/src/gui/opengl/qopenglframebufferobject.cpp
@@ -43,6 +43,7 @@
#include <qwindow.h>
#include <qlibrary.h>
#include <qimage.h>
+#include <QtCore/qbytearray.h>
QT_BEGIN_NAMESPACE
@@ -1275,9 +1276,19 @@ static inline QImage qt_gl_read_framebuffer_rgba8(const QSize &size, bool includ
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
// Without GL_UNSIGNED_INT_8_8_8_8_REV, GL_BGRA only makes sense on little endian.
- const bool supports_bgra = context->isOpenGLES()
- ? context->hasExtension(QByteArrayLiteral("GL_EXT_read_format_bgra"))
- : context->hasExtension(QByteArrayLiteral("GL_EXT_bgra"));
+ const bool has_bgra_ext = context->isOpenGLES()
+ ? context->hasExtension(QByteArrayLiteral("GL_EXT_read_format_bgra"))
+ : context->hasExtension(QByteArrayLiteral("GL_EXT_bgra"));
+
+ const char *renderer = reinterpret_cast<const char *>(funcs->glGetString(GL_RENDERER));
+ const char *ver = reinterpret_cast<const char *>(funcs->glGetString(GL_VERSION));
+
+ // Blacklist PowerVR Rogue G6200 as it has problems with its BGRA support.
+ const bool blackListed = (qstrcmp(renderer, "PowerVR Rogue G6200") == 0
+ && ::strstr(ver, "1.3") != 0);
+
+ const bool supports_bgra = has_bgra_ext && !blackListed;
+
if (supports_bgra) {
QImage img(size, include_alpha ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32);
funcs->glReadPixels(0, 0, w, h, GL_BGRA, GL_UNSIGNED_BYTE, img.bits());
diff --git a/src/gui/painting/qcosmeticstroker.cpp b/src/gui/painting/qcosmeticstroker.cpp
index 61d57ca3f8..8c3fd2ce4f 100644
--- a/src/gui/painting/qcosmeticstroker.cpp
+++ b/src/gui/painting/qcosmeticstroker.cpp
@@ -720,10 +720,11 @@ static inline void capAdjust(int caps, int &x1, int &x2, int &y, int yinc)
template<DrawPixel drawPixel, class Dasher>
static bool drawLine(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2, qreal ry2, int caps)
{
+ bool didDraw = qAbs(rx2 - rx1) + qAbs(ry2 - ry1) >= 1.0;
+
if (stroker->clipLine(rx1, ry1, rx2, ry2))
return true;
- bool didDraw = false;
const int half = stroker->legacyRounding ? 31 : 0;
int x1 = toF26Dot6(rx1) + half;
int y1 = toF26Dot6(ry1) + half;
diff --git a/src/gui/painting/qpdfwriter.cpp b/src/gui/painting/qpdfwriter.cpp
index ca411ebe08..a8c1d8297c 100644
--- a/src/gui/painting/qpdfwriter.cpp
+++ b/src/gui/painting/qpdfwriter.cpp
@@ -151,7 +151,8 @@ QPdfWriter::QPdfWriter(const QString &filename)
Constructs a PDF writer that will write the pdf to \a device.
*/
QPdfWriter::QPdfWriter(QIODevice *device)
- : QObject(*new QPdfWriterPrivate)
+ : QObject(*new QPdfWriterPrivate),
+ QPagedPaintDevice(new QPdfPagedPaintDevicePrivate(d_func()))
{
Q_D(QPdfWriter);
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index c2d986ef3d..e6f1918da8 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -888,8 +888,13 @@ void QHttpNetworkConnectionPrivate::removeReply(QHttpNetworkReply *reply)
// if HTTP mandates we should close
// or the reply is not finished yet, e.g. it was aborted
// we have to close that connection
- if (reply->d_func()->isConnectionCloseEnabled() || !reply->isFinished())
- channels[i].close();
+ if (reply->d_func()->isConnectionCloseEnabled() || !reply->isFinished()) {
+ if (reply->isAborted()) {
+ channels[i].abort();
+ } else {
+ channels[i].close();
+ }
+ }
QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
return;
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index 8980ed7a41..293909c914 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -205,6 +205,26 @@ void QHttpNetworkConnectionChannel::close()
}
+void QHttpNetworkConnectionChannel::abort()
+{
+ 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;
+
+ if (socket) {
+ // socket can be 0 since the host lookup is done from qhttpnetworkconnection.cpp while
+ // there is no socket yet.
+ socket->abort();
+ }
+}
+
+
bool QHttpNetworkConnectionChannel::sendRequest()
{
Q_ASSERT(!protocolHandler.isNull());
@@ -1080,6 +1100,8 @@ void QHttpNetworkConnectionChannel::_q_sslErrors(const QList<QSslError> &errors)
connection->d_func()->pauseConnection();
if (pendingEncrypt && !reply)
connection->d_func()->dequeueRequest(socket);
+ if (reply) // a reply was actually dequeued.
+ reply->d_func()->connectionChannel = this; // set correct channel like in sendRequest() and queueRequest();
if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP) {
if (reply)
emit reply->sslErrors(errors);
diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h
index 37ad6c9b0a..87329b7397 100644
--- a/src/network/access/qhttpnetworkconnectionchannel_p.h
+++ b/src/network/access/qhttpnetworkconnectionchannel_p.h
@@ -157,6 +157,7 @@ public:
void init();
void close();
+ void abort();
bool sendRequest();
diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp
index dd108ad5c7..a0f05523e3 100644
--- a/src/network/access/qhttpnetworkreply.cpp
+++ b/src/network/access/qhttpnetworkreply.cpp
@@ -264,6 +264,17 @@ char* QHttpNetworkReply::userProvidedDownloadBuffer()
return d->userProvidedDownloadBuffer;
}
+void QHttpNetworkReply::abort()
+{
+ Q_D(QHttpNetworkReply);
+ d->state = QHttpNetworkReplyPrivate::Aborted;
+}
+
+bool QHttpNetworkReply::isAborted() const
+{
+ return d_func()->state == QHttpNetworkReplyPrivate::Aborted;
+}
+
bool QHttpNetworkReply::isFinished() const
{
return d_func()->state == QHttpNetworkReplyPrivate::AllDoneState;
diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h
index 6e81663500..e8ed73fdac 100644
--- a/src/network/access/qhttpnetworkreply_p.h
+++ b/src/network/access/qhttpnetworkreply_p.h
@@ -121,6 +121,9 @@ public:
void setUserProvidedDownloadBuffer(char*);
char* userProvidedDownloadBuffer();
+ void abort();
+
+ bool isAborted() const;
bool isFinished() const;
bool isPipeliningUsed() const;
@@ -214,7 +217,8 @@ public:
SPDYSYNSent,
SPDYUploading,
SPDYHalfClosed,
- SPDYClosed
+ SPDYClosed,
+ Aborted
} state;
QHttpNetworkRequest request;
diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp
index 3fc4fa9dee..c07064fd94 100644
--- a/src/network/access/qhttpthreaddelegate.cpp
+++ b/src/network/access/qhttpthreaddelegate.cpp
@@ -396,6 +396,7 @@ void QHttpThreadDelegate::abortRequest()
qDebug() << "QHttpThreadDelegate::abortRequest() thread=" << QThread::currentThreadId() << "sync=" << synchronous;
#endif
if (httpReply) {
+ httpReply->abort();
delete httpReply;
httpReply = 0;
}
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index e6fb1a09a0..7147823309 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -278,7 +278,8 @@ static void ensureInitialized()
\snippet code/src_network_access_qnetworkaccessmanager.cpp 4
- Network requests can be reenabled again by calling
+ Network requests can be re-enabled again, and this property will resume to
+ reflect the actual device state by calling
\snippet code/src_network_access_qnetworkaccessmanager.cpp 5
@@ -467,16 +468,12 @@ QNetworkAccessManager::QNetworkAccessManager(QObject *parent)
#ifndef QT_NO_BEARERMANAGEMENT
Q_D(QNetworkAccessManager);
- if (!d->networkSessionRequired) {
- // if a session is required, we track online state through
- // the QNetworkSession's signals
- connect(&d->networkConfigurationManager, SIGNAL(onlineStateChanged(bool)),
- SLOT(_q_onlineStateChanged(bool)));
- }
- // we would need all active configurations to check for
- // d->networkConfigurationManager.isOnline(), which is asynchronous
- // and potentially expensive. We can just check the configuration here
- d->online = (d->networkConfiguration.state() & QNetworkConfiguration::Active);
+ // if a session is required, we track online state through
+ // the QNetworkSession's signals if a request is already made.
+ // we need to track current accessibility state by default
+ //
+ connect(&d->networkConfigurationManager, SIGNAL(onlineStateChanged(bool)),
+ SLOT(_q_onlineStateChanged(bool)));
#endif
}
@@ -946,7 +943,8 @@ QNetworkConfiguration QNetworkAccessManager::activeConfiguration() const
void QNetworkAccessManager::setNetworkAccessible(QNetworkAccessManager::NetworkAccessibility accessible)
{
Q_D(QNetworkAccessManager);
- d->defaultAccessControl = false;
+
+ d->defaultAccessControl = accessible == NotAccessible ? false : true;
if (d->networkAccessible != accessible) {
NetworkAccessibility previous = networkAccessible();
@@ -965,6 +963,10 @@ void QNetworkAccessManager::setNetworkAccessible(QNetworkAccessManager::NetworkA
QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccessible() const
{
Q_D(const QNetworkAccessManager);
+
+ if (d->networkConfiguration.state().testFlag(QNetworkConfiguration::Undefined))
+ return UnknownAccessibility;
+
if (d->networkSessionRequired) {
QSharedPointer<QNetworkSession> networkSession(d->getNetworkSession());
if (networkSession) {
@@ -1622,32 +1624,56 @@ void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession
if (online) {
if (state != QNetworkSession::Connected && state != QNetworkSession::Roaming) {
online = false;
- networkAccessible = QNetworkAccessManager::NotAccessible;
- emit q->networkAccessibleChanged(networkAccessible);
+ if (networkAccessible != QNetworkAccessManager::NotAccessible) {
+ networkAccessible = QNetworkAccessManager::NotAccessible;
+ emit q->networkAccessibleChanged(networkAccessible);
+ }
}
} else {
if (state == QNetworkSession::Connected || state == QNetworkSession::Roaming) {
online = true;
if (defaultAccessControl)
- networkAccessible = QNetworkAccessManager::Accessible;
- emit q->networkAccessibleChanged(networkAccessible);
+ if (networkAccessible != QNetworkAccessManager::Accessible) {
+ networkAccessible = QNetworkAccessManager::Accessible;
+ emit q->networkAccessibleChanged(networkAccessible);
+ }
}
}
}
void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline)
{
- // if the user set a config, we only care whether this one is active.
+ Q_Q(QNetworkAccessManager);
+ // if the user set a config, we only care whether this one is active.
// Otherwise, this QNAM is online if there is an online config.
if (customNetworkConfiguration) {
online = (networkConfiguration.state() & QNetworkConfiguration::Active);
} else {
- if (isOnline && online != isOnline) {
- networkSessionStrongRef.clear();
- networkSessionWeakRef.clear();
+ if (online != isOnline) {
+ if (isOnline) {
+ networkSessionStrongRef.clear();
+ networkSessionWeakRef.clear();
+ }
+ online = isOnline;
+ }
+ }
+ if (online) {
+ if (defaultAccessControl) {
+ if (networkAccessible != QNetworkAccessManager::Accessible) {
+ networkAccessible = QNetworkAccessManager::Accessible;
+ emit q->networkAccessibleChanged(networkAccessible);
+ }
+ }
+ } else if (networkConfiguration.state().testFlag(QNetworkConfiguration::Undefined)) {
+ if (networkAccessible != QNetworkAccessManager::UnknownAccessibility) {
+ networkAccessible = QNetworkAccessManager::UnknownAccessibility;
+ emit q->networkAccessibleChanged(networkAccessible);
+ }
+ } else {
+ if (networkAccessible != QNetworkAccessManager::NotAccessible) {
+ networkAccessible = QNetworkAccessManager::NotAccessible;
+ emit q->networkAccessibleChanged(networkAccessible);
}
-
- online = isOnline;
}
}
diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h
index c715da00c1..54ae114581 100644
--- a/src/network/access/qnetworkaccessmanager_p.h
+++ b/src/network/access/qnetworkaccessmanager_p.h
@@ -78,7 +78,6 @@ public:
customNetworkConfiguration(false),
networkSessionRequired(networkConfigurationManager.capabilities()
& QNetworkConfigurationManager::NetworkSessionRequired),
- networkAccessible(QNetworkAccessManager::Accessible),
activeReplyCount(0),
online(false),
initializeSession(true),
@@ -86,7 +85,18 @@ public:
cookieJarCreated(false),
defaultAccessControl(true),
authenticationManager(QSharedPointer<QNetworkAccessAuthenticationManager>::create())
- { }
+ {
+#ifndef QT_NO_BEARERMANAGEMENT
+ // we would need all active configurations to check for
+ // d->networkConfigurationManager.isOnline(), which is asynchronous
+ // and potentially expensive. We can just check the configuration here
+ online = (networkConfiguration.state().testFlag(QNetworkConfiguration::Active));
+ if (online)
+ networkAccessible = QNetworkAccessManager::Accessible;
+ else
+ networkAccessible = QNetworkAccessManager::NotAccessible;
+#endif
+ }
~QNetworkAccessManagerPrivate();
void _q_replyFinished();
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index 8c0c098147..63fca2bda2 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -1238,7 +1238,7 @@ void QNetworkReplyHttpImplPrivate::replyDownloadMetaData
if (statusCode == 304) {
#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
- qDebug() << "Received a 304 from" << url();
+ qDebug() << "Received a 304 from" << request.url();
#endif
QAbstractNetworkCache *nc = managerPrivate->networkCache;
if (nc) {
@@ -1562,7 +1562,7 @@ QNetworkCacheMetaData QNetworkReplyHttpImplPrivate::fetchCacheMetaData(const QNe
}
#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
- QByteArray n = rawHeader(header);
+ QByteArray n = q->rawHeader(header);
QByteArray o;
if (it != cacheHeaders.rawHeaders.constEnd())
o = (*it).second;
@@ -1782,6 +1782,11 @@ void QNetworkReplyHttpImplPrivate::_q_startOperation()
QMetaObject::invokeMethod(q, "_q_finished", synchronous ? Qt::DirectConnection : Qt::QueuedConnection);
return;
#endif
+ } else {
+#ifndef QT_NO_BEARERMANAGEMENT
+ QObject::connect(session.data(), SIGNAL(stateChanged(QNetworkSession::State)),
+ q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection);
+#endif
}
if (synchronous) {
@@ -1950,6 +1955,16 @@ void QNetworkReplyHttpImplPrivate::_q_networkSessionConnected()
}
}
+void QNetworkReplyHttpImplPrivate::_q_networkSessionStateChanged(QNetworkSession::State sessionState)
+{
+ if (sessionState == QNetworkSession::Disconnected
+ && (state != Idle || state != Reconnecting)) {
+ error(QNetworkReplyImpl::NetworkSessionFailedError,
+ QCoreApplication::translate("QNetworkReply", "Network session error."));
+ finished();
+ }
+}
+
void QNetworkReplyHttpImplPrivate::_q_networkSessionFailed()
{
// Abort waiting and working replies.
diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h
index fff88f8f2d..44d51d82a4 100644
--- a/src/network/access/qnetworkreplyhttpimpl_p.h
+++ b/src/network/access/qnetworkreplyhttpimpl_p.h
@@ -96,6 +96,7 @@ public:
#ifndef QT_NO_BEARERMANAGEMENT
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionConnected())
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed())
+ Q_PRIVATE_SLOT(d_func(), void _q_networkSessionStateChanged(QNetworkSession::State))
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies))
#endif
Q_PRIVATE_SLOT(d_func(), void _q_finished())
@@ -171,6 +172,7 @@ public:
#ifndef QT_NO_BEARERMANAGEMENT
void _q_networkSessionConnected();
void _q_networkSessionFailed();
+ void _q_networkSessionStateChanged(QNetworkSession::State);
void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies);
#endif
void _q_finished();
diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp
index a73e0ea75e..c73e6162d1 100644
--- a/src/network/access/qnetworkreplyimpl.cpp
+++ b/src/network/access/qnetworkreplyimpl.cpp
@@ -125,6 +125,11 @@ void QNetworkReplyImplPrivate::_q_startOperation()
finished();
#endif
return;
+ } else {
+#ifndef QT_NO_BEARERMANAGEMENT
+ QObject::connect(session.data(), SIGNAL(stateChanged(QNetworkSession::State)),
+ q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection);
+#endif
}
#ifndef QT_NO_BEARERMANAGEMENT
@@ -309,6 +314,16 @@ void QNetworkReplyImplPrivate::_q_networkSessionConnected()
}
}
+void QNetworkReplyImplPrivate::_q_networkSessionStateChanged(QNetworkSession::State sessionState)
+{
+ if (sessionState == QNetworkSession::Disconnected
+ && (state != Idle || state != Reconnecting)) {
+ error(QNetworkReplyImpl::NetworkSessionFailedError,
+ QCoreApplication::translate("QNetworkReply", "Network session error."));
+ finished();
+ }
+}
+
void QNetworkReplyImplPrivate::_q_networkSessionFailed()
{
// Abort waiting and working replies.
diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h
index 3e720ef597..209bf40b72 100644
--- a/src/network/access/qnetworkreplyimpl_p.h
+++ b/src/network/access/qnetworkreplyimpl_p.h
@@ -89,6 +89,7 @@ public:
#ifndef QT_NO_BEARERMANAGEMENT
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionConnected())
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed())
+ Q_PRIVATE_SLOT(d_func(), void _q_networkSessionStateChanged(QNetworkSession::State))
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies))
#endif
@@ -122,6 +123,7 @@ public:
#ifndef QT_NO_BEARERMANAGEMENT
void _q_networkSessionConnected();
void _q_networkSessionFailed();
+ void _q_networkSessionStateChanged(QNetworkSession::State);
void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies);
#endif
diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp
index abb47e9e29..d626d0bcfc 100644
--- a/src/network/kernel/qauthenticator.cpp
+++ b/src/network/kernel/qauthenticator.cpp
@@ -85,6 +85,7 @@ static QByteArray qNtlmPhase3_SSPI(QAuthenticatorPrivate *ctx, const QByteArray&
\li Digest-MD5
\endlist
+ \target qauthenticator-options
\section1 Options
In addition to the username and password required for authentication, a
@@ -104,8 +105,8 @@ static QByteArray qNtlmPhase3_SSPI(QAuthenticatorPrivate *ctx, const QByteArray&
\section2 Basic
\table
- \header \li Option \li Direction \li Description
- \row \li \tt{realm} \li Incoming \li Contains the realm of the authentication, the same as realm()
+ \header \li Option \li Direction \li Type \li Description
+ \row \li \tt{realm} \li Incoming \li QString \li Contains the realm of the authentication, the same as realm()
\endtable
The Basic authentication mechanism supports no outgoing options.
@@ -119,8 +120,8 @@ static QByteArray qNtlmPhase3_SSPI(QAuthenticatorPrivate *ctx, const QByteArray&
\section2 Digest-MD5
\table
- \header \li Option \li Direction \li Description
- \row \li \tt{realm} \li Incoming \li Contains the realm of the authentication, the same as realm()
+ \header \li Option \li Direction \li Type \li Description
+ \row \li \tt{realm} \li Incoming \li QString \li Contains the realm of the authentication, the same as realm()
\endtable
The Digest-MD5 authentication mechanism supports no outgoing options.
@@ -130,7 +131,7 @@ static QByteArray qNtlmPhase3_SSPI(QAuthenticatorPrivate *ctx, const QByteArray&
/*!
- Constructs an empty authentication object
+ Constructs an empty authentication object.
*/
QAuthenticator::QAuthenticator()
: d(0)
@@ -138,7 +139,7 @@ QAuthenticator::QAuthenticator()
}
/*!
- Destructs the object
+ Destructs the object.
*/
QAuthenticator::~QAuthenticator()
{
@@ -207,7 +208,7 @@ bool QAuthenticator::operator==(const QAuthenticator &other) const
*/
/*!
- returns the user used for authentication.
+ Returns the user used for authentication.
*/
QString QAuthenticator::user() const
{
@@ -227,7 +228,7 @@ void QAuthenticator::setUser(const QString &user)
}
/*!
- returns the password used for authentication.
+ Returns the password used for authentication.
*/
QString QAuthenticator::password() const
{
@@ -260,7 +261,7 @@ void QAuthenticator::detach()
}
/*!
- returns the realm requiring authentication.
+ Returns the realm requiring authentication.
*/
QString QAuthenticator::realm() const
{
@@ -279,10 +280,11 @@ void QAuthenticator::setRealm(const QString &realm)
/*!
\since 4.7
Returns the value related to option \a opt if it was set by the server.
- See \l{QAuthenticator#Options} for more information on incoming options.
+ See the \l{QAuthenticator#qauthenticator-options}{Options section} for
+ more information on incoming options.
If option \a opt isn't found, an invalid QVariant will be returned.
- \sa options(), QAuthenticator#Options
+ \sa options(), {QAuthenticator#qauthenticator-options}{QAuthenticator options}
*/
QVariant QAuthenticator::option(const QString &opt) const
{
@@ -292,10 +294,10 @@ QVariant QAuthenticator::option(const QString &opt) const
/*!
\since 4.7
Returns all incoming options set in this QAuthenticator object by parsing
- the server reply. See \l{QAuthenticator#Options} for more information
- on incoming options.
+ the server reply. See the \l{QAuthenticator#qauthenticator-options}{Options section}
+ for more information on incoming options.
- \sa option(), QAuthenticator#Options
+ \sa option(), {QAuthenticator#qauthenticator-options}{QAuthenticator options}
*/
QVariantHash QAuthenticator::options() const
{
@@ -306,9 +308,9 @@ QVariantHash QAuthenticator::options() const
\since 4.7
Sets the outgoing option \a opt to value \a value.
- See \l{QAuthenticator#Options} for more information on outgoing options.
+ See the \l{QAuthenticator#qauthenticator-options}{Options section} for more information on outgoing options.
- \sa options(), option(), QAuthenticator#Options
+ \sa options(), option(), {QAuthenticator#qauthenticator-options}{QAuthenticator options}
*/
void QAuthenticator::setOption(const QString &opt, const QVariant &value)
{
@@ -318,7 +320,10 @@ void QAuthenticator::setOption(const QString &opt, const QVariant &value)
/*!
- Returns \c true if the authenticator is null.
+ Returns \c true if the object has not been initialized. Returns
+ \c false if non-const member functions have been called, or
+ the content was constructed or copied from another initialized
+ QAuthenticator object.
*/
bool QAuthenticator::isNull() const
{
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index 02147d2054..e344a9d17e 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -745,15 +745,9 @@ bool QAbstractSocketPrivate::canReadNotification()
return true;
}
- if (socketEngine) {
- // turn the socket engine off if we've either:
- // - got pending datagrams
- // - reached the buffer size limit
- if (isBuffered)
- socketEngine->setReadNotificationEnabled(readBufferMaxSize == 0 || readBufferMaxSize > q->bytesAvailable());
- else if (socketType != QAbstractSocket::TcpSocket)
- socketEngine->setReadNotificationEnabled(!socketEngine->hasPendingDatagrams());
- }
+ // turn the socket engine off if we've reached the buffer size limit
+ if (socketEngine && isBuffered)
+ socketEngine->setReadNotificationEnabled(readBufferMaxSize == 0 || readBufferMaxSize > q->bytesAvailable());
// reset the read socket notifier state if we reentered inside the
// readyRead() connected slot.
diff --git a/src/network/socket/qlocalserver_unix.cpp b/src/network/socket/qlocalserver_unix.cpp
index ef10b1e68d..634074d91f 100644
--- a/src/network/socket/qlocalserver_unix.cpp
+++ b/src/network/socket/qlocalserver_unix.cpp
@@ -85,7 +85,8 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName)
}
serverName = requestedServerName;
- QString tempPath;
+ QByteArray encodedTempPath;
+ const QByteArray encodedFullServerName = QFile::encodeName(fullServerName);
QScopedPointer<QTemporaryDir> tempDir;
// Check any of the flags
@@ -96,8 +97,7 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName)
setError(QLatin1String("QLocalServer::listen"));
return false;
}
- tempPath = tempDir->path();
- tempPath += QLatin1String("/s");
+ encodedTempPath = QFile::encodeName(tempDir->path() + QLatin1String("/s"));
}
// create the unix socket
@@ -111,23 +111,23 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName)
// Construct the unix address
struct ::sockaddr_un addr;
addr.sun_family = PF_UNIX;
- if (sizeof(addr.sun_path) < (uint)fullServerName.toLatin1().size() + 1) {
+ if (sizeof(addr.sun_path) < (uint)encodedFullServerName.size() + 1) {
setError(QLatin1String("QLocalServer::listen"));
closeServer();
return false;
}
if (socketOptions & QLocalServer::WorldAccessOption) {
- if (sizeof(addr.sun_path) < (uint)tempPath.toLatin1().size() + 1) {
+ if (sizeof(addr.sun_path) < (uint)encodedTempPath.size() + 1) {
setError(QLatin1String("QLocalServer::listen"));
closeServer();
return false;
}
- ::memcpy(addr.sun_path, tempPath.toLatin1().data(),
- tempPath.toLatin1().size() + 1);
+ ::memcpy(addr.sun_path, encodedTempPath.constData(),
+ encodedTempPath.size() + 1);
} else {
- ::memcpy(addr.sun_path, fullServerName.toLatin1().data(),
- fullServerName.toLatin1().size() + 1);
+ ::memcpy(addr.sun_path, encodedFullServerName.constData(),
+ encodedFullServerName.size() + 1);
}
// bind
@@ -165,13 +165,13 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName)
if (socketOptions & QLocalServer::OtherAccessOption)
mode |= S_IRWXO;
- if (::chmod(tempPath.toLatin1(), mode) == -1) {
+ if (::chmod(encodedTempPath.constData(), mode) == -1) {
setError(QLatin1String("QLocalServer::listen"));
closeServer();
return false;
}
- if (::rename(tempPath.toLatin1(), fullServerName.toLatin1()) == -1) {
+ if (::rename(encodedTempPath.constData(), encodedFullServerName.constData()) == -1) {
setError(QLatin1String("QLocalServer::listen"));
closeServer();
return false;
diff --git a/src/network/socket/qlocalsocket_unix.cpp b/src/network/socket/qlocalsocket_unix.cpp
index 77c5028fb3..bb0f11f038 100644
--- a/src/network/socket/qlocalsocket_unix.cpp
+++ b/src/network/socket/qlocalsocket_unix.cpp
@@ -268,15 +268,16 @@ void QLocalSocketPrivate::_q_connectToSocket()
connectingPathName += QLatin1Char('/') + connectingName;
}
+ const QByteArray encodedConnectingPathName = QFile::encodeName(connectingPathName);
struct sockaddr_un name;
name.sun_family = PF_UNIX;
- if (sizeof(name.sun_path) < (uint)connectingPathName.toLatin1().size() + 1) {
+ if (sizeof(name.sun_path) < (uint)encodedConnectingPathName.size() + 1) {
QString function = QLatin1String("QLocalSocket::connectToServer");
errorOccurred(QLocalSocket::ServerNotFoundError, function);
return;
}
- ::memcpy(name.sun_path, connectingPathName.toLatin1().data(),
- connectingPathName.toLatin1().size() + 1);
+ ::memcpy(name.sun_path, encodedConnectingPathName.constData(),
+ encodedConnectingPathName.size() + 1);
if (-1 == qt_safe_connect(connectingSocket, (struct sockaddr *)&name, sizeof(name))) {
QString function = QLatin1String("QLocalSocket::connectToServer");
switch (errno)
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp
index 0e14c175c5..c40eef769e 100644
--- a/src/network/socket/qnativesocketengine_unix.cpp
+++ b/src/network/socket/qnativesocketengine_unix.cpp
@@ -370,7 +370,7 @@ bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt
int n, level;
convertToLevelAndOption(opt, socketProtocol, level, n);
-#if defined(SO_REUSEPORT)
+#if defined(SO_REUSEPORT) && !defined(Q_OS_LINUX)
if (opt == QNativeSocketEngine::AddressReusable) {
// on OS X, SO_REUSEADDR isn't sufficient to allow multiple binds to the
// same port (which is useful for multicast UDP). SO_REUSEPORT is, but
diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp
index 2e905ad610..9aed0caa25 100644
--- a/src/network/socket/qnativesocketengine_win.cpp
+++ b/src/network/socket/qnativesocketengine_win.cpp
@@ -1070,8 +1070,11 @@ qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const
buf.buf = &c;
buf.len = sizeof(c);
DWORD flags = MSG_PEEK;
- if (::WSARecvFrom(socketDescriptor, &buf, 1, 0, &flags, 0,0,0,0) == SOCKET_ERROR)
- return 0;
+ if (::WSARecvFrom(socketDescriptor, &buf, 1, 0, &flags, 0,0,0,0) == SOCKET_ERROR) {
+ int err = WSAGetLastError();
+ if (err != WSAECONNRESET && err != WSAENETRESET)
+ return 0;
+ }
}
return nbytes;
}
@@ -1099,14 +1102,7 @@ bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const
int err = WSAGetLastError();
if (ret == SOCKET_ERROR && err != WSAEMSGSIZE) {
WS_ERROR_DEBUG(err);
- if (err == WSAECONNRESET || err == WSAENETRESET) {
- // Discard error message to prevent QAbstractSocket from
- // getting this message repeatedly after reenabling the
- // notifiers.
- flags = 0;
- ::WSARecvFrom(socketDescriptor, &buf, 1, &available, &flags,
- &storage.a, &storageSize, 0, 0);
- }
+ result = (err == WSAECONNRESET || err == WSAENETRESET);
} else {
// If there's no error, or if our buffer was too small, there must be
// a pending datagram.
@@ -1159,12 +1155,21 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
if (recvResult != SOCKET_ERROR) {
ret = qint64(bytesRead);
break;
- } else if (recvResult == SOCKET_ERROR && err == WSAEMSGSIZE) {
- bufferCount += 5;
- delete[] buf;
- } else if (recvResult == SOCKET_ERROR) {
- WS_ERROR_DEBUG(err);
- ret = -1;
+ } else {
+ switch (err) {
+ case WSAEMSGSIZE:
+ bufferCount += 5;
+ delete[] buf;
+ continue;
+ case WSAECONNRESET:
+ case WSAENETRESET:
+ ret = 0;
+ break;
+ default:
+ WS_ERROR_DEBUG(err);
+ ret = -1;
+ break;
+ }
break;
}
}
diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp
index 025e3e5017..44de7f8526 100644
--- a/src/network/socket/qnativesocketengine_winrt.cpp
+++ b/src/network/socket/qnativesocketengine_winrt.cpp
@@ -285,23 +285,11 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port)
return false;
}
d->socketState = QAbstractSocket::ConnectingState;
- hr = QWinRTFunctions::await(d->connectOp);
- RETURN_FALSE_IF_FAILED("Connection could not be established");
- bool connectionErrors = false;
- d->handleConnectionErrors(d->connectOp.Get(), &connectionErrors);
- if (connectionErrors)
- return false;
- d->connectOp.Reset();
-
- d->socketState = QAbstractSocket::ConnectedState;
- emit connectionReady();
+ hr = d->connectOp->put_Completed(Callback<IAsyncActionCompletedHandler>(
+ d, &QNativeSocketEnginePrivate::handleConnectToHost).Get());
+ Q_ASSERT_SUCCEEDED(hr);
- // Delay the reader so that the SSL socket can upgrade
- if (d->sslSocket)
- connect(d->sslSocket, SIGNAL(encrypted()), SLOT(establishRead()));
- else
- establishRead();
- return true;
+ return d->socketState == QAbstractSocket::ConnectedState;
}
bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port)
@@ -330,8 +318,7 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port)
return false;
}
- EventRegistrationToken token;
- d->tcpListener->add_ConnectionReceived(Callback<ClientConnectedHandler>(d, &QNativeSocketEnginePrivate::handleClientConnection).Get(), &token);
+ d->tcpListener->add_ConnectionReceived(Callback<ClientConnectedHandler>(d, &QNativeSocketEnginePrivate::handleClientConnection).Get(), &d->connectionToken);
hr = d->tcpListener->BindEndpointAsync(hostAddress.Get(), portString.Get(), &op);
if (FAILED(hr)) {
qErrnoWarning(hr, "Unable to bind socket."); // ### Set error message
@@ -688,6 +675,14 @@ bool QNativeSocketEngine::waitForWrite(int msecs, bool *timedOut)
{
Q_UNUSED(msecs);
Q_UNUSED(timedOut);
+ Q_D(QNativeSocketEngine);
+ if (d->socketState == QAbstractSocket::ConnectingState) {
+ HRESULT hr = QWinRTFunctions::await(d->connectOp, QWinRTFunctions::ProcessMainThreadEvents);
+ if (SUCCEEDED(hr)) {
+ d->handleConnectionEstablished(d->connectOp.Get());
+ return true;
+ }
+ }
return false;
}
@@ -728,7 +723,6 @@ void QNativeSocketEngine::setWriteNotificationEnabled(bool enable)
if (bytesToWrite())
return; // will be emitted as a result of bytes written
writeNotification();
- d->notifyOnWrite = false;
}
}
@@ -785,9 +779,8 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc
qWarning("Failed to create stream socket");
return false;
}
- EventRegistrationToken token;
socketDescriptor = qintptr(socket.Detach());
- udpSocket()->add_MessageReceived(Callback<DatagramReceivedHandler>(this, &QNativeSocketEnginePrivate::handleNewDatagram).Get(), &token);
+ udpSocket()->add_MessageReceived(Callback<DatagramReceivedHandler>(this, &QNativeSocketEnginePrivate::handleNewDatagram).Get(), &connectionToken);
break;
}
default:
@@ -815,11 +808,19 @@ QNativeSocketEnginePrivate::QNativeSocketEnginePrivate()
, closingDown(false)
, socketDescriptor(-1)
, sslSocket(Q_NULLPTR)
+ , connectionToken( { -1 } )
{
}
QNativeSocketEnginePrivate::~QNativeSocketEnginePrivate()
{
+ if (socketDescriptor == -1 || connectionToken.value == -1)
+ return;
+
+ if (socketType == QAbstractSocket::UdpSocket)
+ udpSocket()->remove_MessageReceived(connectionToken);
+ else if (socketType == QAbstractSocket::TcpSocket)
+ tcpListener->remove_ConnectionReceived(connectionToken);
}
void QNativeSocketEnginePrivate::setError(QAbstractSocket::SocketError error, ErrorString errorString) const
@@ -1119,10 +1120,19 @@ HRESULT QNativeSocketEnginePrivate::handleClientConnection(IStreamSocketListener
return S_OK;
}
-void QNativeSocketEnginePrivate::handleConnectionErrors(IAsyncAction *connectAction, bool *errorsOccured)
+HRESULT QNativeSocketEnginePrivate::handleConnectToHost(IAsyncAction *action, AsyncStatus)
+{
+ handleConnectionEstablished(action);
+ return S_OK;
+}
+
+void QNativeSocketEnginePrivate::handleConnectionEstablished(IAsyncAction *action)
{
- bool error = true;
- HRESULT hr = connectAction->GetResults();
+ Q_Q(QNativeSocketEngine);
+ if (wasDeleted || !connectOp) // Protect against a late callback
+ return;
+
+ HRESULT hr = action->GetResults();
switch (hr) {
case 0x8007274c: // A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString);
@@ -1140,13 +1150,32 @@ void QNativeSocketEnginePrivate::handleConnectionErrors(IAsyncAction *connectAct
if (FAILED(hr)) {
setError(QAbstractSocket::UnknownSocketError, UnknownSocketErrorString);
socketState = QAbstractSocket::UnconnectedState;
- } else {
- error = false;
}
break;
}
- if (errorsOccured)
- *errorsOccured = error;
+
+ // The callback might be triggered several times if we do not cancel/reset it here
+ if (connectOp) {
+ ComPtr<IAsyncInfo> info;
+ connectOp.As(&info);
+ if (info) {
+ info->Cancel();
+ info->Close();
+ }
+ connectOp.Reset();
+ }
+
+ socketState = QAbstractSocket::ConnectedState;
+ emit q->connectionReady();
+
+ if (socketType != QAbstractSocket::TcpSocket)
+ return;
+
+ // Delay the reader so that the SSL socket can upgrade
+ if (sslSocket)
+ QObject::connect(qobject_cast<QSslSocket *>(sslSocket), &QSslSocket::encrypted, q, &QNativeSocketEngine::establishRead);
+ else
+ q->establishRead();
}
HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *asyncInfo, AsyncStatus status)
@@ -1166,7 +1195,7 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async
hr = buffer->get_Length(&bufferLength);
Q_ASSERT_SUCCEEDED(hr);
if (!bufferLength) {
- if (q->isReadNotificationEnabled())
+ if (notifyOnRead)
emit q->readReady();
return S_OK;
}
@@ -1190,7 +1219,7 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async
readBytes.seek(readPos);
readMutex.unlock();
- if (q->isReadNotificationEnabled())
+ if (notifyOnRead)
emit q->readReady();
ComPtr<IInputStream> stream;
diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h
index 4286ff6373..912b7db973 100644
--- a/src/network/socket/qnativesocketengine_winrt_p.h
+++ b/src/network/socket/qnativesocketengine_winrt_p.h
@@ -207,13 +207,15 @@ private:
QList<ABI::Windows::Networking::Sockets::IStreamSocket *> currentConnections;
QEventLoop eventLoop;
QAbstractSocket *sslSocket;
+ EventRegistrationToken connectionToken;
HRESULT handleBindCompleted(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus);
HRESULT handleNewDatagram(ABI::Windows::Networking::Sockets::IDatagramSocket *socket,
ABI::Windows::Networking::Sockets::IDatagramSocketMessageReceivedEventArgs *args);
HRESULT handleClientConnection(ABI::Windows::Networking::Sockets::IStreamSocketListener *tcpListener,
ABI::Windows::Networking::Sockets::IStreamSocketListenerConnectionReceivedEventArgs *args);
- void handleConnectionErrors(ABI::Windows::Foundation::IAsyncAction *connectAction, bool *errorsOccured);
+ HRESULT handleConnectToHost(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus);
+ void handleConnectionEstablished(ABI::Windows::Foundation::IAsyncAction *action);
HRESULT handleReadyRead(ABI::Windows::Foundation::IAsyncOperationWithProgress<ABI::Windows::Storage::Streams::IBuffer *, UINT32> *asyncInfo, ABI::Windows::Foundation::AsyncStatus);
};
diff --git a/src/network/ssl/qsslellipticcurve.cpp b/src/network/ssl/qsslellipticcurve.cpp
index a16f726429..b4396d567b 100644
--- a/src/network/ssl/qsslellipticcurve.cpp
+++ b/src/network/ssl/qsslellipticcurve.cpp
@@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE
elliptic-curve cipher algorithms.
Elliptic curves can be constructed from a "short name" (SN) (fromShortName()),
- and by a call to QSslSocket::supportedEllipticCurves().
+ and by a call to QSslConfiguration::supportedEllipticCurves().
QSslEllipticCurve instances can be compared for equality and can be used as keys
in QHash and QSet. They cannot be used as key in a QMap.
@@ -65,7 +65,7 @@ QT_BEGIN_NAMESPACE
Constructs an invalid elliptic curve.
- \sa isValid(), QSslSocket::supportedEllipticCurves()
+ \sa isValid(), QSslConfiguration::supportedEllipticCurves()
*/
/*!
@@ -136,7 +136,6 @@ QT_BEGIN_NAMESPACE
\relates QSslEllipticCurve
Returns true if the curve \a lhs represents the same curve of \a rhs;
- false otherwise.
*/
/*!
diff --git a/src/network/ssl/qsslpresharedkeyauthenticator.cpp b/src/network/ssl/qsslpresharedkeyauthenticator.cpp
index 4a3b1aa807..ab78aea1cd 100644
--- a/src/network/ssl/qsslpresharedkeyauthenticator.cpp
+++ b/src/network/ssl/qsslpresharedkeyauthenticator.cpp
@@ -257,7 +257,6 @@ int QSslPreSharedKeyAuthenticator::maximumPreSharedKeyLength() const
identity hint, identity, pre shared key, maximum length for the identity
and maximum length for the pre shared key.
- \sa operator!=(const QSslPreSharedKeyAuthenticator &lhs, const QSslPreSharedKeyAuthenticator &rhs)
*/
bool operator==(const QSslPreSharedKeyAuthenticator &lhs, const QSslPreSharedKeyAuthenticator &rhs)
{
@@ -277,7 +276,6 @@ bool operator==(const QSslPreSharedKeyAuthenticator &lhs, const QSslPreSharedKey
Returns true if the authenticator object \a lhs is different than \a rhs;
false otherwise.
- \sa operator==(const QSslPreSharedKeyAuthenticator &lhs, const QSslPreSharedKeyAuthenticator &rhs)
*/
QT_END_NAMESPACE
diff --git a/src/platformsupport/dbusmenu/qdbusplatformmenu.cpp b/src/platformsupport/dbusmenu/qdbusplatformmenu.cpp
index a64e107e71..1dd2b462ed 100644
--- a/src/platformsupport/dbusmenu/qdbusplatformmenu.cpp
+++ b/src/platformsupport/dbusmenu/qdbusplatformmenu.cpp
@@ -59,6 +59,11 @@ QDBusPlatformMenuItem::QDBusPlatformMenuItem(quintptr tag)
menuItemsByID.insert(m_dbusID, this);
}
+QDBusPlatformMenuItem::~QDBusPlatformMenuItem()
+{
+ menuItemsByID.remove(m_dbusID);
+}
+
void QDBusPlatformMenuItem::setTag(quintptr tag)
{
m_tag = tag;
@@ -155,6 +160,7 @@ QDBusPlatformMenu::QDBusPlatformMenu(quintptr tag)
QDBusPlatformMenu::~QDBusPlatformMenu()
{
menusByID.remove(m_dbusID);
+ m_topLevelMenus.removeOne(this);
}
void QDBusPlatformMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before)
diff --git a/src/platformsupport/dbusmenu/qdbusplatformmenu_p.h b/src/platformsupport/dbusmenu/qdbusplatformmenu_p.h
index 16bb4f195c..fdad7990e9 100644
--- a/src/platformsupport/dbusmenu/qdbusplatformmenu_p.h
+++ b/src/platformsupport/dbusmenu/qdbusplatformmenu_p.h
@@ -57,6 +57,7 @@ class QDBusPlatformMenuItem : public QPlatformMenuItem
public:
QDBusPlatformMenuItem(quintptr tag = 0LL);
+ ~QDBusPlatformMenuItem();
quintptr tag()const Q_DECL_OVERRIDE { return m_tag; }
void setTag(quintptr tag) Q_DECL_OVERRIDE;
diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
index 905f7695bb..2de7fb3b40 100644
--- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
+++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
@@ -39,6 +39,10 @@
#include <QtPlatformHeaders/QEGLNativeContext>
#include <QDebug>
+#ifdef Q_OS_ANDROID
+#include <QtCore/private/qjnihelpers_p.h>
+#endif
+
QT_BEGIN_NAMESPACE
/*!
@@ -305,6 +309,14 @@ void QEGLPlatformContext::updateFormatFromGL()
QByteArray version = QByteArray(reinterpret_cast<const char *>(s));
int major, minor;
if (QPlatformOpenGLContext::parseOpenGLVersion(version, major, minor)) {
+#ifdef Q_OS_ANDROID
+ // Some Android 4.2.2 devices report OpenGL ES 3.0 without the functions being available.
+ static int apiLevel = QtAndroidPrivate::androidSdkVersion();
+ if (apiLevel <= 17 && major >= 3) {
+ major = 2;
+ minor = 0;
+ }
+#endif
m_format.setMajorVersion(major);
m_format.setMinorVersion(minor);
}
diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
index cd38498217..a369747a64 100644
--- a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
+++ b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
@@ -243,8 +243,13 @@ void QKdeThemePrivate::refresh()
toolButtonStyle = Qt::ToolButtonTextBesideIcon;
toolBarIconSize = 0;
styleNames.clear();
+ if (kdeVersion >= 5)
+ styleNames << QStringLiteral("breeze");
styleNames << QStringLiteral("Oxygen") << QStringLiteral("fusion") << QStringLiteral("windows");
- iconFallbackThemeName = iconThemeName = QStringLiteral("oxygen");
+ if (kdeVersion >= 5)
+ iconFallbackThemeName = iconThemeName = QStringLiteral("breeze");
+ else
+ iconFallbackThemeName = iconThemeName = QStringLiteral("oxygen");
QHash<QString, QSettings*> kdeSettings;
diff --git a/src/plugins/platforms/cocoa/qcocoacursor.mm b/src/plugins/platforms/cocoa/qcocoacursor.mm
index 2098f0dc8c..8e38181c29 100644
--- a/src/plugins/platforms/cocoa/qcocoacursor.mm
+++ b/src/plugins/platforms/cocoa/qcocoacursor.mm
@@ -303,7 +303,7 @@ NSCursor *QCocoaCursor::createCursorFromPixmap(const QPixmap pixmap, const QPoin
NSImage *nsimage;
if (pixmap.devicePixelRatio() > 1.0) {
QSize layoutSize = pixmap.size() / pixmap.devicePixelRatio();
- QPixmap scaledPixmap = pixmap.scaled(layoutSize);
+ QPixmap scaledPixmap = pixmap.scaled(layoutSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(scaledPixmap));
CGImageRef cgImage = qt_mac_toCGImage(pixmap.toImage());
NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage];
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index 6bec6b191d..229f515995 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -87,9 +87,17 @@ void QCocoaScreen::updateGeometry()
NSRect frameRect = [nsScreen frame];
- if (m_screenIndex == 0) {
+ // Since Mavericks, there is a setting, System Preferences->Mission Control->
+ // Displays have separate Spaces.
+ BOOL spansDisplays = NO;
+#if QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9)
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_9)
+ spansDisplays = [NSScreen screensHaveSeparateSpaces];
+#endif
+ if (spansDisplays || m_screenIndex == 0) {
m_geometry = QRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width, frameRect.size.height);
- // This is the primary screen, the one that contains the menubar. Its origin should be
+ // Displays have separate Spaces setting is on or this is the primary screen,
+ // the one that contains the menubar. Its origin should be
// (0, 0), and it's the only one whose available geometry differs from its full geometry.
NSRect visibleRect = [nsScreen visibleFrame];
m_availableGeometry = QRect(visibleRect.origin.x,
diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm
index 57739f3a58..aa7a09805a 100644
--- a/src/plugins/platforms/cocoa/qcocoamenu.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenu.mm
@@ -463,6 +463,13 @@ void QCocoaMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect,
NSView *view = cocoaWindow ? cocoaWindow->contentView() : nil;
NSMenuItem *nsItem = item ? ((QCocoaMenuItem *)item)->nsItem() : nil;
+ QScreen *screen = 0;
+ if (parentWindow)
+ screen = parentWindow->screen();
+ if (!screen && !QGuiApplication::screens().isEmpty())
+ screen = QGuiApplication::screens().at(0);
+ Q_ASSERT(screen);
+
// Ideally, we would call -popUpMenuPositioningItem:atLocation:inView:.
// However, this showed not to work with modal windows where the menu items
// would appear disabled. So, we resort to a more artisanal solution. Note
@@ -479,6 +486,21 @@ void QCocoaMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect,
[popupCell setTransparent:YES];
[popupCell setMenu:m_nativeMenu];
[popupCell selectItem:nsItem];
+
+ int availableHeight = screen->availableSize().height();
+ const QPoint &globalPos = parentWindow->mapToGlobal(pos);
+ int menuHeight = m_nativeMenu.size.height;
+ if (globalPos.y() + menuHeight > availableHeight) {
+ // Maybe we need to fix the vertical popup position but we don't know the
+ // exact popup height at the moment (and Cocoa is just guessing) nor its
+ // position. So, instead of translating by the popup's full height, we need
+ // to estimate where the menu will show up and translate by the remaining height.
+ float idx = ([m_nativeMenu indexOfItem:nsItem] + 1.0f) / m_nativeMenu.numberOfItems;
+ float heightBelowPos = (1.0 - idx) * menuHeight;
+ if (globalPos.y() + heightBelowPos > availableHeight)
+ pos.setY(pos.y() - globalPos.y() + availableHeight - heightBelowPos);
+ }
+
NSRect cellFrame = NSMakeRect(pos.x(), pos.y(), m_nativeMenu.minimumWidth, 10);
[popupCell performClickWithFrame:cellFrame inView:view];
} else {
@@ -487,22 +509,21 @@ void QCocoaMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect,
if (view) {
// convert coordinates from view to the view's window
nsPos = [view convertPoint:nsPos toView:nil];
- } else if (!QGuiApplication::screens().isEmpty()) {
- QScreen *screen = QGuiApplication::screens().at(0);
+ } else {
nsPos.y = screen->availableVirtualSize().height() - nsPos.y;
}
if (view) {
// Finally, we need to synthesize an event.
NSEvent *menuEvent = [NSEvent mouseEventWithType:NSRightMouseDown
- location:nsPos
- modifierFlags:0
- timestamp:0
- windowNumber:view ? view.window.windowNumber : 0
- context:nil
- eventNumber:0
- clickCount:1
- pressure:1.0];
+ location:nsPos
+ modifierFlags:0
+ timestamp:0
+ windowNumber:view ? view.window.windowNumber : 0
+ context:nil
+ eventNumber:0
+ clickCount:1
+ pressure:1.0];
[NSMenu popUpContextMenu:m_nativeMenu withEvent:menuEvent forView:view];
} else {
[m_nativeMenu popUpMenuPositioningItem:nsItem atLocation:nsPos inView:0];
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 8a8e03d283..6f1e355790 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -799,13 +799,10 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags)
return styleMask;
if ((type & Qt::Popup) == Qt::Popup) {
if (!windowIsPopupType(type)) {
- styleMask = NSUtilityWindowMask;
+ styleMask = NSUtilityWindowMask | NSResizableWindowMask;
if (!(flags & Qt::CustomizeWindowHint)) {
- styleMask |= NSResizableWindowMask | NSClosableWindowMask |
- NSMiniaturizableWindowMask | NSTitledWindowMask;
+ styleMask |= NSClosableWindowMask | NSMiniaturizableWindowMask | NSTitledWindowMask;
} else {
- if (flags & Qt::WindowMaximizeButtonHint)
- styleMask |= NSResizableWindowMask;
if (flags & Qt::WindowTitleHint)
styleMask |= NSTitledWindowMask;
if (flags & Qt::WindowCloseButtonHint)
@@ -1352,6 +1349,9 @@ void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow)
[m_contentView setHidden: YES];
}
+ m_nsWindow.ignoresMouseEvents =
+ (window()->flags() & Qt::WindowTransparentForInput) == Qt::WindowTransparentForInput;
+
const qreal opacity = qt_window_private(window())->opacity;
if (!qFuzzyCompare(opacity, qreal(1.0)))
setOpacity(opacity);
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 7da0c4d402..a4f4c0855b 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -710,8 +710,12 @@ QT_WARNING_POP
// Popups implicitly grap mouse events; forward to the active popup if there is one
if (QCocoaWindow *popup = QCocoaIntegration::instance()->activePopupWindow()) {
- if (QNSView *popupView = popup->qtView())
- targetView = popupView;
+ // Tooltips must be transparent for mouse events
+ // The bug reference is QTBUG-46379
+ if (!popup->m_windowFlags.testFlag(Qt::ToolTip)) {
+ if (QNSView *popupView = popup->qtView())
+ targetView = popupView;
+ }
}
[targetView convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint];
diff --git a/src/plugins/platforms/ios/qiosmenu.h b/src/plugins/platforms/ios/qiosmenu.h
index 4fa0416df7..ec23b55507 100644
--- a/src/plugins/platforms/ios/qiosmenu.h
+++ b/src/plugins/platforms/ios/qiosmenu.h
@@ -62,7 +62,7 @@ public:
void setRole(MenuRole role) Q_DECL_OVERRIDE;
void setCheckable(bool) Q_DECL_OVERRIDE {}
void setChecked(bool) Q_DECL_OVERRIDE {}
- void setShortcut(const QKeySequence&) Q_DECL_OVERRIDE {}
+ void setShortcut(const QKeySequence&) Q_DECL_OVERRIDE;
void setEnabled(bool enabled) Q_DECL_OVERRIDE;
void setIconSize(int) Q_DECL_OVERRIDE {}
@@ -73,6 +73,7 @@ public:
bool m_enabled;
bool m_separator;
QIOSMenu *m_menu;
+ QKeySequence m_shortcut;
private:
QString removeMnemonics(const QString &original);
@@ -134,6 +135,7 @@ private:
void toggleShowUsingUIMenuController(bool show);
void toggleShowUsingUIPickerView(bool show);
QIOSMenuItemList visibleMenuItems() const;
+ QIOSMenuItemList filterFirstResponderActions(const QIOSMenuItemList &menuItems);
void repositionMenu();
};
diff --git a/src/plugins/platforms/ios/qiosmenu.mm b/src/plugins/platforms/ios/qiosmenu.mm
index 045d39e328..7aea3729fd 100644
--- a/src/plugins/platforms/ios/qiosmenu.mm
+++ b/src/plugins/platforms/ios/qiosmenu.mm
@@ -277,6 +277,11 @@ void QIOSMenuItem::setRole(QPlatformMenuItem::MenuRole role)
m_role = role;
}
+void QIOSMenuItem::setShortcut(const QKeySequence &sequence)
+{
+ m_shortcut = sequence;
+}
+
void QIOSMenuItem::setEnabled(bool enabled)
{
m_enabled = enabled;
@@ -364,7 +369,7 @@ void QIOSMenu::syncMenuItem(QPlatformMenuItem *)
switch (m_effectiveMenuType) {
case EditMenu:
- [m_menuController setVisibleMenuItems:visibleMenuItems()];
+ [m_menuController setVisibleMenuItems:filterFirstResponderActions(visibleMenuItems())];
break;
default:
[m_pickerView setVisibleMenuItems:visibleMenuItems() selectItem:m_targetItem];
@@ -469,7 +474,7 @@ void QIOSMenu::toggleShowUsingUIMenuController(bool show)
{
if (show) {
Q_ASSERT(!m_menuController);
- m_menuController = [[QUIMenuController alloc] initWithVisibleMenuItems:visibleMenuItems()];
+ m_menuController = [[QUIMenuController alloc] initWithVisibleMenuItems:filterFirstResponderActions(visibleMenuItems())];
repositionMenu();
connect(qGuiApp->inputMethod(), &QInputMethod::keyboardRectangleChanged, this, &QIOSMenu::repositionMenu);
} else {
@@ -542,6 +547,36 @@ QIOSMenuItemList QIOSMenu::visibleMenuItems() const
return visibleMenuItems;
}
+QIOSMenuItemList QIOSMenu::filterFirstResponderActions(const QIOSMenuItemList &menuItems)
+{
+ // UIResponderStandardEditActions found in first responder will be prepended to the edit
+ // menu automatically (or e.g made available as buttons on the virtual keyboard). So we
+ // filter them out to avoid duplicates, and let first responder handle the actions instead.
+ // In case of QIOSTextResponder, edit actions will be converted to key events that ends up
+ // triggering the shortcuts of the filtered menu items.
+ QIOSMenuItemList filteredMenuItems;
+ UIResponder *responder = [UIResponder currentFirstResponder];
+
+ for (int i = 0; i < menuItems.count(); ++i) {
+ QIOSMenuItem *menuItem = menuItems.at(i);
+ QKeySequence shortcut = menuItem->m_shortcut;
+ if ((shortcut == QKeySequence::Cut && [responder canPerformAction:@selector(cut:) withSender:nil])
+ || (shortcut == QKeySequence::Copy && [responder canPerformAction:@selector(copy:) withSender:nil])
+ || (shortcut == QKeySequence::Paste && [responder canPerformAction:@selector(paste:) withSender:nil])
+ || (shortcut == QKeySequence::Delete && [responder canPerformAction:@selector(delete:) withSender:nil])
+ || (shortcut == QKeySequence::SelectAll && [responder canPerformAction:@selector(selectAll:) withSender:nil])
+ || (shortcut == QKeySequence::Undo && [responder canPerformAction:@selector(undo:) withSender:nil])
+ || (shortcut == QKeySequence::Redo && [responder canPerformAction:@selector(redo:) withSender:nil])
+ || (shortcut == QKeySequence::Bold && [responder canPerformAction:@selector(toggleBoldface:) withSender:nil])
+ || (shortcut == QKeySequence::Italic && [responder canPerformAction:@selector(toggleItalics:) withSender:nil])
+ || (shortcut == QKeySequence::Underline && [responder canPerformAction:@selector(toggleUnderline:) withSender:nil])) {
+ continue;
+ }
+ filteredMenuItems.append(menuItem);
+ }
+ return filteredMenuItems;
+}
+
void QIOSMenu::repositionMenu()
{
switch (m_effectiveMenuType) {
diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm
index e4917593db..b95be7a883 100644
--- a/src/plugins/platforms/ios/qiostextresponder.mm
+++ b/src/plugins/platforms/ios/qiostextresponder.mm
@@ -231,6 +231,9 @@
if (UIView *accessoryView = static_cast<UIView *>(platformData.value(kImePlatformDataInputAccessoryView).value<void *>()))
self.inputAccessoryView = [[[WrapperView alloc] initWithView:accessoryView] autorelease];
+ self.undoManager.groupsByEvent = NO;
+ [self rebuildUndoStack];
+
return self;
}
@@ -346,44 +349,183 @@
- (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];
+ QWindowSystemInterface::handleKeyEvent(qApp->focusWindow(), QEvent::KeyPress, key, modifiers);
+ QWindowSystemInterface::handleKeyEvent(qApp->focusWindow(), QEvent::KeyRelease, key, modifiers);
+}
+
+#ifndef QT_NO_SHORTCUT
+
+- (void)sendShortcut:(QKeySequence::StandardKey)standardKey
+{
+ const int keys = QKeySequence(standardKey)[0];
+ Qt::Key key = Qt::Key(keys & 0x0000FFFF);
+ Qt::KeyboardModifiers modifiers = Qt::KeyboardModifiers(keys & 0xFFFF0000);
+ [self sendKeyPressRelease:key modifiers:modifiers];
}
- (void)cut:(id)sender
{
Q_UNUSED(sender);
- [self sendKeyPressRelease:Qt::Key_X modifiers:Qt::ControlModifier];
+ [self sendShortcut:QKeySequence::Cut];
}
- (void)copy:(id)sender
{
Q_UNUSED(sender);
- [self sendKeyPressRelease:Qt::Key_C modifiers:Qt::ControlModifier];
+ [self sendShortcut:QKeySequence::Copy];
}
- (void)paste:(id)sender
{
Q_UNUSED(sender);
- [self sendKeyPressRelease:Qt::Key_V modifiers:Qt::ControlModifier];
+ [self sendShortcut:QKeySequence::Paste];
}
- (void)selectAll:(id)sender
{
Q_UNUSED(sender);
- [self sendKeyPressRelease:Qt::Key_A modifiers:Qt::ControlModifier];
+ [self sendShortcut:QKeySequence::SelectAll];
}
- (void)delete:(id)sender
{
Q_UNUSED(sender);
- [self sendKeyPressRelease:Qt::Key_Delete modifiers:Qt::ControlModifier];
+ [self sendShortcut:QKeySequence::Delete];
+}
+
+- (void)toggleBoldface:(id)sender
+{
+ Q_UNUSED(sender);
+ [self sendShortcut:QKeySequence::Bold];
+}
+
+- (void)toggleItalics:(id)sender
+{
+ Q_UNUSED(sender);
+ [self sendShortcut:QKeySequence::Italic];
+}
+
+- (void)toggleUnderline:(id)sender
+{
+ Q_UNUSED(sender);
+ [self sendShortcut:QKeySequence::Underline];
+}
+
+// -------------------------------------------------------------------------
+
+- (void)undo
+{
+ [self sendShortcut:QKeySequence::Undo];
+ [self rebuildUndoStack];
+}
+
+- (void)redo
+{
+ [self sendShortcut:QKeySequence::Redo];
+ [self rebuildUndoStack];
+}
+
+- (void)registerRedo
+{
+ NSUndoManager *undoMgr = self.undoManager;
+ [undoMgr beginUndoGrouping];
+ [undoMgr registerUndoWithTarget:self selector:@selector(redo) object:nil];
+ [undoMgr endUndoGrouping];
+}
+
+- (void)rebuildUndoStack
+{
+ dispatch_async(dispatch_get_main_queue (), ^{
+ // Register dummy undo/redo operations to enable Cmd-Z and Cmd-Shift-Z
+ // Ensure we do this outside any undo/redo callback since NSUndoManager
+ // will treat registerUndoWithTarget as registering a redo when called
+ // from within a undo callback.
+ NSUndoManager *undoMgr = self.undoManager;
+ [undoMgr removeAllActions];
+ [undoMgr beginUndoGrouping];
+ [undoMgr registerUndoWithTarget:self selector:@selector(undo) object:nil];
+ [undoMgr endUndoGrouping];
+
+ // Schedule an operation that we immediately pop off to be able to schedule a redo
+ [undoMgr beginUndoGrouping];
+ [undoMgr registerUndoWithTarget:self selector:@selector(registerRedo) object:nil];
+ [undoMgr endUndoGrouping];
+ [undoMgr undo];
+
+ // Note that, perhaps because of a bug in UIKit, the buttons on the shortcuts bar ends up
+ // disabled if a undo/redo callback doesn't lead to a [UITextInputDelegate textDidChange].
+ // And we only call that method if Qt made changes to the text. The effect is that the buttons
+ // become disabled when there is nothing more to undo (Qt didn't change anything upon receiving
+ // an undo request). This seems to be OK behavior, so we let it stay like that unless it shows
+ // to cause problems.
+ });
}
// -------------------------------------------------------------------------
+- (void)keyCommandTriggered:(UIKeyCommand *)keyCommand
+{
+ Qt::Key key = Qt::Key_unknown;
+ Qt::KeyboardModifiers modifiers = Qt::NoModifier;
+
+ if (keyCommand.input == UIKeyInputLeftArrow)
+ key = Qt::Key_Left;
+ else if (keyCommand.input == UIKeyInputRightArrow)
+ key = Qt::Key_Right;
+ else if (keyCommand.input == UIKeyInputUpArrow)
+ key = Qt::Key_Up;
+ else if (keyCommand.input == UIKeyInputDownArrow)
+ key = Qt::Key_Down;
+ else
+ Q_UNREACHABLE();
+
+ if (keyCommand.modifierFlags & UIKeyModifierAlternate)
+ modifiers |= Qt::AltModifier;
+ if (keyCommand.modifierFlags & UIKeyModifierShift)
+ modifiers |= Qt::ShiftModifier;
+ if (keyCommand.modifierFlags & UIKeyModifierCommand)
+ modifiers |= Qt::ControlModifier;
+
+ [self sendKeyPressRelease:key modifiers:modifiers];
+}
+
+- (void)addKeyCommandsToArray:(NSMutableArray *)array key:(NSString *)key
+{
+ SEL s = @selector(keyCommandTriggered:);
+ [array addObject:[UIKeyCommand keyCommandWithInput:key modifierFlags:0 action:s]];
+ [array addObject:[UIKeyCommand keyCommandWithInput:key modifierFlags:UIKeyModifierShift action:s]];
+ [array addObject:[UIKeyCommand keyCommandWithInput:key modifierFlags:UIKeyModifierAlternate action:s]];
+ [array addObject:[UIKeyCommand keyCommandWithInput:key modifierFlags:UIKeyModifierAlternate|UIKeyModifierShift action:s]];
+ [array addObject:[UIKeyCommand keyCommandWithInput:key modifierFlags:UIKeyModifierCommand action:s]];
+ [array addObject:[UIKeyCommand keyCommandWithInput:key modifierFlags:UIKeyModifierCommand|UIKeyModifierShift action:s]];
+}
+
+- (NSArray *)keyCommands
+{
+ // Since keyCommands is called for every key
+ // press/release, we cache the result
+ static dispatch_once_t once;
+ static NSMutableArray *array;
+
+ dispatch_once(&once, ^{
+ // We let Qt move the cursor around when the arrow keys are being used. This
+ // is normally implemented through UITextInput, but since IM in Qt have poor
+ // support for moving the cursor vertically, and even less support for selecting
+ // text across multiple paragraphs, we do this through key events.
+ array = [NSMutableArray new];
+ [self addKeyCommandsToArray:array key:UIKeyInputUpArrow];
+ [self addKeyCommandsToArray:array key:UIKeyInputDownArrow];
+ [self addKeyCommandsToArray:array key:UIKeyInputLeftArrow];
+ [self addKeyCommandsToArray:array key:UIKeyInputRightArrow];
+ });
+
+ return array;
+}
+
+#endif // QT_NO_SHORTCUT
+
+// -------------------------------------------------------------------------
+
- (void)notifyInputDelegate:(Qt::InputMethodQueries)updatedProperties
{
// As documented, we should not report textWillChange/textDidChange unless the text
@@ -540,7 +682,17 @@
- (UITextPosition *)positionFromPosition:(UITextPosition *)position inDirection:(UITextLayoutDirection)direction offset:(NSInteger)offset
{
int p = static_cast<QUITextPosition *>(position).index;
- return [QUITextPosition positionWithIndex:(direction == UITextLayoutDirectionRight ? p + offset : p - offset)];
+
+ switch (direction) {
+ case UITextLayoutDirectionLeft:
+ return [QUITextPosition positionWithIndex:p - offset];
+ case UITextLayoutDirectionRight:
+ return [QUITextPosition positionWithIndex:p + offset];
+ default:
+ // Qt doesn't support getting the position above or below the current position, so
+ // for those cases we just return the current position, making it a no-op.
+ return position;
+ }
}
- (UITextPosition *)positionWithinRange:(UITextRange *)range farthestInDirection:(UITextLayoutDirection)direction
@@ -608,6 +760,15 @@
return toCGRect(startRect.united(endRect));
}
+- (NSArray *)selectionRectsForRange:(UITextRange *)range
+{
+ Q_UNUSED(range);
+ // This method is supposed to return a rectangle for each line with selection. Since we don't
+ // expose an API in Qt/IM for getting this information, and since we never seems to be getting
+ // a call from UIKit for this, we return an empty array until a need arise.
+ return [[NSArray new] autorelease];
+}
+
- (CGRect)caretRectForPosition:(UITextPosition *)position
{
Q_UNUSED(position);
@@ -734,10 +895,10 @@
- (void)deleteBackward
{
- // 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.
+ // UITextInput selects the text to be deleted before calling this method. To avoid
+ // drawing the selection, we flush after posting the key press/release.
[self sendKeyPressRelease:Qt::Key_Backspace modifiers:Qt::NoModifier];
+ QWindowSystemInterface::flushWindowSystemEvents();
}
@end
diff --git a/src/plugins/platforms/ios/qiostheme.mm b/src/plugins/platforms/ios/qiostheme.mm
index edeabf66dc..bc40069670 100644
--- a/src/plugins/platforms/ios/qiostheme.mm
+++ b/src/plugins/platforms/ios/qiostheme.mm
@@ -107,6 +107,8 @@ QVariant QIOSTheme::themeHint(ThemeHint hint) const
switch (hint) {
case QPlatformTheme::StyleNames:
return QStringList(QStringLiteral("fusion"));
+ case KeyboardScheme:
+ return QVariant(int(MacKeyboardScheme));
default:
return QPlatformTheme::themeHint(hint);
}
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm
index 67b33ce235..94d894bba7 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.mm
+++ b/src/plugins/platforms/ios/qiosviewcontroller.mm
@@ -185,7 +185,14 @@
- (void)setFrame:(CGRect)newFrame
{
- [super setFrame:CGRectMake(0, 0, CGRectGetWidth(newFrame), CGRectGetHeight(self.window.bounds))];
+ Q_UNUSED(newFrame);
+ Q_ASSERT(!self.window || self.window.rootViewController.view == self);
+
+ // When presenting view controllers our view may be temporarily reparented into a UITransitionView
+ // instead of the UIWindow, and the UITransitionView may have a transform set, so we need to do a
+ // mapping even if we still expect to always be the root view-controller.
+ CGRect transformedWindowBounds = [self.superview convertRect:self.window.bounds fromView:self.window];
+ [super setFrame:transformedWindowBounds];
}
- (void)setBounds:(CGRect)newBounds
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp
index e4ec3f3cf8..02073f5098 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp
@@ -152,7 +152,7 @@ bool QWindowsLibEGL::init()
eglGetCurrentSurface = RESOLVE((EGLSurface (EGLAPIENTRY *)(EGLint )), eglGetCurrentSurface);
eglGetCurrentDisplay = RESOLVE((EGLDisplay (EGLAPIENTRY *)(void)), eglGetCurrentDisplay);
eglSwapBuffers = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLSurface)), eglSwapBuffers);
- eglGetProcAddress = RESOLVE((__eglMustCastToProperFunctionPointerType (EGLAPIENTRY * )(const char *)), eglGetProcAddress);
+ eglGetProcAddress = RESOLVE((QFunctionPointer (EGLAPIENTRY * )(const char *)), eglGetProcAddress);
if (!eglGetError || !eglGetDisplay || !eglInitialize || !eglGetProcAddress)
return false;
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.h b/src/plugins/platforms/windows/qwindowseglcontext.h
index d8302c97a7..555d633a78 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.h
+++ b/src/plugins/platforms/windows/qwindowseglcontext.h
@@ -71,7 +71,7 @@ struct QWindowsLibEGL
EGLSurface (EGLAPIENTRY * eglGetCurrentSurface)(EGLint readdraw);
EGLDisplay (EGLAPIENTRY * eglGetCurrentDisplay)(void);
EGLBoolean (EGLAPIENTRY * eglSwapBuffers)(EGLDisplay dpy, EGLSurface surface);
- __eglMustCastToProperFunctionPointerType (EGLAPIENTRY * eglGetProcAddress)(const char *procname);
+ QFunctionPointer (EGLAPIENTRY *eglGetProcAddress)(const char *procname);
EGLDisplay (EGLAPIENTRY * eglGetPlatformDisplayEXT)(EGLenum platform, void *native_display, const EGLint *attrib_list);
diff --git a/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp b/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp
index 0dd2facd4d..0bfa0239aa 100644
--- a/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp
+++ b/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp
@@ -67,18 +67,20 @@ QWindowsGuiEventDispatcher::QWindowsGuiEventDispatcher(QObject *parent) :
bool QWindowsGuiEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
{
+ const QEventLoop::ProcessEventsFlags oldFlags = m_flags;
m_flags = flags;
if (QWindowsContext::verbose > 2 && lcQpaEvents().isDebugEnabled())
qCDebug(lcQpaEvents) << '>' << __FUNCTION__ << objectName() << flags;
const bool rc = QEventDispatcherWin32::processEvents(flags);
if (QWindowsContext::verbose > 2 && lcQpaEvents().isDebugEnabled())
qCDebug(lcQpaEvents) << '<' << __FUNCTION__ << "returns" << rc;
+ m_flags = oldFlags;
return rc;
}
void QWindowsGuiEventDispatcher::sendPostedEvents()
{
- QCoreApplication::sendPostedEvents();
+ QEventDispatcherWin32::sendPostedEvents();
QWindowSystemInterface::sendWindowSystemEvents(m_flags);
}
diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp
index 52e83395d1..befd06f1a2 100644
--- a/src/plugins/platforms/windows/qwindowsopengltester.cpp
+++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp
@@ -276,7 +276,7 @@ QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::supportedGlesRenderers()
{
const GpuDescription gpu = GpuDescription::detect();
const QWindowsOpenGLTester::Renderers result = detectSupportedRenderers(gpu, true);
- qDebug(lcQpaGl) << __FUNCTION__ << gpu << "renderer: " << result;
+ qCDebug(lcQpaGl) << __FUNCTION__ << gpu << "renderer: " << result;
return result;
}
@@ -284,7 +284,7 @@ QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::supportedRenderers()
{
const GpuDescription gpu = GpuDescription::detect();
const QWindowsOpenGLTester::Renderers result = detectSupportedRenderers(gpu, false);
- qDebug(lcQpaGl) << __FUNCTION__ << gpu << "renderer: " << result;
+ qCDebug(lcQpaGl) << __FUNCTION__ << gpu << "renderer: " << result;
return result;
}
diff --git a/src/printsupport/dialogs/qprintdialog_unix.cpp b/src/printsupport/dialogs/qprintdialog_unix.cpp
index a15fd51c98..9633032a0f 100644
--- a/src/printsupport/dialogs/qprintdialog_unix.cpp
+++ b/src/printsupport/dialogs/qprintdialog_unix.cpp
@@ -806,7 +806,7 @@ void QUnixPrintWidgetPrivate::applyPrinterProperties()
home += QLatin1Char('/');
if (!cur.isEmpty() && cur.at(cur.length()-1) != QLatin1Char('/'))
cur += QLatin1Char('/');
- if (cur.left(home.length()) != home)
+ if (!cur.startsWith(home))
cur = home;
if (QGuiApplication::platformName() == QLatin1String("xcb")) {
if (printer->docName().isEmpty()) {
diff --git a/src/printsupport/kernel/qpaintengine_alpha.cpp b/src/printsupport/kernel/qpaintengine_alpha.cpp
index 0ae9464b69..79026e5762 100644
--- a/src/printsupport/kernel/qpaintengine_alpha.cpp
+++ b/src/printsupport/kernel/qpaintengine_alpha.cpp
@@ -146,8 +146,16 @@ void QAlphaPaintEngine::updateState(const QPaintEngineState &state)
d->m_hasalpha = d->m_alphaOpacity || d->m_alphaBrush || d->m_alphaPen;
- if (d->m_picengine)
+ if (d->m_picengine) {
+ const QPainter *p = painter();
+ d->m_picpainter->setPen(p->pen());
+ d->m_picpainter->setBrush(p->brush());
+ d->m_picpainter->setBrushOrigin(p->brushOrigin());
+ d->m_picpainter->setFont(p->font());
+ d->m_picpainter->setOpacity(p->opacity());
+ d->m_picpainter->setTransform(p->combinedTransform());
d->m_picengine->updateState(state);
+ }
}
void QAlphaPaintEngine::drawPath(const QPainterPath &path)
diff --git a/src/printsupport/kernel/qprintengine_win.cpp b/src/printsupport/kernel/qprintengine_win.cpp
index b377401ed9..a4209d833a 100644
--- a/src/printsupport/kernel/qprintengine_win.cpp
+++ b/src/printsupport/kernel/qprintengine_win.cpp
@@ -93,9 +93,10 @@ static QByteArray msgBeginFailed(const char *function, const DOCINFO &d)
{
QString result;
QTextStream str(&result);
- str << "QWin32PrintEngine::begin: " << function << " failed, document \""
- << QString::fromWCharArray(d.lpszDocName) << '"';
- if (d.lpszOutput[0])
+ str << "QWin32PrintEngine::begin: " << function << " failed";
+ if (d.lpszDocName && d.lpszDocName[0])
+ str << ", document \"" << QString::fromWCharArray(d.lpszDocName) << '"';
+ if (d.lpszOutput && d.lpszOutput[0])
str << ", file \"" << QString::fromWCharArray(d.lpszOutput) << '"';
return result.toLocal8Bit();
}
diff --git a/src/tools/qdoc/doc/examples/examples.qdoc b/src/tools/qdoc/doc/examples/examples.qdoc
index ce67dea20e..28810e30da 100644
--- a/src/tools/qdoc/doc/examples/examples.qdoc
+++ b/src/tools/qdoc/doc/examples/examples.qdoc
@@ -89,9 +89,9 @@
\title UI Components
\brief Basic set of UI components
- This is a listing of a list of UI components implemented by QML types.
- These files are available for general import and they are based off the
- \e {Qt Quick Code Samples}.
+ This is a listing of a list of UI components implemented by QML types. These
+ files are available for general import and they are based on the
+ \l{Qt Quick Examples and Tutorials}{Qt Quick Code Samples}.
This module is part of the \l{componentset}{UIComponents} example.
*/
diff --git a/src/widgets/accessible/accessible.pri b/src/widgets/accessible/accessible.pri
index bcdfbd639c..ac8205b1e3 100644
--- a/src/widgets/accessible/accessible.pri
+++ b/src/widgets/accessible/accessible.pri
@@ -4,12 +4,12 @@ contains(QT_CONFIG, accessibility) {
HEADERS += \
accessible/qaccessiblewidget.h \
accessible/qaccessiblewidgetfactory_p.h \
- accessible/complexwidgets.h \
- accessible/itemviews.h \
- accessible/qaccessiblemenu.h \
- accessible/qaccessiblewidgets.h \
- accessible/rangecontrols.h \
- accessible/simplewidgets.h
+ accessible/complexwidgets_p.h \
+ accessible/itemviews_p.h \
+ accessible/qaccessiblemenu_p.h \
+ accessible/qaccessiblewidgets_p.h \
+ accessible/rangecontrols_p.h \
+ accessible/simplewidgets_p.h
SOURCES += \
accessible/qaccessiblewidget.cpp \
diff --git a/src/widgets/accessible/complexwidgets.cpp b/src/widgets/accessible/complexwidgets.cpp
index 649a7f4363..ba87fead3c 100644
--- a/src/widgets/accessible/complexwidgets.cpp
+++ b/src/widgets/accessible/complexwidgets.cpp
@@ -31,7 +31,7 @@
**
****************************************************************************/
-#include "complexwidgets.h"
+#include "complexwidgets_p.h"
#include <qaccessible.h>
#include <qapplication.h>
diff --git a/src/widgets/accessible/complexwidgets.h b/src/widgets/accessible/complexwidgets_p.h
index bd063e7517..8edf996818 100644
--- a/src/widgets/accessible/complexwidgets.h
+++ b/src/widgets/accessible/complexwidgets_p.h
@@ -34,6 +34,17 @@
#ifndef COMPLEXWIDGETS_H
#define COMPLEXWIDGETS_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/qpointer.h>
#include <QtWidgets/qaccessiblewidget.h>
#include <QtWidgets/qabstractitemview.h>
diff --git a/src/widgets/accessible/itemviews.cpp b/src/widgets/accessible/itemviews.cpp
index 23a459c7e6..1b724c9a17 100644
--- a/src/widgets/accessible/itemviews.cpp
+++ b/src/widgets/accessible/itemviews.cpp
@@ -31,7 +31,7 @@
**
****************************************************************************/
-#include "itemviews.h"
+#include "itemviews_p.h"
#include <qheaderview.h>
#include <qtableview.h>
diff --git a/src/widgets/accessible/itemviews.h b/src/widgets/accessible/itemviews_p.h
index 33757f168a..6a18a1231b 100644
--- a/src/widgets/accessible/itemviews.h
+++ b/src/widgets/accessible/itemviews_p.h
@@ -34,6 +34,17 @@
#ifndef ACCESSIBLE_ITEMVIEWS_H
#define ACCESSIBLE_ITEMVIEWS_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include "QtCore/qpointer.h"
#include <QtGui/qaccessible.h>
#include <QtWidgets/qaccessiblewidget.h>
diff --git a/src/widgets/accessible/qaccessiblemenu.cpp b/src/widgets/accessible/qaccessiblemenu.cpp
index 72eb82b2b7..a0a7852851 100644
--- a/src/widgets/accessible/qaccessiblemenu.cpp
+++ b/src/widgets/accessible/qaccessiblemenu.cpp
@@ -31,7 +31,7 @@
**
****************************************************************************/
-#include "qaccessiblemenu.h"
+#include "qaccessiblemenu_p.h"
#include <qmenu.h>
#include <qmenubar.h>
diff --git a/src/widgets/accessible/qaccessiblemenu.h b/src/widgets/accessible/qaccessiblemenu_p.h
index 9c7671072d..b42c852ff1 100644
--- a/src/widgets/accessible/qaccessiblemenu.h
+++ b/src/widgets/accessible/qaccessiblemenu_p.h
@@ -34,6 +34,17 @@
#ifndef QACCESSIBLEMENU_H
#define QACCESSIBLEMENU_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtWidgets/qaccessiblewidget.h>
#include <QtCore/qpointer.h>
diff --git a/src/widgets/accessible/qaccessiblewidgetfactory.cpp b/src/widgets/accessible/qaccessiblewidgetfactory.cpp
index e8b325b93f..4fa7c89482 100644
--- a/src/widgets/accessible/qaccessiblewidgetfactory.cpp
+++ b/src/widgets/accessible/qaccessiblewidgetfactory.cpp
@@ -31,12 +31,12 @@
**
****************************************************************************/
-#include "qaccessiblewidgets.h"
-#include "qaccessiblemenu.h"
-#include "simplewidgets.h"
-#include "rangecontrols.h"
-#include "complexwidgets.h"
-#include "itemviews.h"
+#include "qaccessiblewidgets_p.h"
+#include "qaccessiblemenu_p.h"
+#include "simplewidgets_p.h"
+#include "rangecontrols_p.h"
+#include "complexwidgets_p.h"
+#include "itemviews_p.h"
#include <qpushbutton.h>
#include <qtoolbutton.h>
diff --git a/src/widgets/accessible/qaccessiblewidgets.cpp b/src/widgets/accessible/qaccessiblewidgets.cpp
index c598a5b4cb..adf908b821 100644
--- a/src/widgets/accessible/qaccessiblewidgets.cpp
+++ b/src/widgets/accessible/qaccessiblewidgets.cpp
@@ -31,7 +31,7 @@
**
****************************************************************************/
-#include "qaccessiblewidgets.h"
+#include "qaccessiblewidgets_p.h"
#include "qabstracttextdocumentlayout.h"
#include "qapplication.h"
#include "qclipboard.h"
diff --git a/src/widgets/accessible/qaccessiblewidgets.h b/src/widgets/accessible/qaccessiblewidgets_p.h
index 53f8c2c603..4bdc229578 100644
--- a/src/widgets/accessible/qaccessiblewidgets.h
+++ b/src/widgets/accessible/qaccessiblewidgets_p.h
@@ -34,6 +34,17 @@
#ifndef QACCESSIBLEWIDGETS_H
#define QACCESSIBLEWIDGETS_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtWidgets/qaccessiblewidget.h>
#ifndef QT_NO_ACCESSIBILITY
diff --git a/src/widgets/accessible/rangecontrols.cpp b/src/widgets/accessible/rangecontrols.cpp
index 002d4a9ef4..0607a35269 100644
--- a/src/widgets/accessible/rangecontrols.cpp
+++ b/src/widgets/accessible/rangecontrols.cpp
@@ -31,7 +31,7 @@
**
****************************************************************************/
-#include "rangecontrols.h"
+#include "rangecontrols_p.h"
#include <qslider.h>
#include <qdial.h>
@@ -47,7 +47,7 @@
#include <qmath.h>
#include <private/qmath_p.h>
-#include "simplewidgets.h" // let spinbox use line edit's interface
+#include "simplewidgets_p.h" // let spinbox use line edit's interface
QT_BEGIN_NAMESPACE
diff --git a/src/widgets/accessible/rangecontrols.h b/src/widgets/accessible/rangecontrols_p.h
index 11d4435e9d..32c6d6985f 100644
--- a/src/widgets/accessible/rangecontrols.h
+++ b/src/widgets/accessible/rangecontrols_p.h
@@ -34,6 +34,17 @@
#ifndef RANGECONTROLS_H
#define RANGECONTROLS_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtWidgets/qaccessiblewidget.h>
QT_BEGIN_NAMESPACE
diff --git a/src/widgets/accessible/simplewidgets.cpp b/src/widgets/accessible/simplewidgets.cpp
index b08c21939a..065c618cf7 100644
--- a/src/widgets/accessible/simplewidgets.cpp
+++ b/src/widgets/accessible/simplewidgets.cpp
@@ -31,7 +31,7 @@
**
****************************************************************************/
-#include "simplewidgets.h"
+#include "simplewidgets_p.h"
#include <qabstractbutton.h>
#include <qcheckbox.h>
diff --git a/src/widgets/accessible/simplewidgets.h b/src/widgets/accessible/simplewidgets_p.h
index 0dfd9f79c8..c2e904273f 100644
--- a/src/widgets/accessible/simplewidgets.h
+++ b/src/widgets/accessible/simplewidgets_p.h
@@ -34,6 +34,17 @@
#ifndef SIMPLEWIDGETS_H
#define SIMPLEWIDGETS_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/qcoreapplication.h>
#include <QtWidgets/qaccessiblewidget.h>
diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp
index ee2b1e6dae..443213d0de 100644
--- a/src/widgets/dialogs/qfiledialog.cpp
+++ b/src/widgets/dialogs/qfiledialog.cpp
@@ -2833,6 +2833,13 @@ void QFileDialogPrivate::createWidgets()
if (qFileDialogUi)
return;
Q_Q(QFileDialog);
+
+ // This function is sometimes called late (e.g as a fallback from setVisible). In that case we
+ // need to ensure that the following UI code (setupUI in particular) doesn't reset any explicitly
+ // set window state or geometry.
+ QSize preSize = q->testAttribute(Qt::WA_Resized) ? q->size() : QSize();
+ Qt::WindowStates preState = q->windowState();
+
model = new QFileSystemModel(q);
model->setFilter(options->filter());
model->setObjectName(QLatin1String("qt_filesystem_model"));
@@ -2878,6 +2885,9 @@ void QFileDialogPrivate::createWidgets()
completer = new QFSCompleter(model, q);
qFileDialogUi->fileNameEdit->setCompleter(completer);
#endif // QT_NO_FSCOMPLETER
+
+ qFileDialogUi->fileNameEdit->setInputMethodHints(Qt::ImhNoPredictiveText);
+
QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(textChanged(QString)),
q, SLOT(_q_autoCompleteFileName(QString)));
QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(textChanged(QString)),
@@ -2991,7 +3001,8 @@ void QFileDialogPrivate::createWidgets()
lineEdit()->selectAll();
_q_updateOkButton();
retranslateStrings();
- q->resize(q->sizeHint());
+ q->resize(preSize.isValid() ? preSize : q->sizeHint());
+ q->setWindowState(preState);
}
void QFileDialogPrivate::_q_showHeader(QAction *action)
diff --git a/src/widgets/doc/images/filedialogurls.png b/src/widgets/doc/images/filedialogurls.png
index 7d22ef33ae..4e26bbfb6d 100644
--- a/src/widgets/doc/images/filedialogurls.png
+++ b/src/widgets/doc/images/filedialogurls.png
Binary files differ
diff --git a/src/widgets/doc/qtwidgets.qdocconf b/src/widgets/doc/qtwidgets.qdocconf
index ab20a8666c..f307e9d3e4 100644
--- a/src/widgets/doc/qtwidgets.qdocconf
+++ b/src/widgets/doc/qtwidgets.qdocconf
@@ -26,7 +26,7 @@ qhp.QtWidgets.subprojects.classes.sortPages = true
tagfile = ../../../doc/qtwidgets/qtwidgets.tags
-depends += qtcore qtgui qtdoc qtsql qtdesigner qtquick qmake
+depends += qtcore qtgui qtdoc qtsql qtdesigner qtquick qmake qtsvg
headerdirs += ..
diff --git a/src/widgets/doc/snippets/filedialogurls.cpp b/src/widgets/doc/snippets/filedialogurls.cpp
index 9e2862b56f..ea771c2050 100644
--- a/src/widgets/doc/snippets/filedialogurls.cpp
+++ b/src/widgets/doc/snippets/filedialogurls.cpp
@@ -46,8 +46,8 @@ int main(int argv, char **args)
//![0]
QList<QUrl> urls;
- urls << QUrl::fromLocalFile("/home/gvatteka/dev/qt-45")
- << QUrl::fromLocalFile(QDesktopServices::storageLocation(QDesktopServices::MusicLocation));
+ urls << QUrl::fromLocalFile("/Users/foo/Code/qt5")
+ << QUrl::fromLocalFile(QStandardPaths::standardLocations(QStandardPaths::MusicLocation).first());
QFileDialog dialog;
dialog.setSidebarUrls(urls);
diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp
index 8cb7c2b560..9a35308cad 100644
--- a/src/widgets/kernel/qgesturemanager.cpp
+++ b/src/widgets/kernel/qgesturemanager.cpp
@@ -405,6 +405,8 @@ void QGestureManager::cancelGesturesForChildren(QGesture *original)
Q_ASSERT(original);
QWidget *originatingWidget = m_gestureTargets.value(original);
Q_ASSERT(originatingWidget);
+ if (!originatingWidget)
+ return;
// iterate over all active gestures and all maybe gestures
// for each find the owner
@@ -565,7 +567,8 @@ void QGestureManager::getGestureTargets(const QSet<QGesture*> &gestures,
foreach (QGesture *gesture, gestures) {
QWidget *receiver = m_gestureTargets.value(gesture, 0);
Q_ASSERT(receiver);
- gestureByTypes[gesture->gestureType()].insert(receiver, gesture);
+ if (receiver)
+ gestureByTypes[gesture->gestureType()].insert(receiver, gesture);
}
// for each gesture type
diff --git a/src/widgets/kernel/qgesturemanager_p.h b/src/widgets/kernel/qgesturemanager_p.h
index 8ba253d17e..4e349ac731 100644
--- a/src/widgets/kernel/qgesturemanager_p.h
+++ b/src/widgets/kernel/qgesturemanager_p.h
@@ -117,7 +117,7 @@ private:
QHash<QGesture *, QGestureRecognizer *> m_gestureToRecognizer;
QHash<QGesture *, QObject *> m_gestureOwners;
- QHash<QGesture *, QWidget *> m_gestureTargets;
+ QHash<QGesture *, QPointer<QWidget> > m_gestureTargets;
int m_lastCustomGestureId;
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 66c86a7bce..a006246454 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -5829,7 +5829,10 @@ QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *
pixmapOffset -= effectRect.topLeft();
- QPixmap pixmap(effectRect.size());
+ const qreal dpr = context->painter->device()->devicePixelRatio();
+ QPixmap pixmap(effectRect.size() * dpr);
+ pixmap.setDevicePixelRatio(dpr);
+
pixmap.fill(Qt::transparent);
m_widget->render(&pixmap, pixmapOffset, QRegion(), QWidget::DrawChildren);
return pixmap;