Merge remote-tracking branch 'origin/5.8.0' into 5.8

Conflicts:
	doc/global/qt-cpp-defines.qdocconf
	src/plugins/platforms/android/qandroidplatformopenglcontext.h
	src/plugins/platforms/android/qandroidplatformtheme.h

Change-Id: I13d51cc66f708138ff4d667ceea7d515992e58a4
This commit is contained in:
Liang Qi 2016-12-16 09:38:46 +01:00
commit 9bfe3ab71e
80 changed files with 999 additions and 455 deletions

View File

@ -81,6 +81,34 @@
\externalpage http://doc.qt.io/qtcreator/creator-version-control.html \externalpage http://doc.qt.io/qtcreator/creator-version-control.html
\title Qt Creator: Using Version Control Systems \title Qt Creator: Using Version Control Systems
*/ */
/*!
\externalpage http://doc.qt.io/qtcreator/creator-vcs-bazaar.html
\title Qt Creator: Using Bazaar
*/
/*!
\externalpage http://doc.qt.io/qtcreator/creator-vcs-clearcase.html
\title Qt Creator: Using ClearCase
*/
/*!
\externalpage http://doc.qt.io/qtcreator/creator-vcs-cvs.html
\title Qt Creator: Using CVS
*/
/*!
\externalpage http://doc.qt.io/qtcreator/creator-vcs-git.html
\title Qt Creator: Using Git
*/
/*!
\externalpage http://doc.qt.io/qtcreator/creator-vcs-mercurial.html
\title Qt Creator: Using Mercurial
*/
/*!
\externalpage http://doc.qt.io/qtcreator/creator-vcs-perforce.html
\title Qt Creator: Using Perforce
*/
/*!
\externalpage http://doc.qt.io/qtcreator/creator-vcs-subversion.html
\title Qt Creator: Using Subversion
*/
/*! /*!
\externalpage http://doc.qt.io/qtcreator/creator-keyboard-shortcuts.html \externalpage http://doc.qt.io/qtcreator/creator-keyboard-shortcuts.html
\title Qt Creator: Keyboard Shortcuts \title Qt Creator: Keyboard Shortcuts

View File

@ -33,7 +33,6 @@ manifestmeta.filters = highlighted android thumbnail ios
manifestmeta.highlighted.names = "QtQuick/Qt Quick Demo - Same Game" \ manifestmeta.highlighted.names = "QtQuick/Qt Quick Demo - Same Game" \
"QtQuick/Qt Quick Demo - Photo Surface" \ "QtQuick/Qt Quick Demo - Photo Surface" \
"QtQuick/Qt Quick Demo - Tweet Search" \ "QtQuick/Qt Quick Demo - Tweet Search" \
"QtQuick/Qt Quick Demo - Maroon*" \
"QtQuick/Qt Quick Demo - Calqlatr" \ "QtQuick/Qt Quick Demo - Calqlatr" \
"QtQuick/Qt Quick Demo - StocQt" \ "QtQuick/Qt Quick Demo - StocQt" \
"QtQuick/Qt Quick Demo - Clocks" \ "QtQuick/Qt Quick Demo - Clocks" \
@ -45,14 +44,12 @@ manifestmeta.highlighted.names = "QtQuick/Qt Quick Demo - Same Game" \
"QtQuickDialogs/Qt Quick System Dialog Examples" \ "QtQuickDialogs/Qt Quick System Dialog Examples" \
"QtWinExtras/Quick Player" \ "QtWinExtras/Quick Player" \
"QtMultimedia/QML Video Shader Effects Example" \ "QtMultimedia/QML Video Shader Effects Example" \
"QtCanvas3D/Planets Example" \
"QtCanvas3D/Interactive Mobile Phone Example" \ "QtCanvas3D/Interactive Mobile Phone Example" \
"QtLocation/Map Viewer (QML)" "QtLocation/Map Viewer (QML)"
manifestmeta.highlighted.attributes = isHighlighted:true manifestmeta.highlighted.attributes = isHighlighted:true
manifestmeta.android.names = "QtQuick/Qt Quick Demo - Maroon*" \ manifestmeta.android.names = "QtQuick/Qt Quick Demo - Calqlatr" \
"QtQuick/Qt Quick Demo - Calqlatr" \
"QtWidgets/Application Chooser Example" \ "QtWidgets/Application Chooser Example" \
"QtWidgets/Stickman Example" \ "QtWidgets/Stickman Example" \
"QtWidgets/Move Blocks Example" \ "QtWidgets/Move Blocks Example" \

View File

@ -14,12 +14,14 @@ defines += Q_QDOC \
Q_NO_USING_KEYWORD \ Q_NO_USING_KEYWORD \
__cplusplus \ __cplusplus \
Q_COMPILER_INITIALIZER_LISTS \ Q_COMPILER_INITIALIZER_LISTS \
Q_COMPILER_UNICODE_STRINGS \
Q_COMPILER_UNIFORM_INIT \ Q_COMPILER_UNIFORM_INIT \
Q_COMPILER_RVALUE_REFS Q_COMPILER_RVALUE_REFS
Cpp.ignoretokens += \ Cpp.ignoretokens += \
ENGINIOCLIENT_EXPORT \ ENGINIOCLIENT_EXPORT \
PHONON_EXPORT \ PHONON_EXPORT \
Q_ALWAYS_INLINE \
Q_AUTOTEST_EXPORT \ Q_AUTOTEST_EXPORT \
Q_BLUETOOTH_EXPORT \ Q_BLUETOOTH_EXPORT \
Q_COMPAT_EXPORT \ Q_COMPAT_EXPORT \
@ -121,6 +123,7 @@ Cpp.ignoretokens += \
QT_END_NAMESPACE \ QT_END_NAMESPACE \
QT_FASTCALL \ QT_FASTCALL \
QT_MUTEX_LOCK_NOEXCEPT \ QT_MUTEX_LOCK_NOEXCEPT \
QT_WARNING_DISABLE_DEPRECATED \
QT_WARNING_PUSH \ QT_WARNING_PUSH \
QT_WARNING_POP \ QT_WARNING_POP \
QT_WIDGET_PLUGIN_EXPORT \ QT_WIDGET_PLUGIN_EXPORT \
@ -152,6 +155,7 @@ Cpp.ignoredirectives += \
Q_FLAG \ Q_FLAG \
Q_FLAGS \ Q_FLAGS \
Q_FLAG_NS \ Q_FLAG_NS \
QT_HAS_INCLUDE \
Q_INTERFACES \ Q_INTERFACES \
Q_PRIVATE_PROPERTY \ Q_PRIVATE_PROPERTY \
QT_FORWARD_DECLARE_CLASS \ QT_FORWARD_DECLARE_CLASS \

View File

@ -49,7 +49,9 @@
****************************************************************************/ ****************************************************************************/
#include <QtWidgets> #include <QtWidgets>
#if defined(QT_PRINTSUPPORT_LIB)
#include <QPrintPreviewDialog> #include <QPrintPreviewDialog>
#endif
#include "mainwindow.h" #include "mainwindow.h"
@ -210,7 +212,7 @@ QMap<QString, StyleItems> MainWindow::currentPageMap()
return pageMap; return pageMap;
} }
#if !defined(QT_NO_PRINTER) && !defined(QT_NO_PRINTDIALOG) #if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printdialog)
void MainWindow::on_printAction_triggered() void MainWindow::on_printAction_triggered()
{ {
pageMap = currentPageMap(); pageMap = currentPageMap();
@ -342,4 +344,4 @@ void MainWindow::printPage(int index, QPainter *painter, QPrinter *printer)
painter->restore(); painter->restore();
} }
#endif // QT_NO_PRINTER #endif

View File

@ -55,6 +55,9 @@
#include <QPrinter> #include <QPrinter>
#include <QPrintDialog> #include <QPrintDialog>
#if defined(QT_PRINTSUPPORT_LIB)
#include <QtPrintSupport/qtprintsupportglobal.h>
#endif
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QPrinter; class QPrinter;
class QTextEdit; class QTextEdit;
@ -74,12 +77,11 @@ public:
public slots: public slots:
void on_clearAction_triggered(); void on_clearAction_triggered();
void on_markAction_triggered(); void on_markAction_triggered();
#if !defined(QT_NO_PRINTER) && !defined(QT_NO_PRINTDIALOG) void on_unmarkAction_triggered();
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printdialog)
void on_printAction_triggered(); void on_printAction_triggered();
void on_printPreviewAction_triggered(); void on_printPreviewAction_triggered();
#endif
void on_unmarkAction_triggered();
#if !defined(QT_NO_PRINTER) && !defined(QT_NO_PRINTDIALOG)
void printDocument(QPrinter *printer); void printDocument(QPrinter *printer);
void printPage(int index, QPainter *painter, QPrinter *printer); void printPage(int index, QPainter *painter, QPrinter *printer);
#endif #endif

View File

@ -28,12 +28,13 @@ win32:count(MOC_INCLUDEPATH, 40, >) {
# UIKit builds are always multi-arch due to simulator_and_device (unless # UIKit builds are always multi-arch due to simulator_and_device (unless
# -sdk is used) so this feature cannot possibly work. # -sdk is used) so this feature cannot possibly work.
if(gcc|intel_icl|msvc):!rim_qcc:!uikit { if(gcc|intel_icl|msvc):!rim_qcc:!uikit {
moc_predefs.name = "Generate moc_predefs.h"
moc_predefs.CONFIG = no_link moc_predefs.CONFIG = no_link
gcc: moc_predefs.commands = $$QMAKE_CXX $$QMAKE_CXXFLAGS -dM -E -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN} gcc: moc_predefs.commands = $$QMAKE_CXX $$QMAKE_CXXFLAGS -dM -E -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN}
else:intel_icl: moc_predefs.commands = $$QMAKE_CXX $$QMAKE_CXXFLAGS -QdM -P -Fi${QMAKE_FILE_OUT} ${QMAKE_FILE_IN} else:intel_icl: moc_predefs.commands = $$QMAKE_CXX $$QMAKE_CXXFLAGS -QdM -P -Za -Fi${QMAKE_FILE_OUT} ${QMAKE_FILE_IN}
else:msvc { else:msvc {
moc_predefs.commands += $$QMAKE_CXX -Bx$$shell_quote($$shell_path($$QMAKE_QMAKE)) $$QMAKE_CXXFLAGS \ moc_predefs.commands += $$QMAKE_CXX -Bx$$shell_quote($$shell_path($$QMAKE_QMAKE)) $$QMAKE_CXXFLAGS \
-E ${QMAKE_FILE_IN} 2>NUL >${QMAKE_FILE_OUT} -E -Za ${QMAKE_FILE_IN} 2>NUL >${QMAKE_FILE_OUT}
} else: error("Oops, I messed up") } else: error("Oops, I messed up")
moc_predefs.output = $$MOC_DIR/moc_predefs.h moc_predefs.output = $$MOC_DIR/moc_predefs.h
moc_predefs.input = MOC_PREDEF_FILE moc_predefs.input = MOC_PREDEF_FILE

View File

@ -25,7 +25,7 @@ for (s, QLALRSOURCES) {
$${base}.variable_out = GENERATED_SOURCES $${base}.variable_out = GENERATED_SOURCES
$${base}.depends += $$QMAKE_QLALR_EXE $${base}.depends += $$QMAKE_QLALR_EXE
$${base}.commands = $$QMAKE_QLALR $$QMAKE_QLALRFLAGS ${QMAKE_FILE_IN} $${base}.commands = $$QMAKE_QLALR $$QMAKE_QLALRFLAGS ${QMAKE_FILE_IN}
silent: $${base}.commands = @echo qlalr ${QMAKE_FILE_IN} && $${base}.commands silent: $${base}.commands = @echo qlalr ${QMAKE_FILE_IN} && $$eval($${base}.commands)
$${base}.name = QLALR ${QMAKE_FILE_IN} $${base}.name = QLALR ${QMAKE_FILE_IN}
$${base}_h.input = $$invar $${base}_h.input = $$invar

View File

@ -14,7 +14,7 @@ QMAKE_YACCFLAGS = -d
QMAKE_CFLAGS = QMAKE_CFLAGS =
QMAKE_CFLAGS_APP = -fPIC QMAKE_CFLAGS_APP = -fPIC
QMAKE_CFLAGS_DEPS = -M QMAKE_CFLAGS_DEPS = -M
QMAKE_CFLAGS_WARN_ON = -w1 -Wall -Wcheck -wd1572,873,2259,2261 QMAKE_CFLAGS_WARN_ON = -w1 -Wall -Wcheck -wd1572,873,2259,2261,3373
QMAKE_CFLAGS_WARN_OFF = -w QMAKE_CFLAGS_WARN_OFF = -w
QMAKE_CFLAGS_RELEASE = -O2 -falign-functions=16 -ansi-alias -fstrict-aliasing QMAKE_CFLAGS_RELEASE = -O2 -falign-functions=16 -ansi-alias -fstrict-aliasing
QMAKE_CFLAGS_DEBUG = -O0 -g QMAKE_CFLAGS_DEBUG = -O0 -g

View File

@ -14,7 +14,7 @@ QMAKE_COMPILER = gcc clang intel_icc # icc pretends to be gcc and cla
QMAKE_CC = icc QMAKE_CC = icc
QMAKE_CFLAGS = QMAKE_CFLAGS =
QMAKE_CFLAGS_DEPS = -M QMAKE_CFLAGS_DEPS = -M
QMAKE_CFLAGS_WARN_ON = -w1 -Wcheck -wd654,1572,411,873,1125,2259,2261,3280 QMAKE_CFLAGS_WARN_ON = -w1 -Wcheck -wd654,1572,411,873,1125,2259,2261,3280,3373
QMAKE_CFLAGS_WARN_OFF = -w QMAKE_CFLAGS_WARN_OFF = -w
QMAKE_CFLAGS_RELEASE = QMAKE_CFLAGS_RELEASE =
QMAKE_CFLAGS_DEBUG = -g QMAKE_CFLAGS_DEBUG = -g

View File

@ -19,7 +19,7 @@ QMAKE_LEX = flex
QMAKE_LEXFLAGS = QMAKE_LEXFLAGS =
QMAKE_YACC = bison -y QMAKE_YACC = bison -y
QMAKE_YACCFLAGS = -d QMAKE_YACCFLAGS = -d
QMAKE_CFLAGS = -nologo -Zm200 /Qprec /Qwd1744,1738,809 QMAKE_CFLAGS = -nologo -Zm200 /Qprec /Qwd1744,1738,809,3373
QMAKE_CFLAGS_WARN_ON = -W3 /Qwd673 QMAKE_CFLAGS_WARN_ON = -W3 /Qwd673
QMAKE_CFLAGS_WARN_OFF = -W0 /Qwd673 QMAKE_CFLAGS_WARN_OFF = -W0 /Qwd673
QMAKE_CFLAGS_RELEASE = -O2 -MD QMAKE_CFLAGS_RELEASE = -O2 -MD

View File

@ -308,13 +308,13 @@ void MingwMakefileGenerator::writeBuildRulesPart(QTextStream &t)
{ {
t << "first: all\n"; t << "first: all\n";
t << "all: " << escapeDependencyPath(fileFixify(Option::output.fileName())) t << "all: " << escapeDependencyPath(fileFixify(Option::output.fileName()))
<< ' ' << depVar("ALL_DEPS"); << ' ' << depVar("ALL_DEPS") << " $(DESTDIR_TARGET)\n\n";
t << "$(DESTDIR_TARGET): " << depVar("PRE_TARGETDEPS") << " $(OBJECTS) " << depVar("POST_TARGETDEPS");
if (project->first("TEMPLATE") == "aux") { if (project->first("TEMPLATE") == "aux") {
t << "\n\n"; t << "\n\n";
return; return;
} }
t << " $(DESTDIR_TARGET)\n\n";
t << "$(DESTDIR_TARGET): " << depVar("PRE_TARGETDEPS") << " $(OBJECTS) " << depVar("POST_TARGETDEPS");
if(!project->isEmpty("QMAKE_PRE_LINK")) if(!project->isEmpty("QMAKE_PRE_LINK"))
t << "\n\t" <<var("QMAKE_PRE_LINK"); t << "\n\t" <<var("QMAKE_PRE_LINK");
if(project->isActiveConfig("staticlib") && project->first("TEMPLATE") == "lib") { if(project->isActiveConfig("staticlib") && project->first("TEMPLATE") == "lib") {

View File

@ -517,13 +517,12 @@ void NmakeMakefileGenerator::writeBuildRulesPart(QTextStream &t)
t << "first: all\n"; t << "first: all\n";
t << "all: " << escapeDependencyPath(fileFixify(Option::output.fileName())) t << "all: " << escapeDependencyPath(fileFixify(Option::output.fileName()))
<< ' ' << depVar("ALL_DEPS"); << ' ' << depVar("ALL_DEPS") << " $(DESTDIR_TARGET)\n\n";
t << "$(DESTDIR_TARGET): " << depVar("PRE_TARGETDEPS") << " $(OBJECTS) " << depVar("POST_TARGETDEPS");
if (templateName == "aux") { if (templateName == "aux") {
t << "\n\n"; t << "\n\n";
return; return;
} }
t << " $(DESTDIR_TARGET)\n\n";
t << "$(DESTDIR_TARGET): " << depVar("PRE_TARGETDEPS") << " $(OBJECTS) " << depVar("POST_TARGETDEPS");
if(!project->isEmpty("QMAKE_PRE_LINK")) if(!project->isEmpty("QMAKE_PRE_LINK"))
t << "\n\t" <<var("QMAKE_PRE_LINK"); t << "\n\t" <<var("QMAKE_PRE_LINK");

View File

@ -2264,10 +2264,14 @@ bool VCFilter::addExtraCompiler(const VCFilterFile &info)
QString inFile = info.file; QString inFile = info.file;
// is the extracompiler rule on a file with a built in compiler? // is the extracompiler rule on a file with a built in compiler?
const QStringList &objectMappedFile = Project->extraCompilerOutputs[inFile]; const QString objectMappedFile = Project->extraCompilerOutputs.value(inFile);
bool hasBuiltIn = false; bool hasBuiltIn = false;
if (!objectMappedFile.isEmpty()) { if (!objectMappedFile.isEmpty()) {
hasBuiltIn = Project->hasBuiltinCompiler(objectMappedFile.at(0)); hasBuiltIn = Project->hasBuiltinCompiler(objectMappedFile);
// Remove the fake file suffix we've added initially to generate correct command lines.
inFile.chop(Project->customBuildToolFilterFileSuffix.length());
// qDebug("*** Extra compiler file has object mapped file '%s' => '%s'", qPrintable(inFile), qPrintable(objectMappedFile.join(' '))); // qDebug("*** Extra compiler file has object mapped file '%s' => '%s'", qPrintable(inFile), qPrintable(objectMappedFile.join(' ')));
} }
@ -2309,7 +2313,7 @@ bool VCFilter::addExtraCompiler(const VCFilterFile &info)
// compiler, too bad.. // compiler, too bad..
if (hasBuiltIn) { if (hasBuiltIn) {
out = inFile; out = inFile;
inFile = objectMappedFile.at(0); inFile = objectMappedFile;
} }
// Dependency for the output // Dependency for the output

View File

@ -204,7 +204,8 @@ const char _slnExtSections[] = "\n\tGlobalSection(ExtensibilityGlobals) = pos
VcprojGenerator::VcprojGenerator() VcprojGenerator::VcprojGenerator()
: Win32MakefileGenerator(), : Win32MakefileGenerator(),
is64Bit(false), is64Bit(false),
projectWriter(0) projectWriter(0),
customBuildToolFilterFileSuffix(QStringLiteral(".cbt"))
{ {
} }
@ -892,10 +893,14 @@ void VcprojGenerator::init()
if (!hasBuiltinCompiler(file)) { if (!hasBuiltinCompiler(file)) {
extraCompilerSources[file] += quc.toQString(); extraCompilerSources[file] += quc.toQString();
} else { } else {
// Use a fake file name foo.moc.cbt for the project view.
// This prevents VS from complaining about a circular
// dependency from foo.moc -> foo.moc.
QString out = Option::fixPathToTargetOS(replaceExtraCompilerVariables( QString out = Option::fixPathToTargetOS(replaceExtraCompilerVariables(
compiler_out, file, QString(), NoShell), false); compiler_out, file, QString(), NoShell), false);
out += customBuildToolFilterFileSuffix;
extraCompilerSources[out] += quc.toQString(); extraCompilerSources[out] += quc.toQString();
extraCompilerOutputs[out] = QStringList(file); // Can only have one extraCompilerOutputs[out] = file;
} }
} }
} }

View File

@ -63,7 +63,8 @@ public:
static bool hasBuiltinCompiler(const QString &file); static bool hasBuiltinCompiler(const QString &file);
QHash<QString, QStringList> extraCompilerSources; QHash<QString, QStringList> extraCompilerSources;
QHash<QString, QStringList> extraCompilerOutputs; QHash<QString, QString> extraCompilerOutputs;
const QString customBuildToolFilterFileSuffix;
bool usePCH; bool usePCH;
VCProjectWriter *projectWriter; VCProjectWriter *projectWriter;

View File

@ -165,6 +165,9 @@ Win32MakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags)
void Win32MakefileGenerator::processVars() void Win32MakefileGenerator::processVars()
{ {
if (project->first("TEMPLATE").endsWith("aux"))
return;
project->values("QMAKE_ORIG_TARGET") = project->values("TARGET"); project->values("QMAKE_ORIG_TARGET") = project->values("TARGET");
if (project->isEmpty("QMAKE_PROJECT_NAME")) if (project->isEmpty("QMAKE_PROJECT_NAME"))
project->values("QMAKE_PROJECT_NAME") = project->values("QMAKE_ORIG_TARGET"); project->values("QMAKE_PROJECT_NAME") = project->values("QMAKE_ORIG_TARGET");

View File

@ -17,7 +17,9 @@ JAVASOURCES += \
$$PATHPREFIX/QtNativeLibrariesDir.java \ $$PATHPREFIX/QtNativeLibrariesDir.java \
$$PATHPREFIX/QtSurface.java \ $$PATHPREFIX/QtSurface.java \
$$PATHPREFIX/ExtractStyle.java \ $$PATHPREFIX/ExtractStyle.java \
$$PATHPREFIX/QtServiceDelegate.java $$PATHPREFIX/EditMenu.java \
$$PATHPREFIX/EditPopupMenu.java \
$$PATHPREFIX/CursorHandle.java
# install # install
target.path = $$[QT_INSTALL_PREFIX]/jar target.path = $$[QT_INSTALL_PREFIX]/jar

View File

@ -1,7 +1,7 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<resources> <resources>
<array name="qt_sources"> <array name="qt_sources">
<item>https://download.qt.io/ministro/android/qt5/qt-5.7</item> <item>https://download.qt.io/ministro/android/qt5/qt-5.8</item>
</array> </array>
<!-- The following is handled automatically by the deployment tool. It should <!-- The following is handled automatically by the deployment tool. It should

View File

@ -1273,7 +1273,7 @@
# define QT_WARNING_DISABLE_INTEL(number) __pragma(warning(disable: number)) # define QT_WARNING_DISABLE_INTEL(number) __pragma(warning(disable: number))
# define QT_WARNING_DISABLE_CLANG(text) # define QT_WARNING_DISABLE_CLANG(text)
# define QT_WARNING_DISABLE_GCC(text) # define QT_WARNING_DISABLE_GCC(text)
# define QT_WARNING_DISABLE_DEPRECATED QT_WARNING_DISABLE_INTEL(1786) # define QT_WARNING_DISABLE_DEPRECATED QT_WARNING_DISABLE_INTEL(1478 1786)
#elif defined(Q_CC_INTEL) #elif defined(Q_CC_INTEL)
/* icc: Intel compiler on Linux or OS X */ /* icc: Intel compiler on Linux or OS X */
# define QT_WARNING_PUSH QT_DO_PRAGMA(warning(push)) # define QT_WARNING_PUSH QT_DO_PRAGMA(warning(push))
@ -1282,7 +1282,7 @@
# define QT_WARNING_DISABLE_MSVC(number) # define QT_WARNING_DISABLE_MSVC(number)
# define QT_WARNING_DISABLE_CLANG(text) # define QT_WARNING_DISABLE_CLANG(text)
# define QT_WARNING_DISABLE_GCC(text) # define QT_WARNING_DISABLE_GCC(text)
# define QT_WARNING_DISABLE_DEPRECATED QT_WARNING_DISABLE_INTEL(1786) # define QT_WARNING_DISABLE_DEPRECATED QT_WARNING_DISABLE_INTEL(1478 1786)
#elif defined(Q_CC_MSVC) && _MSC_VER >= 1500 && !defined(Q_CC_CLANG) #elif defined(Q_CC_MSVC) && _MSC_VER >= 1500 && !defined(Q_CC_CLANG)
# undef QT_DO_PRAGMA /* not needed */ # undef QT_DO_PRAGMA /* not needed */
# define QT_WARNING_PUSH __pragma(warning(push)) # define QT_WARNING_PUSH __pragma(warning(push))

View File

@ -921,10 +921,10 @@ template <typename T>
class QForeachContainer { class QForeachContainer {
QForeachContainer &operator=(const QForeachContainer &) Q_DECL_EQ_DELETE; QForeachContainer &operator=(const QForeachContainer &) Q_DECL_EQ_DELETE;
public: public:
QForeachContainer(const T &t) : c(t) {} QForeachContainer(const T &t) : c(t), i(c.begin()), e(c.end()) {}
QForeachContainer(T &&t) : c(std::move(t)) {} QForeachContainer(T &&t) : c(std::move(t)), i(c.begin()), e(c.end()) {}
const T c; const T c;
typename T::const_iterator i = c.begin(), e = c.end(); typename T::const_iterator i, e;
int control = 1; int control = 1;
}; };

View File

@ -1042,6 +1042,10 @@ void QMessagePattern::setPattern(const QString &pattern)
delete [] literals; delete [] literals;
} }
delete [] tokens; delete [] tokens;
timeArgs.clear();
#ifdef QLOGGING_HAVE_BACKTRACE
backtraceArgs.clear();
#endif
// scanner // scanner
QList<QString> lexemes; QList<QString> lexemes;

View File

@ -68,7 +68,8 @@
#if !defined(Q_CC_MSVC) && (defined(Q_OS_QNX) || defined(Q_CC_INTEL) || !defined(__cplusplus)) #if !defined(Q_CC_MSVC) && (defined(Q_OS_QNX) || defined(Q_CC_INTEL) || !defined(__cplusplus))
# include <math.h> # include <math.h>
# define QT_MATH_H_DEFINES_MACROS # ifdef isnan
# define QT_MATH_H_DEFINES_MACROS
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
namespace qnumeric_std_wrapper { namespace qnumeric_std_wrapper {
// the 'using namespace std' below is cases where the stdlib already put the math.h functions in the std namespace and undefined the macros. // the 'using namespace std' below is cases where the stdlib already put the math.h functions in the std namespace and undefined the macros.
@ -81,10 +82,11 @@ static inline bool math_h_isfinite(float f) { using namespace std; return isfini
} }
QT_END_NAMESPACE QT_END_NAMESPACE
// These macros from math.h conflict with the real functions in the std namespace. // These macros from math.h conflict with the real functions in the std namespace.
#undef signbit # undef signbit
#undef isnan # undef isnan
#undef isinf # undef isinf
#undef isfinite # undef isfinite
# endif // defined(isnan)
#endif #endif
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE

View File

@ -578,6 +578,22 @@ QDebug &QDebug::resetFormat()
output, but note that some QDebug backends might not be 8-bit clean. output, but note that some QDebug backends might not be 8-bit clean.
*/ */
/*!
\fn QDebug &QDebug::operator<<(char16_t t)
\since 5.5
Writes the UTF-16 character, \a t, to the stream and returns a reference
to the stream.
*/
/*!
\fn QDebug &QDebug::operator<<(char32_t t)
\since 5.5
Writes the UTF-32 character, \a t, to the stream and returns a reference
to the stream.
*/
/*! /*!
\fn QDebug &QDebug::operator<<(const QString &s) \fn QDebug &QDebug::operator<<(const QString &s)

View File

@ -122,6 +122,7 @@ Q_DECL_CONST_FUNCTION static inline QPair<qint64, qint64> toSecsAndNSecs(qint64
\code \code
using namespace std::chrono; using namespace std::chrono;
using namespace std::chrono_literals;
QDeadlineTimer deadline(30s); QDeadlineTimer deadline(30s);
device->waitForReadyRead(deadline); device->waitForReadyRead(deadline);
@ -141,6 +142,7 @@ Q_DECL_CONST_FUNCTION static inline QPair<qint64, qint64> toSecsAndNSecs(qint64
\code \code
using namespace std::chrono; using namespace std::chrono;
using namespace std::chrono_literals;
auto now = steady_clock::now(); auto now = steady_clock::now();
QDeadlineTimer deadline(now + 1s); QDeadlineTimer deadline(now + 1s);
Q_ASSERT(deadline == now + 1s); Q_ASSERT(deadline == now + 1s);
@ -240,7 +242,7 @@ QDeadlineTimer::QDeadlineTimer(qint64 msecs, Qt::TimerType type) Q_DECL_NOTHROW
This constructor can be used with C++14's user-defined literals for time, such as in: This constructor can be used with C++14's user-defined literals for time, such as in:
\code \code
using namespace std::chrono; using namespace std::chrono_literals;
QDeadlineTimer deadline(250ms); QDeadlineTimer deadline(250ms);
\endcode \endcode
@ -333,7 +335,7 @@ void QDeadlineTimer::setPreciseRemainingTime(qint64 secs, qint64 nsecs, Qt::Time
This function can be used with C++14's user-defined literals for time, such as in: This function can be used with C++14's user-defined literals for time, such as in:
\code \code
using namespace std::chrono; using namespace std::chrono_literals;
deadline.setRemainingTime(250ms); deadline.setRemainingTime(250ms);
\endcode \endcode

View File

@ -1389,10 +1389,6 @@ namespace QtPrivate
}; };
QT_WARNING_PUSH
// In C++03 mode, clang consider local or unnamed type and throw a warning instead of ignoring them
QT_WARNING_DISABLE_CLANG("-Wunnamed-type-template-args")
QT_WARNING_DISABLE_CLANG("-Wlocal-type-template-args")
template<typename T> char qt_getEnumMetaObject(const T&); template<typename T> char qt_getEnumMetaObject(const T&);
template<typename T> template<typename T>
@ -1405,7 +1401,6 @@ QT_WARNING_DISABLE_CLANG("-Wlocal-type-template-args")
enum { Value = sizeof(qt_getEnumMetaObject(declval())) == sizeof(QMetaObject*) }; enum { Value = sizeof(qt_getEnumMetaObject(declval())) == sizeof(QMetaObject*) };
}; };
template<> struct IsQEnumHelper<void> { enum { Value = false }; }; template<> struct IsQEnumHelper<void> { enum { Value = false }; };
QT_WARNING_POP
template<typename T, typename Enable = void> template<typename T, typename Enable = void>
struct MetaObjectForType struct MetaObjectForType

View File

@ -279,7 +279,7 @@ bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
for the mutex to become available. for the mutex to become available.
Note: Passing a negative duration as the \a duration is equivalent to Note: Passing a negative duration as the \a duration is equivalent to
calling try_lock(). This behavior is different from tryLock. calling try_lock(). This behavior differs from tryLock().
If the lock was obtained, the mutex must be unlocked with unlock() If the lock was obtained, the mutex must be unlocked with unlock()
before another thread can successfully lock it. before another thread can successfully lock it.
@ -303,7 +303,7 @@ bool QMutex::tryLock(int timeout) QT_MUTEX_LOCK_NOEXCEPT
for the mutex to become available. for the mutex to become available.
Note: Passing a \a timePoint which has already passed is equivalent Note: Passing a \a timePoint which has already passed is equivalent
to calling try_lock. This behavior is different from tryLock. to calling try_lock(). This behavior differs from tryLock().
If the lock was obtained, the mutex must be unlocked with unlock() If the lock was obtained, the mutex must be unlocked with unlock()
before another thread can successfully lock it. before another thread can successfully lock it.

View File

@ -535,7 +535,7 @@ QT_DEPRECATED_X("Use std::binary_search") Q_OUTOFLINE_TEMPLATE RandomAccessItera
# define QT_HAS_BUILTIN_CTZS # define QT_HAS_BUILTIN_CTZS
Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_ctzs(quint16 v) Q_DECL_NOTHROW Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_ctzs(quint16 v) Q_DECL_NOTHROW
{ {
# if QT_HAS_BUILTIN(__builtin_ctzs) || defined(__BMI__) # if QT_HAS_BUILTIN(__builtin_ctzs)
return __builtin_ctzs(v); return __builtin_ctzs(v);
# else # else
return __builtin_ctz(v); return __builtin_ctz(v);
@ -544,7 +544,7 @@ Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_ctzs(quint16 v) Q_DECL_NOTHROW
#define QT_HAS_BUILTIN_CLZS #define QT_HAS_BUILTIN_CLZS
Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_clzs(quint16 v) Q_DECL_NOTHROW Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_clzs(quint16 v) Q_DECL_NOTHROW
{ {
# if QT_HAS_BUILTIN(__builtin_clzs) || defined(__BMI__) # if QT_HAS_BUILTIN(__builtin_clzs)
return __builtin_clzs(v); return __builtin_clzs(v);
# else # else
return __builtin_clz(v) - 16U; return __builtin_clz(v) - 16U;

View File

@ -94,17 +94,17 @@ public:
}; };
explicit QBmpHandler(InternalFormat fmt = BmpFormat); explicit QBmpHandler(InternalFormat fmt = BmpFormat);
bool canRead() const; bool canRead() const override;
bool read(QImage *image); bool read(QImage *image) override;
bool write(const QImage &image); bool write(const QImage &image) override;
QByteArray name() const; QByteArray name() const override;
static bool canRead(QIODevice *device); static bool canRead(QIODevice *device);
QVariant option(ImageOption option) const; QVariant option(ImageOption option) const override;
void setOption(ImageOption option, const QVariant &value); void setOption(ImageOption option, const QVariant &value) override;
bool supportsOption(ImageOption option) const; bool supportsOption(ImageOption option) const override;
private: private:
bool readHeader(); bool readHeader();

View File

@ -91,6 +91,14 @@ QIconEngine::QIconEngine()
{ {
} }
/*!
\since 5.8
\internal
*/
QIconEngine::QIconEngine(const QIconEngine &)
{
}
/*! /*!
Destroys the icon engine. Destroys the icon engine.
*/ */

View File

@ -51,6 +51,7 @@ class Q_GUI_EXPORT QIconEngine
{ {
public: public:
QIconEngine(); QIconEngine();
QIconEngine(const QIconEngine &other); // ### Qt6: make protected
virtual ~QIconEngine(); virtual ~QIconEngine();
virtual void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) = 0; virtual void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) = 0;
virtual QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state); virtual QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state);
@ -80,6 +81,9 @@ public:
bool isNull() const; // ### Qt6 make virtual bool isNull() const; // ### Qt6 make virtual
virtual void virtual_hook(int id, void *data); virtual void virtual_hook(int id, void *data);
private:
QIconEngine &operator=(const QIconEngine &other) Q_DECL_EQ_DELETE;
}; };
#if QT_DEPRECATED_SINCE(5, 0) #if QT_DEPRECATED_SINCE(5, 0)

View File

@ -596,37 +596,6 @@ bool QImageData::checkForAlphaPixels() const
\endtable \endtable
\target qimage-legalese
\section1 Legal Information
For smooth scaling, the transformed() functions use code based on
smooth scaling algorithm by Daniel M. Duley.
\badcode
Copyright (C) 2004, 2005 Daniel M. Duley
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\endcode
\sa QImageReader, QImageWriter, QPixmap, QSvgRenderer, {Image Composition Example}, \sa QImageReader, QImageWriter, QPixmap, QSvgRenderer, {Image Composition Example},
{Image Viewer Example}, {Scribble Example}, {Pixelator Example} {Image Viewer Example}, {Scribble Example}, {Pixelator Example}
*/ */

View File

@ -65,15 +65,15 @@ public:
QPngHandler(); QPngHandler();
~QPngHandler(); ~QPngHandler();
bool canRead() const; bool canRead() const override;
bool read(QImage *image); bool read(QImage *image) override;
bool write(const QImage &image); bool write(const QImage &image) override;
QByteArray name() const; QByteArray name() const override;
QVariant option(ImageOption option) const; QVariant option(ImageOption option) const override;
void setOption(ImageOption option, const QVariant &value); void setOption(ImageOption option, const QVariant &value) override;
bool supportsOption(ImageOption option) const; bool supportsOption(ImageOption option) const override;
static bool canRead(QIODevice *device); static bool canRead(QIODevice *device);

View File

@ -63,17 +63,17 @@ class QPpmHandler : public QImageIOHandler
{ {
public: public:
QPpmHandler(); QPpmHandler();
bool canRead() const; bool canRead() const override;
bool read(QImage *image); bool read(QImage *image) override;
bool write(const QImage &image); bool write(const QImage &image) override;
QByteArray name() const; QByteArray name() const override;
static bool canRead(QIODevice *device, QByteArray *subType = 0); static bool canRead(QIODevice *device, QByteArray *subType = 0);
QVariant option(ImageOption option) const; QVariant option(ImageOption option) const override;
void setOption(ImageOption option, const QVariant &value); void setOption(ImageOption option, const QVariant &value) override;
bool supportsOption(ImageOption option) const; bool supportsOption(ImageOption option) const override;
private: private:
bool readHeader(); bool readHeader();

View File

@ -62,17 +62,17 @@ class QXbmHandler : public QImageIOHandler
{ {
public: public:
QXbmHandler(); QXbmHandler();
bool canRead() const; bool canRead() const override;
bool read(QImage *image); bool read(QImage *image) override;
bool write(const QImage &image); bool write(const QImage &image) override;
QByteArray name() const; QByteArray name() const override;
static bool canRead(QIODevice *device); static bool canRead(QIODevice *device);
QVariant option(ImageOption option) const; QVariant option(ImageOption option) const override;
void setOption(ImageOption option, const QVariant &value); void setOption(ImageOption option, const QVariant &value) override;
bool supportsOption(ImageOption option) const; bool supportsOption(ImageOption option) const override;
private: private:
bool readHeader(); bool readHeader();

View File

@ -62,17 +62,17 @@ class QXpmHandler : public QImageIOHandler
{ {
public: public:
QXpmHandler(); QXpmHandler();
bool canRead() const; bool canRead() const override;
bool read(QImage *image); bool read(QImage *image) override;
bool write(const QImage &image); bool write(const QImage &image) override;
static bool canRead(QIODevice *device); static bool canRead(QIODevice *device);
QByteArray name() const; QByteArray name() const override;
QVariant option(ImageOption option) const; QVariant option(ImageOption option) const override;
void setOption(ImageOption option, const QVariant &value); void setOption(ImageOption option, const QVariant &value) override;
bool supportsOption(ImageOption option) const; bool supportsOption(ImageOption option) const override;
private: private:
bool readHeader(); bool readHeader();

View File

@ -44,6 +44,7 @@
#include "qpa/qplatformdrag.h" #include "qpa/qplatformdrag.h"
#include "private/qevent_p.h" #include "private/qevent_p.h"
#include "qfile.h" #include "qfile.h"
#include "qhashfunctions.h"
#include "qmetaobject.h" #include "qmetaobject.h"
#include "qmimedata.h" #include "qmimedata.h"
#include "private/qdnd_p.h" #include "private/qdnd_p.h"
@ -4474,14 +4475,14 @@ int QTouchEvent::TouchPoint::id() const
\since 5.8 \since 5.8
Returns the unique ID of this touch point or token, if any. Returns the unique ID of this touch point or token, if any.
It is normally invalid (with a \l {QPointerUniqueId::numeric()} {numeric()} value of -1), It is normally invalid (see \l {QPointingDeviceUniqueId::isValid()} {isValid()}),
because touchscreens cannot uniquely identify fingers. But when the because touchscreens cannot uniquely identify fingers. But when the
\l {TouchPoint::InfoFlag} {Token} flag is set, it is expected to uniquely \l {TouchPoint::InfoFlag} {Token} flag is set, it is expected to uniquely
identify a specific token (fiducial object). identify a specific token (fiducial object).
\sa flags \sa flags
*/ */
QPointerUniqueId QTouchEvent::TouchPoint::uniqueId() const QPointingDeviceUniqueId QTouchEvent::TouchPoint::uniqueId() const
{ {
return d->uniqueId; return d->uniqueId;
} }
@ -4757,7 +4758,7 @@ void QTouchEvent::TouchPoint::setUniqueId(qint64 uid)
{ {
if (d->ref.load() != 1) if (d->ref.load() != 1)
d = d->detach(); d = d->detach();
d->uniqueId = QPointerUniqueId(uid); d->uniqueId = QPointingDeviceUniqueId::fromNumericId(uid);
} }
/*! \internal */ /*! \internal */
@ -5176,36 +5177,99 @@ Qt::ApplicationState QApplicationStateChangeEvent::applicationState() const
} }
/*! /*!
\class QPointerUniqueId \class QPointingDeviceUniqueId
\since 5.8 \since 5.8
\ingroup events \ingroup events
\inmodule QtGui \inmodule QtGui
\brief QPointerUniqueId identifies a unique object, such as a tagged token \brief QPointingDeviceUniqueId identifies a unique object, such as a tagged token
or stylus, which is used with a pointing device. or stylus, which is used with a pointing device.
QPointingDeviceUniqueIds can be compared for equality, and can be used as keys in a QHash.
You get access to the numerical ID via numericId(), if the device supports such IDs.
For future extensions, though, you should not use that function, but compare objects
of this type using the equality operator.
This class is a thin wrapper around an integer ID. You pass it into and out of
functions by value.
This type actively prevents you from holding it in a QList, because doing so would
be very inefficient. Use a QVector instead, which has the same API as QList, but more
efficient storage.
\sa QTouchEvent::TouchPoint \sa QTouchEvent::TouchPoint
*/ */
/*! /*!
Constructs a unique pointer ID with a numeric \a id provided by the hardware. \fn QPointingDeviceUniqueId::QPointingDeviceUniqueId()
The default is -1, which means an invalid pointer ID. Constructs an invalid unique pointer ID.
*/ */
QPointerUniqueId::QPointerUniqueId(qint64 id)
: m_numericId(id) /*!
Constructs a unique pointer ID from numeric ID \a id.
*/
QPointingDeviceUniqueId QPointingDeviceUniqueId::fromNumericId(qint64 id)
{ {
QPointingDeviceUniqueId result;
result.m_numericId = id;
return result;
} }
/*! /*!
\property QPointerUniqueId::numeric \fn bool QPointingDeviceUniqueId::isValid() const
Returns whether this unique pointer ID is valid, that is, it represents an actual
pointer.
*/
/*!
\property QPointingDeviceUniqueId::numericId
\brief the numeric unique ID of the token represented by a touchpoint \brief the numeric unique ID of the token represented by a touchpoint
This is the numeric unique ID if the device provides that type of ID; If the device provides a numeric ID, isValid() returns true, and this
property provides the numeric ID;
otherwise it is -1. otherwise it is -1.
You should not use the value of this property in portable code, but
instead rely on equality to identify pointers.
\sa isValid()
*/ */
qint64 QPointerUniqueId::numeric() const qint64 QPointingDeviceUniqueId::numericId() const Q_DECL_NOTHROW
{ {
return m_numericId; return m_numericId;
} }
/*!
\relates QPointingDeviceUniqueId
\since 5.8
Returns whether the two unique pointer IDs \a lhs and \a rhs identify the same pointer
(\c true) or not (\c false).
*/
bool operator==(QPointingDeviceUniqueId lhs, QPointingDeviceUniqueId rhs) Q_DECL_NOTHROW
{
return lhs.numericId() == rhs.numericId();
}
/*!
\fn bool operator!=(QPointingDeviceUniqueId lhs, QPointingDeviceUniqueId rhs)
\relates QPointingDeviceUniqueId
\since 5.8
Returns whether the two unique pointer IDs \a lhs and \a rhs identify different pointers
(\c true) or not (\c false).
*/
/*!
\relates QPointingDeviceUniqueId
\since 5.8
Returns the hash value for \a key, using \a seed to seed the calculation.
*/
uint qHash(QPointingDeviceUniqueId key, uint seed) Q_DECL_NOTHROW
{
return qHash(key.numericId(), seed);
}
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -793,21 +793,36 @@ inline bool operator==(QKeyEvent *e, QKeySequence::StandardKey key){return (e ?
inline bool operator==(QKeySequence::StandardKey key, QKeyEvent *e){return (e ? e->matches(key) : false);} inline bool operator==(QKeySequence::StandardKey key, QKeyEvent *e){return (e ? e->matches(key) : false);}
#endif // QT_NO_SHORTCUT #endif // QT_NO_SHORTCUT
class QPointerUniqueIdPrivate; class Q_GUI_EXPORT QPointingDeviceUniqueId
class Q_GUI_EXPORT QPointerUniqueId
{ {
Q_GADGET Q_GADGET
Q_PROPERTY(qint64 numeric READ numeric CONSTANT) Q_PROPERTY(qint64 numericId READ numericId CONSTANT)
public: public:
explicit QPointerUniqueId(qint64 id = -1); Q_ALWAYS_INLINE
Q_DECL_CONSTEXPR QPointingDeviceUniqueId() Q_DECL_NOTHROW : m_numericId(-1) {}
// compiler-generated copy/move ctor/assignment operators are ok!
// compiler-generated dtor is ok!
qint64 numeric() const; static QPointingDeviceUniqueId fromNumericId(qint64 id);
Q_ALWAYS_INLINE Q_DECL_CONSTEXPR bool isValid() const Q_DECL_NOTHROW { return m_numericId != -1; }
qint64 numericId() const Q_DECL_NOTHROW;
private: private:
// TODO for TUIO 2, or any other type of complex token ID, a d-pointer can replace // TODO: for TUIO 2, or any other type of complex token ID, an internal
// m_numericId without changing the size of this class. // array (or hash) can be added to hold additional properties.
// In this case, m_numericId will then turn into an index into that array (or hash).
qint64 m_numericId; qint64 m_numericId;
}; };
Q_DECLARE_TYPEINFO(QPointingDeviceUniqueId, Q_MOVABLE_TYPE);
template <> class QList<QPointingDeviceUniqueId> {}; // to prevent instantiation: use QVector instead
Q_GUI_EXPORT bool operator==(QPointingDeviceUniqueId lhs, QPointingDeviceUniqueId rhs) Q_DECL_NOTHROW;
inline bool operator!=(QPointingDeviceUniqueId lhs, QPointingDeviceUniqueId rhs) Q_DECL_NOTHROW
{ return !operator==(lhs, rhs); }
Q_GUI_EXPORT uint qHash(QPointingDeviceUniqueId key, uint seed = 0) Q_DECL_NOTHROW;
class QTouchEventTouchPointPrivate; class QTouchEventTouchPointPrivate;
class Q_GUI_EXPORT QTouchEvent : public QInputEvent class Q_GUI_EXPORT QTouchEvent : public QInputEvent
@ -844,7 +859,7 @@ public:
{ qSwap(d, other.d); } { qSwap(d, other.d); }
int id() const; int id() const;
QPointerUniqueId uniqueId() const; QPointingDeviceUniqueId uniqueId() const;
Qt::TouchPointState state() const; Qt::TouchPointState state() const;

View File

@ -80,7 +80,7 @@ public:
QAtomicInt ref; QAtomicInt ref;
int id; int id;
QPointerUniqueId uniqueId; QPointingDeviceUniqueId uniqueId;
Qt::TouchPointStates state; Qt::TouchPointStates state;
QRectF rect, sceneRect, screenRect; QRectF rect, sceneRect, screenRect;
QPointF normalizedPos, QPointF normalizedPos,

View File

@ -129,7 +129,7 @@ public:
TouchPoint() : id(0), uniqueId(-1), pressure(0), rotation(0), state(Qt::TouchPointStationary) { } TouchPoint() : id(0), uniqueId(-1), pressure(0), rotation(0), state(Qt::TouchPointStationary) { }
int id; // for application use int id; // for application use
qint64 uniqueId; // for TUIO: object/token ID; otherwise empty qint64 uniqueId; // for TUIO: object/token ID; otherwise empty
// TODO for TUIO 2.0: add registerPointerUniqueID(QPointerUniqueId) // TODO for TUIO 2.0: add registerPointerUniqueID(QPointingDeviceUniqueId)
QPointF normalPosition; // touch device coordinates, (0 to 1, 0 to 1) QPointF normalPosition; // touch device coordinates, (0 to 1, 0 to 1)
QRectF area; // the touched area, centered at position in screen coordinates QRectF area; // the touched area, centered at position in screen coordinates
qreal pressure; // 0 to 1 qreal pressure; // 0 to 1

View File

@ -61,8 +61,8 @@ public:
QOpenGLPaintDevice(int width, int height); QOpenGLPaintDevice(int width, int height);
virtual ~QOpenGLPaintDevice(); virtual ~QOpenGLPaintDevice();
int devType() const { return QInternal::OpenGL; } int devType() const override { return QInternal::OpenGL; }
QPaintEngine *paintEngine() const; QPaintEngine *paintEngine() const override;
QOpenGLContext *context() const; QOpenGLContext *context() const;
QSize size() const; QSize size() const;
@ -82,7 +82,7 @@ public:
protected: protected:
QOpenGLPaintDevice(QOpenGLPaintDevicePrivate &dd); QOpenGLPaintDevice(QOpenGLPaintDevicePrivate &dd);
int metric(QPaintDevice::PaintDeviceMetric metric) const; int metric(QPaintDevice::PaintDeviceMetric metric) const override;
Q_DISABLE_COPY(QOpenGLPaintDevice) Q_DISABLE_COPY(QOpenGLPaintDevice)
QScopedPointer<QOpenGLPaintDevicePrivate> d_ptr; QScopedPointer<QOpenGLPaintDevicePrivate> d_ptr;

View File

@ -0,0 +1,60 @@
qimagetransform.cpp was contributed by Daniel M. Duley based on code from Imlib2.
Copyright (C) 2004, 2005 Daniel M. Duley
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Imlib2 License
Copyright (C) 2000 Carsten Haitzler and various contributors (see
AUTHORS)
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies of the Software and its Copyright notices. In addition
publicly documented acknowledgment must be given that this software has
been used if no source code of this software is made available publicly.
This includes acknowledgments in either Copyright notices, Manuals,
Publicity and Marketing documents or any documentation provided with any
product containing this software. This License does not apply to any
software that links to the libraries provided by this software
(statically or dynamically), but only to the software provided.
Please see the COPYING.PLAIN for a plain-english explanation of this
notice and it's intent.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

View File

@ -1581,7 +1581,7 @@ static const uint *QT_FASTCALL fetchTransformed(uint *buffer, const Operator *,
if (bpp != QPixelLayout::BPPNone) // Like this to not ICE on GCC 5.3.1 if (bpp != QPixelLayout::BPPNone) // Like this to not ICE on GCC 5.3.1
Q_ASSERT(layout->bpp == bpp); Q_ASSERT(layout->bpp == bpp);
// When templated 'fetch' should be inlined at compile time: // When templated 'fetch' should be inlined at compile time:
const FetchPixelFunc fetch = (bpp == QPixelLayout::BPPNone) ? qFetchPixel[layout->bpp] : fetchPixel<bpp>; const FetchPixelFunc fetch = (bpp == QPixelLayout::BPPNone) ? qFetchPixel[layout->bpp] : FetchPixelFunc(fetchPixel<bpp>);
uint *const end = buffer + length; uint *const end = buffer + length;
uint *b = buffer; uint *b = buffer;
@ -2532,8 +2532,8 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
if (bpp != QPixelLayout::BPPNone) // Like this to not ICE on GCC 5.3.1 if (bpp != QPixelLayout::BPPNone) // Like this to not ICE on GCC 5.3.1
Q_ASSERT(layout->bpp == bpp); Q_ASSERT(layout->bpp == bpp);
// When templated 'fetch' should be inlined at compile time: // When templated 'fetch' should be inlined at compile time:
const FetchPixelsFunc fetch = (bpp == QPixelLayout::BPPNone) ? qFetchPixels[layout->bpp] : fetchPixels<bpp>; const FetchPixelsFunc fetch = (bpp == QPixelLayout::BPPNone) ? qFetchPixels[layout->bpp] : FetchPixelsFunc(fetchPixels<bpp>);
const FetchPixelFunc fetch1 = (bpp == QPixelLayout::BPPNone) ? qFetchPixel[layout->bpp] : fetchPixel<bpp>; const FetchPixelFunc fetch1 = (bpp == QPixelLayout::BPPNone) ? qFetchPixel[layout->bpp] : FetchPixelFunc(fetchPixel<bpp>);
int image_width = data->texture.width; int image_width = data->texture.width;
int image_height = data->texture.height; int image_height = data->texture.height;

View File

@ -62,37 +62,37 @@ class QEmulationPaintEngine : public QPaintEngineEx
public: public:
QEmulationPaintEngine(QPaintEngineEx *engine); QEmulationPaintEngine(QPaintEngineEx *engine);
virtual bool begin(QPaintDevice *pdev); bool begin(QPaintDevice *pdev) override;
virtual bool end(); bool end() override;
virtual Type type() const; Type type() const override;
virtual QPainterState *createState(QPainterState *orig) const; QPainterState *createState(QPainterState *orig) const override;
virtual void fill(const QVectorPath &path, const QBrush &brush); void fill(const QVectorPath &path, const QBrush &brush) override;
virtual void stroke(const QVectorPath &path, const QPen &pen); void stroke(const QVectorPath &path, const QPen &pen) override;
virtual void clip(const QVectorPath &path, Qt::ClipOperation op); void clip(const QVectorPath &path, Qt::ClipOperation op) override;
virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) override;
virtual void drawTextItem(const QPointF &p, const QTextItem &textItem); void drawTextItem(const QPointF &p, const QTextItem &textItem) override;
virtual void drawStaticTextItem(QStaticTextItem *item); void drawStaticTextItem(QStaticTextItem *item) override;
virtual void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s); void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s) override;
virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags); void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags) override;
virtual void clipEnabledChanged(); void clipEnabledChanged() override;
virtual void penChanged(); void penChanged() override;
virtual void brushChanged(); void brushChanged() override;
virtual void brushOriginChanged(); void brushOriginChanged() override;
virtual void opacityChanged(); void opacityChanged() override;
virtual void compositionModeChanged(); void compositionModeChanged() override;
virtual void renderHintsChanged(); void renderHintsChanged() override;
virtual void transformChanged(); void transformChanged() override;
virtual void setState(QPainterState *s); void setState(QPainterState *s) override;
virtual void beginNativePainting(); void beginNativePainting() override;
virtual void endNativePainting(); void endNativePainting() override;
virtual uint flags() const {return QPaintEngineEx::IsEmulationEngine | QPaintEngineEx::DoNotEmulate;} uint flags() const override { return QPaintEngineEx::IsEmulationEngine | QPaintEngineEx::DoNotEmulate; }
inline QPainterState *state() { return (QPainterState *)QPaintEngine::state; } inline QPainterState *state() { return (QPainterState *)QPaintEngine::state; }
inline const QPainterState *state() const { return (const QPainterState *)QPaintEngine::state; } inline const QPainterState *state() const { return (const QPainterState *)QPaintEngine::state; }

View File

@ -287,7 +287,7 @@ public:
void rasterize(QT_FT_Outline *outline, ProcessSpans callback, void *userData, QRasterBuffer *rasterBuffer); void rasterize(QT_FT_Outline *outline, ProcessSpans callback, void *userData, QRasterBuffer *rasterBuffer);
void updateMatrixData(QSpanData *spanData, const QBrush &brush, const QTransform &brushMatrix); void updateMatrixData(QSpanData *spanData, const QBrush &brush, const QTransform &brushMatrix);
void systemStateChanged(); void systemStateChanged() override;
void drawImage(const QPointF &pt, const QImage &img, SrcOverBlendFunc func, void drawImage(const QPointF &pt, const QImage &img, SrcOverBlendFunc func,
const QRect &clip, int alpha, const QRect &sr = QRect()); const QRect &clip, int alpha, const QRect &sr = QRect());

View File

@ -67,7 +67,7 @@ public:
QString creator() const; QString creator() const;
void setCreator(const QString &creator); void setCreator(const QString &creator);
bool newPage(); bool newPage() override;
void setResolution(int resolution); void setResolution(int resolution);
int resolution() const; int resolution() const;
@ -83,14 +83,14 @@ public:
using QPagedPaintDevice::setPageSize; using QPagedPaintDevice::setPageSize;
#endif #endif
void setPageSize(PageSize size); void setPageSize(PageSize size) override;
void setPageSizeMM(const QSizeF &size); void setPageSizeMM(const QSizeF &size) override;
void setMargins(const Margins &m); void setMargins(const Margins &m) override;
protected: protected:
QPaintEngine *paintEngine() const; QPaintEngine *paintEngine() const override;
int metric(PaintDeviceMetric id) const; int metric(PaintDeviceMetric id) const override;
private: private:
Q_DISABLE_COPY(QPdfWriter) Q_DISABLE_COPY(QPdfWriter)

View File

@ -234,7 +234,7 @@ protected:
static Qt::PenJoinStyle joinForJoinMode(LineJoinMode mode); static Qt::PenJoinStyle joinForJoinMode(LineJoinMode mode);
static LineJoinMode joinModeForJoin(Qt::PenJoinStyle joinStyle); static LineJoinMode joinModeForJoin(Qt::PenJoinStyle joinStyle);
virtual void processCurrentSubpath(); void processCurrentSubpath() override;
qfixed m_strokeWidth; qfixed m_strokeWidth;
qfixed m_miterLimit; qfixed m_miterLimit;
@ -265,14 +265,14 @@ public:
void setDashOffset(qreal offset) { m_dashOffset = offset; } void setDashOffset(qreal offset) { m_dashOffset = offset; }
qreal dashOffset() const { return m_dashOffset; } qreal dashOffset() const { return m_dashOffset; }
virtual void begin(void *data); void begin(void *data) override;
virtual void end(); void end() override;
inline void setStrokeWidth(qreal width) { m_stroke_width = width; } inline void setStrokeWidth(qreal width) { m_stroke_width = width; }
inline void setMiterLimit(qreal limit) { m_miter_limit = limit; } inline void setMiterLimit(qreal limit) { m_miter_limit = limit; }
protected: protected:
virtual void processCurrentSubpath(); void processCurrentSubpath() override;
QStroker *m_stroker; QStroker *m_stroker;
QVector<qfixed> m_dashPattern; QVector<qfixed> m_dashPattern;

View File

@ -1,14 +1,31 @@
{ [
"Id": "grayraster", {
"Name": "Anti-aliasing rasterizer from FreeType 2", "Id": "grayraster",
"QDocModule": "qtgui", "Name": "Anti-aliasing rasterizer from FreeType 2",
"QtUsage": "Used in Qt GUI.", "QDocModule": "qtgui",
"Path": "qgrayraster.c", "QtUsage": "Used in Qt GUI.",
"Path": "qgrayraster.c",
"Description": "FreeType is a freely available software library to render fonts.", "Description": "FreeType is a freely available software library to render fonts.",
"Homepage": "http://www.freetype.org", "Homepage": "http://www.freetype.org",
"License": "Freetype Project License or GNU General Public License v2.0 only", "License": "Freetype Project License or GNU General Public License v2.0 only",
"LicenseId": "FTL or GPL-2.0", "LicenseId": "FTL or GPL-2.0",
"LicenseFile": "../../3rdparty/freetype/docs/LICENSE.TXT", "LicenseFile": "../../3rdparty/freetype/docs/LICENSE.TXT",
"Copyright": "Copyright 2006-2015 by David Turner, Robert Wilhelm, and Werner Lemberg." "Copyright": "Copyright 2006-2015 by David Turner, Robert Wilhelm, and Werner Lemberg."
} },
{
"Id": "smooth-scaling-algorithm",
"Name": "Smooth Scaling Algorithm",
"QDocModule": "qtgui",
"QtUsage": "Used in Qt Gui (QImage::transformed() functions).",
"Files": "qimagescale.cpp",
"Description": "Normal smoothscale method, based on Imlib2's smoothscale.",
"LicenseId": "BSD-2-Clause AND Imlib2",
"License": "BSD 2-clause \"Simplified\" License and Imlib2 License",
"LicenseFile": "QIMAGETRANSFORM_LICENSE.txt",
"Copyright": "Copyright (C) 2004, 2005 Daniel M. Duley.
(C) Carsten Haitzler and various contributors.
(C) Willem Monsuwe <willem@stack.nl>"
}
]

View File

@ -118,6 +118,7 @@ QHttpNetworkConnectionPrivate::~QHttpNetworkConnectionPrivate()
{ {
for (int i = 0; i < channelCount; ++i) { for (int i = 0; i < channelCount; ++i) {
if (channels[i].socket) { if (channels[i].socket) {
QObject::disconnect(channels[i].socket, Q_NULLPTR, &channels[i], Q_NULLPTR);
channels[i].socket->close(); channels[i].socket->close();
delete channels[i].socket; delete channels[i].socket;
} }

View File

@ -517,6 +517,19 @@ QHostAddress::QHostAddress(const QHostAddress &address)
QHostAddress::QHostAddress(SpecialAddress address) QHostAddress::QHostAddress(SpecialAddress address)
: d(new QHostAddressPrivate) : d(new QHostAddressPrivate)
{ {
setAddress(address);
}
/*!
\overload
\since 5.8
Sets the special address specified by \a address.
*/
void QHostAddress::setAddress(SpecialAddress address)
{
d->clear();
Q_IPV6ADDR ip6; Q_IPV6ADDR ip6;
memset(&ip6, 0, sizeof ip6); memset(&ip6, 0, sizeof ip6);
quint32 ip4 = INADDR_ANY; quint32 ip4 = INADDR_ANY;
@ -567,6 +580,7 @@ QHostAddress &QHostAddress::operator=(const QHostAddress &address)
return *this; return *this;
} }
#if QT_DEPRECATED_SINCE(5, 8)
/*! /*!
Assigns the host address \a address to this object, and returns a Assigns the host address \a address to this object, and returns a
reference to this object. reference to this object.
@ -578,6 +592,20 @@ QHostAddress &QHostAddress::operator=(const QString &address)
setAddress(address); setAddress(address);
return *this; return *this;
} }
#endif
/*!
\since 5.8
Assigns the special address \a address to this object, and returns a
reference to this object.
\sa setAddress()
*/
QHostAddress &QHostAddress::operator=(SpecialAddress address)
{
setAddress(address);
return *this;
}
/*! /*!
\fn bool QHostAddress::operator!=(const QHostAddress &other) const \fn bool QHostAddress::operator!=(const QHostAddress &other) const

View File

@ -108,7 +108,11 @@ public:
#endif #endif
QHostAddress &operator=(const QHostAddress &other); QHostAddress &operator=(const QHostAddress &other);
#if QT_DEPRECATED_SINCE(5, 8)
QT_DEPRECATED_X("use = QHostAddress(string) instead")
QHostAddress &operator=(const QString &address); QHostAddress &operator=(const QString &address);
#endif
QHostAddress &operator=(SpecialAddress address);
void swap(QHostAddress &other) Q_DECL_NOTHROW { d.swap(other.d); } void swap(QHostAddress &other) Q_DECL_NOTHROW { d.swap(other.d); }
@ -118,6 +122,7 @@ public:
void setAddress(const Q_IPV6ADDR &ip6Addr); void setAddress(const Q_IPV6ADDR &ip6Addr);
void setAddress(const sockaddr *address); void setAddress(const sockaddr *address);
bool setAddress(const QString &address); bool setAddress(const QString &address);
void setAddress(SpecialAddress address);
QAbstractSocket::NetworkLayerProtocol protocol() const; QAbstractSocket::NetworkLayerProtocol protocol() const;
quint32 toIPv4Address() const; // ### Qt6: merge with next overload quint32 toIPv4Address() const; // ### Qt6: merge with next overload

View File

@ -126,6 +126,33 @@ static HRESULT qt_winrt_try_create_thread_network_context(QString host, ComPtr<I
} }
#endif // _MSC_VER >= 1900 #endif // _MSC_VER >= 1900
typedef QHash<qintptr, IStreamSocket *> TcpSocketHash;
struct SocketHandler
{
SocketHandler() : socketCount(0) {}
qintptr socketCount;
TcpSocketHash pendingTcpSockets;
};
Q_GLOBAL_STATIC(SocketHandler, gSocketHandler)
struct SocketGlobal
{
SocketGlobal()
{
HRESULT hr;
hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(),
&bufferFactory);
Q_ASSERT_SUCCEEDED(hr);
}
ComPtr<IBufferFactory> bufferFactory;
};
Q_GLOBAL_STATIC(SocketGlobal, g)
#define READ_BUFFER_SIZE 65536
static inline QString qt_QStringFromHString(const HString &string) static inline QString qt_QStringFromHString(const HString &string)
{ {
UINT32 length; UINT32 length;
@ -136,8 +163,43 @@ static inline QString qt_QStringFromHString(const HString &string)
class SocketEngineWorker : public QObject class SocketEngineWorker : public QObject
{ {
Q_OBJECT Q_OBJECT
public:
SocketEngineWorker(QNativeSocketEnginePrivate *engine)
: enginePrivate(engine)
{
}
~SocketEngineWorker()
{
if (Q_UNLIKELY(initialReadOp)) {
ComPtr<IAsyncInfo> info;
HRESULT hr = initialReadOp.As(&info);
Q_ASSERT_SUCCEEDED(hr);
if (info) {
hr = info->Cancel();
Q_ASSERT_SUCCEEDED(hr);
hr = info->Close();
Q_ASSERT_SUCCEEDED(hr);
}
}
if (readOp) {
ComPtr<IAsyncInfo> info;
HRESULT hr = readOp.As(&info);
Q_ASSERT_SUCCEEDED(hr);
if (info) {
hr = info->Cancel();
Q_ASSERT_SUCCEEDED(hr);
hr = info->Close();
Q_ASSERT_SUCCEEDED(hr);
}
}
}
signals: signals:
void newDatagramsReceived(const QList<WinRtDatagram> &datagram); void newDatagramsReceived(const QList<WinRtDatagram> &datagram);
void newDataReceived(const QVector<QByteArray> &data);
void socketErrorOccured(QAbstractSocket::SocketError error);
public slots: public slots:
Q_INVOKABLE void notifyAboutNewDatagrams() Q_INVOKABLE void notifyAboutNewDatagrams()
@ -148,7 +210,30 @@ public slots:
emit newDatagramsReceived(datagrams); emit newDatagramsReceived(datagrams);
} }
Q_INVOKABLE void notifyAboutNewData()
{
QMutexLocker locker(&mutex);
const QVector<QByteArray> newData = std::move(pendingData);
pendingData.clear();
emit newDataReceived(newData);
}
public: public:
void startReading()
{
ComPtr<IBuffer> buffer;
HRESULT hr = g->bufferFactory->Create(READ_BUFFER_SIZE, &buffer);
Q_ASSERT_SUCCEEDED(hr);
ComPtr<IInputStream> stream;
hr = tcpSocket->get_InputStream(&stream);
Q_ASSERT_SUCCEEDED(hr);
hr = stream->ReadAsync(buffer.Get(), READ_BUFFER_SIZE, InputStreamOptions_Partial, initialReadOp.GetAddressOf());
Q_ASSERT_SUCCEEDED(hr);
enginePrivate->socketState = QAbstractSocket::ConnectedState;
hr = initialReadOp->put_Completed(Callback<SocketReadCompletedHandler>(this, &SocketEngineWorker::onReadyRead).Get());
Q_ASSERT_SUCCEEDED(hr);
}
HRESULT OnNewDatagramReceived(IDatagramSocket *, IDatagramSocketMessageReceivedEventArgs *args) HRESULT OnNewDatagramReceived(IDatagramSocket *, IDatagramSocketMessageReceivedEventArgs *args)
{ {
WinRtDatagram datagram; WinRtDatagram datagram;
@ -184,9 +269,127 @@ public:
return S_OK; return S_OK;
} }
HRESULT onReadyRead(IAsyncBufferOperation *asyncInfo, AsyncStatus status)
{
if (asyncInfo == initialReadOp.Get()) {
initialReadOp.Reset();
} else if (asyncInfo == readOp.Get()) {
readOp.Reset();
} else {
Q_ASSERT(false);
}
// A read in UnconnectedState will close the socket and return -1 and thus tell the caller,
// that the connection was closed. The socket cannot be closed here, as the subsequent read
// might fail then.
if (status == Error || status == Canceled) {
emit socketErrorOccured(QAbstractSocket::RemoteHostClosedError);
return S_OK;
}
ComPtr<IBuffer> buffer;
HRESULT hr = asyncInfo->GetResults(&buffer);
if (FAILED(hr)) {
qErrnoWarning(hr, "Failed to get read results buffer");
emit socketErrorOccured(QAbstractSocket::UnknownSocketError);
return S_OK;
}
UINT32 bufferLength;
hr = buffer->get_Length(&bufferLength);
if (FAILED(hr)) {
qErrnoWarning(hr, "Failed to get buffer length");
emit socketErrorOccured(QAbstractSocket::UnknownSocketError);
return S_OK;
}
// A zero sized buffer length signals, that the remote host closed the connection. The socket
// cannot be closed though, as the following read might have socket descriptor -1 and thus and
// the closing of the socket won't be communicated to the caller. So only the error is set. The
// actual socket close happens inside of read.
if (!bufferLength) {
emit socketErrorOccured(QAbstractSocket::RemoteHostClosedError);
return S_OK;
}
ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteArrayAccess;
hr = buffer.As(&byteArrayAccess);
if (FAILED(hr)) {
qErrnoWarning(hr, "Failed to get cast buffer");
emit socketErrorOccured(QAbstractSocket::UnknownSocketError);
return S_OK;
}
byte *data;
hr = byteArrayAccess->Buffer(&data);
if (FAILED(hr)) {
qErrnoWarning(hr, "Failed to access buffer data");
emit socketErrorOccured(QAbstractSocket::UnknownSocketError);
return S_OK;
}
QByteArray newData(reinterpret_cast<const char*>(data), qint64(bufferLength));
QMutexLocker readLocker(&mutex);
if (pendingData.isEmpty())
QMetaObject::invokeMethod(this, "notifyAboutNewData", Qt::QueuedConnection);
pendingData << newData;
readLocker.unlock();
hr = QEventDispatcherWinRT::runOnXamlThread([buffer, this]() {
UINT32 readBufferLength;
ComPtr<IInputStream> stream;
HRESULT hr = tcpSocket->get_InputStream(&stream);
if (FAILED(hr)) {
qErrnoWarning(hr, "Failed to obtain input stream");
emit socketErrorOccured(QAbstractSocket::UnknownSocketError);
return S_OK;
}
// Reuse the stream buffer
hr = buffer->get_Capacity(&readBufferLength);
if (FAILED(hr)) {
qErrnoWarning(hr, "Failed to get buffer capacity");
emit socketErrorOccured(QAbstractSocket::UnknownSocketError);
return S_OK;
}
hr = buffer->put_Length(0);
if (FAILED(hr)) {
qErrnoWarning(hr, "Failed to set buffer length");
emit socketErrorOccured(QAbstractSocket::UnknownSocketError);
return S_OK;
}
hr = stream->ReadAsync(buffer.Get(), readBufferLength, InputStreamOptions_Partial, &readOp);
if (FAILED(hr)) {
qErrnoWarning(hr, "onReadyRead(): Could not read into socket stream buffer.");
emit socketErrorOccured(QAbstractSocket::UnknownSocketError);
return S_OK;
}
hr = readOp->put_Completed(Callback<SocketReadCompletedHandler>(this, &SocketEngineWorker::onReadyRead).Get());
if (FAILED(hr)) {
qErrnoWarning(hr, "onReadyRead(): Failed to set socket read callback.");
emit socketErrorOccured(QAbstractSocket::UnknownSocketError);
return S_OK;
}
return S_OK;
});
Q_ASSERT_SUCCEEDED(hr);
return S_OK;
}
void setTcpSocket(ComPtr<IStreamSocket> socket) { tcpSocket = socket; }
private: private:
ComPtr<IStreamSocket> tcpSocket;
QList<WinRtDatagram> pendingDatagrams; QList<WinRtDatagram> pendingDatagrams;
QVector<QByteArray> pendingData;
// Protects pendingData/pendingDatagrams which are accessed from native callbacks
QMutex mutex; QMutex mutex;
ComPtr<IAsyncOperationWithProgress<IBuffer *, UINT32>> initialReadOp;
ComPtr<IAsyncOperationWithProgress<IBuffer *, UINT32>> readOp;
QNativeSocketEnginePrivate *enginePrivate;
}; };
static QByteArray socketDescription(const QAbstractSocketEngine *s) static QByteArray socketDescription(const QAbstractSocketEngine *s)
@ -239,33 +442,6 @@ static QByteArray socketDescription(const QAbstractSocketEngine *s)
} } while (0) } } while (0)
#define Q_TR(a) QT_TRANSLATE_NOOP(QNativeSocketEngine, a) #define Q_TR(a) QT_TRANSLATE_NOOP(QNativeSocketEngine, a)
typedef QHash<qintptr, IStreamSocket *> TcpSocketHash;
struct SocketHandler
{
SocketHandler() : socketCount(0) {}
qintptr socketCount;
TcpSocketHash pendingTcpSockets;
};
Q_GLOBAL_STATIC(SocketHandler, gSocketHandler)
struct SocketGlobal
{
SocketGlobal()
{
HRESULT hr;
hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(),
&bufferFactory);
Q_ASSERT_SUCCEEDED(hr);
}
ComPtr<IBufferFactory> bufferFactory;
};
Q_GLOBAL_STATIC(SocketGlobal, g)
#define READ_BUFFER_SIZE 65536
template <typename T> template <typename T>
static AsyncStatus opStatus(const ComPtr<T> &op) static AsyncStatus opStatus(const ComPtr<T> &op)
{ {
@ -315,6 +491,10 @@ QNativeSocketEngine::QNativeSocketEngine(QObject *parent)
connect(this, SIGNAL(readReady()), SLOT(readNotification()), Qt::QueuedConnection); connect(this, SIGNAL(readReady()), SLOT(readNotification()), Qt::QueuedConnection);
connect(this, SIGNAL(writeReady()), SLOT(writeNotification()), Qt::QueuedConnection); connect(this, SIGNAL(writeReady()), SLOT(writeNotification()), Qt::QueuedConnection);
connect(d->worker, &SocketEngineWorker::newDatagramsReceived, this, &QNativeSocketEngine::handleNewDatagrams, Qt::QueuedConnection); connect(d->worker, &SocketEngineWorker::newDatagramsReceived, this, &QNativeSocketEngine::handleNewDatagrams, Qt::QueuedConnection);
connect(d->worker, &SocketEngineWorker::newDataReceived,
this, &QNativeSocketEngine::handleNewData, Qt::QueuedConnection);
connect(d->worker, &SocketEngineWorker::socketErrorOccured,
this, &QNativeSocketEngine::handleTcpError, Qt::QueuedConnection);
} }
QNativeSocketEngine::~QNativeSocketEngine() QNativeSocketEngine::~QNativeSocketEngine()
@ -358,23 +538,9 @@ bool QNativeSocketEngine::initialize(qintptr socketDescriptor, QAbstractSocket::
// Start processing incoming data // Start processing incoming data
if (d->socketType == QAbstractSocket::TcpSocket) { if (d->socketType == QAbstractSocket::TcpSocket) {
HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([d, socket, socketState, this]() { HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([d, socket, this]() {
ComPtr<IBuffer> buffer; d->worker->setTcpSocket(socket);
HRESULT hr = g->bufferFactory->Create(READ_BUFFER_SIZE, &buffer); d->worker->startReading();
RETURN_HR_IF_FAILED("initialize(): Could not create buffer");
ComPtr<IInputStream> stream;
hr = socket->get_InputStream(&stream);
RETURN_HR_IF_FAILED("initialize(): Could not obtain input stream");
ComPtr<IAsyncBufferOperation> readOp;
hr = stream->ReadAsync(buffer.Get(), READ_BUFFER_SIZE, InputStreamOptions_Partial, readOp.GetAddressOf());
RETURN_HR_IF_FAILED_WITH_ARGS("initialize(): Failed to read from the socket buffer (%s).",
socketDescription(this).constData());
QMutexLocker locker(&d->readOperationsMutex);
d->pendingReadOps.append(readOp);
d->socketState = socketState;
hr = readOp->put_Completed(Callback<SocketReadCompletedHandler>(d, &QNativeSocketEnginePrivate::handleReadyRead).Get());
RETURN_HR_IF_FAILED_WITH_ARGS("initialize(): Failed to set socket read callback (%s).",
socketDescription(this).constData());
return S_OK; return S_OK;
}); });
if (FAILED(hr)) if (FAILED(hr))
@ -639,20 +805,6 @@ void QNativeSocketEngine::close()
} }
#endif // _MSC_VER >= 1900 #endif // _MSC_VER >= 1900
QMutexLocker locker(&d->readOperationsMutex);
for (ComPtr<IAsyncBufferOperation> readOp : d->pendingReadOps) {
ComPtr<IAsyncInfo> info;
hr = readOp.As(&info);
Q_ASSERT_SUCCEEDED(hr);
if (info) {
hr = info->Cancel();
Q_ASSERT_SUCCEEDED(hr);
hr = info->Close();
Q_ASSERT_SUCCEEDED(hr);
}
}
locker.unlock();
if (d->socketDescriptor != -1) { if (d->socketDescriptor != -1) {
ComPtr<IClosable> socket; ComPtr<IClosable> socket;
if (d->socketType == QAbstractSocket::TcpSocket) { if (d->socketType == QAbstractSocket::TcpSocket) {
@ -730,14 +882,32 @@ qint64 QNativeSocketEngine::read(char *data, qint64 maxlen)
// happens and there isn't anything left in the buffer, we have to return -1 in order to signal // happens and there isn't anything left in the buffer, we have to return -1 in order to signal
// the closing of the socket. // the closing of the socket.
QMutexLocker mutexLocker(&d->readMutex); QMutexLocker mutexLocker(&d->readMutex);
if (d->readBytes.pos() == d->readBytes.size() && d->socketState != QAbstractSocket::ConnectedState) { if (d->pendingData.isEmpty() && d->socketState != QAbstractSocket::ConnectedState) {
close(); close();
return -1; return -1;
} }
qint64 b = d->readBytes.read(data, maxlen); QByteArray readData;
d->bytesAvailable = d->readBytes.size() - d->readBytes.pos(); qint64 leftToMaxLen = maxlen;
return b; while (leftToMaxLen > 0 && !d->pendingData.isEmpty()) {
QByteArray pendingData = d->pendingData.takeFirst();
// Do not read the whole data. Put the rest of it back into the "queue"
if (leftToMaxLen < pendingData.length()) {
readData += pendingData.left(leftToMaxLen);
pendingData = pendingData.remove(0, maxlen);
d->pendingData.prepend(pendingData);
break;
} else {
readData += pendingData;
leftToMaxLen -= pendingData.length();
}
}
const int copyLength = qMin(maxlen, qint64(readData.length()));
d->bytesAvailable -= copyLength;
mutexLocker.unlock();
memcpy(data, readData, copyLength);
return copyLength;
} }
qint64 QNativeSocketEngine::write(const char *data, qint64 len) qint64 QNativeSocketEngine::write(const char *data, qint64 len)
@ -913,7 +1083,7 @@ bool QNativeSocketEngine::waitForRead(int msecs, bool *timedOut)
// If we are a client, we are ready to read if our buffer has data // If we are a client, we are ready to read if our buffer has data
QMutexLocker locker(&d->readMutex); QMutexLocker locker(&d->readMutex);
if (!d->readBytes.atEnd()) if (!d->pendingData.isEmpty())
return true; return true;
// Nothing to do, wait for more events // Nothing to do, wait for more events
@ -1001,21 +1171,8 @@ void QNativeSocketEngine::establishRead()
HRESULT hr; HRESULT hr;
hr = QEventDispatcherWinRT::runOnXamlThread([d]() { hr = QEventDispatcherWinRT::runOnXamlThread([d]() {
ComPtr<IInputStream> stream; d->worker->setTcpSocket(d->tcpSocket());
HRESULT hr = d->tcpSocket()->get_InputStream(&stream); d->worker->startReading();
RETURN_HR_IF_FAILED("establishRead(): Failed to get socket input stream");
ComPtr<IBuffer> buffer;
hr = g->bufferFactory->Create(READ_BUFFER_SIZE, &buffer);
RETURN_HR_IF_FAILED("establishRead(): Failed to create buffer");
ComPtr<IAsyncBufferOperation> readOp;
hr = stream->ReadAsync(buffer.Get(), READ_BUFFER_SIZE, InputStreamOptions_Partial, readOp.GetAddressOf());
RETURN_HR_IF_FAILED("establishRead(): Failed to initiate socket read");
QMutexLocker locker(&d->readOperationsMutex);
d->pendingReadOps.append(readOp);
hr = readOp->put_Completed(Callback<SocketReadCompletedHandler>(d, &QNativeSocketEnginePrivate::handleReadyRead).Get());
RETURN_HR_IF_FAILED("establishRead(): Failed to register read callback");
return S_OK; return S_OK;
}); });
Q_ASSERT_SUCCEEDED(hr); Q_ASSERT_SUCCEEDED(hr);
@ -1032,6 +1189,32 @@ void QNativeSocketEngine::handleNewDatagrams(const QList<WinRtDatagram> &datagra
emit readReady(); emit readReady();
} }
void QNativeSocketEngine::handleNewData(const QVector<QByteArray> &data)
{
// Defer putting the data into the list until the next event loop iteration
// (where the readyRead signal is emitted as well)
QMetaObject::invokeMethod(this, "putIntoPendingData", Qt::QueuedConnection,
Q_ARG(QVector<QByteArray>, data));
}
void QNativeSocketEngine::handleTcpError(QAbstractSocket::SocketError error)
{
Q_D(QNativeSocketEngine);
QNativeSocketEnginePrivate::ErrorString errorString;
switch (error) {
case QAbstractSocket::RemoteHostClosedError:
errorString = QNativeSocketEnginePrivate::RemoteHostClosedErrorString;
break;
default:
errorString = QNativeSocketEnginePrivate::UnknownSocketErrorString;
}
d->setError(error, errorString);
d->socketState = QAbstractSocket::UnconnectedState;
if (d->notifyOnRead)
emit readReady();
}
void QNativeSocketEngine::putIntoPendingDatagramsList(const QList<WinRtDatagram> &datagrams) void QNativeSocketEngine::putIntoPendingDatagramsList(const QList<WinRtDatagram> &datagrams)
{ {
Q_D(QNativeSocketEngine); Q_D(QNativeSocketEngine);
@ -1039,6 +1222,18 @@ void QNativeSocketEngine::putIntoPendingDatagramsList(const QList<WinRtDatagram>
d->pendingDatagrams.append(datagrams); d->pendingDatagrams.append(datagrams);
} }
void QNativeSocketEngine::putIntoPendingData(const QVector<QByteArray> &data)
{
Q_D(QNativeSocketEngine);
QMutexLocker locker(&d->readMutex);
d->pendingData.append(data);
for (const QByteArray &newData : data)
d->bytesAvailable += newData.length();
locker.unlock();
if (d->notifyOnRead)
readNotification();
}
bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol &socketProtocol) bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol &socketProtocol)
{ {
Q_UNUSED(socketProtocol); Q_UNUSED(socketProtocol);
@ -1093,7 +1288,7 @@ QNativeSocketEnginePrivate::QNativeSocketEnginePrivate()
, notifyOnException(false) , notifyOnException(false)
, closingDown(false) , closingDown(false)
, socketDescriptor(-1) , socketDescriptor(-1)
, worker(new SocketEngineWorker) , worker(new SocketEngineWorker(this))
, sslSocket(Q_NULLPTR) , sslSocket(Q_NULLPTR)
, connectionToken( { -1 } ) , connectionToken( { -1 } )
{ {
@ -1481,109 +1676,6 @@ HRESULT QNativeSocketEnginePrivate::handleConnectOpFinished(IAsyncAction *action
return S_OK; return S_OK;
} }
HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *asyncInfo, AsyncStatus status)
{
if (closingDown || wasDeleted || isDeletingChildren
|| socketState == QAbstractSocket::UnconnectedState) {
return S_OK;
}
Q_Q(QNativeSocketEngine);
QMutexLocker locker(&readOperationsMutex);
for (int i = 0; i < pendingReadOps.count(); ++i) {
if (pendingReadOps.at(i).Get() == asyncInfo) {
pendingReadOps.takeAt(i);
break;
}
}
locker.unlock();
// A read in UnconnectedState will close the socket and return -1 and thus tell the caller,
// that the connection was closed. The socket cannot be closed here, as the subsequent read
// might fail then.
if (status == Error || status == Canceled) {
setError(QAbstractSocket::RemoteHostClosedError, RemoteHostClosedErrorString);
socketState = QAbstractSocket::UnconnectedState;
if (notifyOnRead)
emit q->readReady();
return S_OK;
}
ComPtr<IBuffer> buffer;
HRESULT hr = asyncInfo->GetResults(&buffer);
RETURN_OK_IF_FAILED("Failed to get read results buffer");
UINT32 bufferLength;
hr = buffer->get_Length(&bufferLength);
Q_ASSERT_SUCCEEDED(hr);
// A zero sized buffer length signals, that the remote host closed the connection. The socket
// cannot be closed though, as the following read might have socket descriptor -1 and thus and
// the closing of the socket won't be communicated to the caller. So only the error is set. The
// actual socket close happens inside of read.
if (!bufferLength) {
setError(QAbstractSocket::RemoteHostClosedError, RemoteHostClosedErrorString);
socketState = QAbstractSocket::UnconnectedState;
if (notifyOnRead)
emit q->readReady();
return S_OK;
}
ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteArrayAccess;
hr = buffer.As(&byteArrayAccess);
Q_ASSERT_SUCCEEDED(hr);
byte *data;
hr = byteArrayAccess->Buffer(&data);
Q_ASSERT_SUCCEEDED(hr);
QMutexLocker readLocker(&readMutex);
if (readBytes.atEnd()) // Everything has been read; the buffer is safe to reset
readBytes.close();
if (!readBytes.isOpen())
readBytes.open(QBuffer::ReadWrite|QBuffer::Truncate);
qint64 readPos = readBytes.pos();
readBytes.seek(readBytes.size());
Q_ASSERT(readBytes.atEnd());
readBytes.write(reinterpret_cast<const char*>(data), qint64(bufferLength));
readBytes.seek(readPos);
bytesAvailable = readBytes.size() - readBytes.pos();
readLocker.unlock();
if (notifyOnRead)
emit q->readReady();
hr = QEventDispatcherWinRT::runOnXamlThread([buffer, q, this]() {
UINT32 readBufferLength;
ComPtr<IInputStream> stream;
HRESULT hr = tcpSocket()->get_InputStream(&stream);
RETURN_HR_IF_FAILED("handleReadyRead(): Could not obtain input stream");
// Reuse the stream buffer
hr = buffer->get_Capacity(&readBufferLength);
RETURN_HR_IF_FAILED("handleReadyRead(): Could not obtain buffer capacity");
hr = buffer->put_Length(0);
RETURN_HR_IF_FAILED("handleReadyRead(): Could not set buffer length");
ComPtr<IAsyncBufferOperation> readOp;
hr = stream->ReadAsync(buffer.Get(), readBufferLength, InputStreamOptions_Partial, &readOp);
if (FAILED(hr)) {
qErrnoWarning(hr, "handleReadyRead(): Could not read into socket stream buffer (%s).",
socketDescription(q).constData());
return S_OK;
}
QMutexLocker locker(&readOperationsMutex);
pendingReadOps.append(readOp);
hr = readOp->put_Completed(Callback<SocketReadCompletedHandler>(this, &QNativeSocketEnginePrivate::handleReadyRead).Get());
if (FAILED(hr)) {
qErrnoWarning(hr, "handleReadyRead(): Failed to set socket read callback (%s).",
socketDescription(q).constData());
return S_OK;
}
return S_OK;
});
Q_ASSERT_SUCCEEDED(hr);
return S_OK;
}
HRESULT QNativeSocketEnginePrivate::handleNewDatagram(IDatagramSocket *socket, IDatagramSocketMessageReceivedEventArgs *args) HRESULT QNativeSocketEnginePrivate::handleNewDatagram(IDatagramSocket *socket, IDatagramSocketMessageReceivedEventArgs *args)
{ {
Q_Q(QNativeSocketEngine); Q_Q(QNativeSocketEngine);

View File

@ -144,9 +144,12 @@ signals:
private slots: private slots:
void establishRead(); void establishRead();
void handleNewDatagrams(const QList<WinRtDatagram> &datagram); void handleNewDatagrams(const QList<WinRtDatagram> &datagram);
void handleNewData(const QVector<QByteArray> &data);
void handleTcpError(QAbstractSocket::SocketError error);
private: private:
Q_INVOKABLE void putIntoPendingDatagramsList(const QList<WinRtDatagram> &datagrams); Q_INVOKABLE void putIntoPendingDatagramsList(const QList<WinRtDatagram> &datagrams);
Q_INVOKABLE void putIntoPendingData(const QVector<QByteArray> &data);
Q_DECLARE_PRIVATE(QNativeSocketEngine) Q_DECLARE_PRIVATE(QNativeSocketEngine)
Q_DISABLE_COPY(QNativeSocketEngine) Q_DISABLE_COPY(QNativeSocketEngine)
@ -215,23 +218,17 @@ private:
Microsoft::WRL::ComPtr<ABI::Windows::Networking::Sockets::IStreamSocketListener> tcpListener; Microsoft::WRL::ComPtr<ABI::Windows::Networking::Sockets::IStreamSocketListener> tcpListener;
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncAction> connectOp; Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncAction> connectOp;
// Protected by readOperationsMutex. Written in handleReadyRead (native callback)
QVector<Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncOperationWithProgress<ABI::Windows::Storage::Streams::IBuffer *, UINT32>>> pendingReadOps;
// Protected by readMutex. Written in handleReadyRead (native callback)
QBuffer readBytes;
// In case of TCP readMutex protects readBytes and bytesAvailable. In case of UDP it is // In case of TCP readMutex protects readBytes and bytesAvailable. In case of UDP it is
// pendingDatagrams. They are written inside native callbacks (handleReadyRead and // pendingDatagrams. They are written inside native callbacks (handleReadyRead and
// handleNewDatagrams/putIntoPendingDatagramsList) // handleNewDatagrams/putIntoPendingDatagramsList)
mutable QMutex readMutex; mutable QMutex readMutex;
// As pendingReadOps is changed inside handleReadyRead(native callback) it has to be protected
QMutex readOperationsMutex;
// Protected by readMutex. Written in handleReadyRead (native callback) // Protected by readMutex. Written in handleReadyRead (native callback)
QAtomicInteger<int> bytesAvailable; QAtomicInteger<int> bytesAvailable;
// Protected by readMutex. Written in handleNewData/putIntoPendingData (native callback)
QVector<QByteArray> pendingData;
// Protected by readMutex. Written in handleNewDatagrams/putIntoPendingDatagramsList // Protected by readMutex. Written in handleNewDatagrams/putIntoPendingDatagramsList
QList<WinRtDatagram> pendingDatagrams; QList<WinRtDatagram> pendingDatagrams;
@ -246,7 +243,6 @@ private:
HRESULT handleClientConnection(ABI::Windows::Networking::Sockets::IStreamSocketListener *tcpListener, HRESULT handleClientConnection(ABI::Windows::Networking::Sockets::IStreamSocketListener *tcpListener,
ABI::Windows::Networking::Sockets::IStreamSocketListenerConnectionReceivedEventArgs *args); ABI::Windows::Networking::Sockets::IStreamSocketListenerConnectionReceivedEventArgs *args);
HRESULT handleConnectOpFinished(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus); HRESULT handleConnectOpFinished(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus);
HRESULT handleReadyRead(ABI::Windows::Foundation::IAsyncOperationWithProgress<ABI::Windows::Storage::Streams::IBuffer *, UINT32> *asyncInfo, ABI::Windows::Foundation::AsyncStatus);
}; };
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -41,7 +41,8 @@
#define QEGLNATIVECONTEXT_H #define QEGLNATIVECONTEXT_H
#include <QtCore/QMetaType> #include <QtCore/QMetaType>
#include <QtEglSupport/private/qt_egl_p.h>
// Leave including egl.h with the appropriate defines to the client.
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE

View File

@ -36,6 +36,12 @@
that an application using it is only guaranteed to work with the Qt version it was that an application using it is only guaranteed to work with the Qt version it was
developed against. developed against.
\note Due to being public while relying on otherwise hidden EGL types, this header
itself does not include \c{EGL/egl.h}. It is the application's responsibility to
include egl.h with any appropriate defines (for example, \c{MESA_EGL_NO_X11_HEADERS}
or other vendor-specific defines controlling the typedefs for EGL's native resources)
before this header.
\sa QOpenGLContext::setNativeHandle(), QOpenGLContext::nativeHandle() \sa QOpenGLContext::setNativeHandle(), QOpenGLContext::nativeHandle()
*/ */

View File

@ -663,7 +663,7 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
glyphRun.glyphOffsets = &glyphOffset; glyphRun.glyphOffsets = &glyphOffset;
QTransform xform = originalTransform; QTransform xform = originalTransform;
if (fontDef.stretch != 100) if (fontDef.stretch != 100 && fontDef.stretch != QFont::AnyStretch)
xform.scale(fontDef.stretch / 100.0, 1.0); xform.scale(fontDef.stretch / 100.0, 1.0);
DWRITE_MATRIX transform; DWRITE_MATRIX transform;
@ -933,7 +933,7 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph
Q_UNUSED(format); Q_UNUSED(format);
QTransform matrix = originalTransform; QTransform matrix = originalTransform;
if (fontDef.stretch != 100) if (fontDef.stretch != 100 && fontDef.stretch != QFont::AnyStretch)
matrix.scale(fontDef.stretch / 100.0, 1.0); matrix.scale(fontDef.stretch / 100.0, 1.0);
glyph_metrics_t bbox = QFontEngine::boundingBox(glyph, matrix); // To get transformed advance glyph_metrics_t bbox = QFontEngine::boundingBox(glyph, matrix); // To get transformed advance

View File

@ -767,6 +767,10 @@ static bool readExifHeader(QDataStream &stream)
*/ */
static int getExifOrientation(QByteArray &exifData) static int getExifOrientation(QByteArray &exifData)
{ {
// Current EXIF version (2.3) says there can be at most 5 IFDs,
// byte we allow for 10 so we're able to deal with future extensions.
const int maxIfdCount = 10;
QDataStream stream(&exifData, QIODevice::ReadOnly); QDataStream stream(&exifData, QIODevice::ReadOnly);
if (!readExifHeader(stream)) if (!readExifHeader(stream))
@ -774,7 +778,8 @@ static int getExifOrientation(QByteArray &exifData)
quint16 val; quint16 val;
quint32 offset; quint32 offset;
const qint64 headerStart = stream.device()->pos(); const qint64 headerStart = 6; // the EXIF header has a constant size
Q_ASSERT(headerStart == stream.device()->pos());
// read byte order marker // read byte order marker
stream >> val; stream >> val;
@ -785,7 +790,7 @@ static int getExifOrientation(QByteArray &exifData)
else else
return -1; // unknown byte order return -1; // unknown byte order
// read size // confirm byte order
stream >> val; stream >> val;
if (val != 0x2a) if (val != 0x2a)
return -1; return -1;
@ -793,18 +798,22 @@ static int getExifOrientation(QByteArray &exifData)
stream >> offset; stream >> offset;
// read IFD // read IFD
while (!stream.atEnd()) { for (int n = 0; n < maxIfdCount; ++n) {
quint16 numEntries; quint16 numEntries;
// skip offset bytes to get the next IFD
const qint64 bytesToSkip = offset - (stream.device()->pos() - headerStart); const qint64 bytesToSkip = offset - (stream.device()->pos() - headerStart);
if (bytesToSkip < 0 || (offset + headerStart >= exifData.size())) {
if (stream.skipRawData(bytesToSkip) != bytesToSkip) // disallow going backwards, though it's permitted in the spec
return -1; return -1;
} else if (bytesToSkip != 0) {
// seek to the IFD
if (!stream.device()->seek(offset + headerStart))
return -1;
}
stream >> numEntries; stream >> numEntries;
for (; numEntries > 0; --numEntries) { for (; numEntries > 0 && stream.status() == QDataStream::Ok; --numEntries) {
quint16 tag; quint16 tag;
quint16 type; quint16 type;
quint32 components; quint32 components;
@ -828,12 +837,14 @@ static int getExifOrientation(QByteArray &exifData)
// read offset to next IFD // read offset to next IFD
stream >> offset; stream >> offset;
if (stream.status() != QDataStream::Ok)
return -1;
if (offset == 0) // this is the last IFD if (offset == 0) // this is the last IFD
break; return 0; // No Exif orientation was found
} }
// No Exif orientation was found // too many IFDs
return 0; return -1;
} }
static QImageIOHandler::Transformations exif2Qt(int exifOrientation) static QImageIOHandler::Transformations exif2Qt(int exifOrientation)

View File

@ -54,7 +54,6 @@
static const char m_qtTag[] = "Qt A11Y"; static const char m_qtTag[] = "Qt A11Y";
static const char m_classErrorMsg[] = "Can't find class \"%s\""; static const char m_classErrorMsg[] = "Can't find class \"%s\"";
static const char m_methodErrorMsg[] = "Can't find method \"%s%s\"";
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE

View File

@ -810,7 +810,7 @@ namespace QtAndroidInput
#endif #endif
QAndroidInputContext *inputContext = QAndroidInputContext::androidInputContext(); QAndroidInputContext *inputContext = QAndroidInputContext::androidInputContext();
if (inputContext && qGuiApp) if (inputContext && qGuiApp)
QMetaObject::invokeMethod(inputContext, "handleLocationChanged", QMetaObject::invokeMethod(inputContext, "handleLocationChanged", Qt::BlockingQueuedConnection,
Q_ARG(int, id), Q_ARG(int, x), Q_ARG(int, y)); Q_ARG(int, id), Q_ARG(int, x), Q_ARG(int, y));
} }

View File

@ -122,8 +122,6 @@ static int m_desktopHeightPixels = 0;
static double m_scaledDensity = 0; static double m_scaledDensity = 0;
static double m_density = 1.0; static double m_density = 1.0;
static volatile bool m_pauseApplication;
static AndroidAssetsFileEngineHandler *m_androidAssetsFileEngineHandler = nullptr; static AndroidAssetsFileEngineHandler *m_androidAssetsFileEngineHandler = nullptr;

View File

@ -578,6 +578,11 @@ void QAndroidInputContext::updateSelectionHandles()
*/ */
void QAndroidInputContext::handleLocationChanged(int handleId, int x, int y) void QAndroidInputContext::handleLocationChanged(int handleId, int x, int y)
{ {
if (m_batchEditNestingLevel.load() || m_blockUpdateSelection)
return;
finishComposingText();
auto im = qGuiApp->inputMethod(); auto im = qGuiApp->inputMethod();
auto leftRect = im->cursorRectangle(); auto leftRect = im->cursorRectangle();
// The handle is down of the cursor, but we want the position in the middle. // The handle is down of the cursor, but we want the position in the middle.

View File

@ -152,7 +152,7 @@ private:
CursorHandleShowPopup = 3 CursorHandleShowPopup = 3
}; };
CursorHandleShowMode m_cursorHandleShown; CursorHandleShowMode m_cursorHandleShown;
int m_batchEditNestingLevel; QAtomicInt m_batchEditNestingLevel;
QObject *m_focusObject; QObject *m_focusObject;
}; };

View File

@ -331,11 +331,12 @@ void QCocoaMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *
void QCocoaMenu::insertNative(QCocoaMenuItem *item, QCocoaMenuItem *beforeItem) void QCocoaMenu::insertNative(QCocoaMenuItem *item, QCocoaMenuItem *beforeItem)
{ {
item->nsItem().target = m_nativeMenu.delegate; NSMenuItem *nativeItem = item->nsItem();
item->nsItem().action = @selector(itemFired:); nativeItem.target = m_nativeMenu.delegate;
nativeItem.action = @selector(itemFired:);
// Someone's adding new items after aboutToShow() was emitted // Someone's adding new items after aboutToShow() was emitted
if (isOpen() && item->menu() && item->nsItem()) if (isOpen() && nativeItem && item->menu())
item->menu()->setAttachedItem(item->nsItem()); item->menu()->setAttachedItem(nativeItem);
item->setParentEnabled(isEnabled()); item->setParentEnabled(isEnabled());
@ -348,15 +349,20 @@ void QCocoaMenu::insertNative(QCocoaMenuItem *item, QCocoaMenuItem *beforeItem)
beforeItem = itemOrNull(m_menuItems.indexOf(beforeItem) + 1); beforeItem = itemOrNull(m_menuItems.indexOf(beforeItem) + 1);
} }
if (nativeItem.menu) {
qWarning() << "Menu item" << item->text() << "already in menu" << QString::fromNSString(nativeItem.menu.title);
return;
}
if (beforeItem) { if (beforeItem) {
if (beforeItem->isMerged()) { if (beforeItem->isMerged()) {
qWarning("No non-merged before menu item found"); qWarning("No non-merged before menu item found");
return; return;
} }
NSUInteger nativeIndex = [m_nativeMenu indexOfItem:beforeItem->nsItem()]; const NSInteger nativeIndex = [m_nativeMenu indexOfItem:beforeItem->nsItem()];
[m_nativeMenu insertItem: item->nsItem() atIndex: nativeIndex]; [m_nativeMenu insertItem:nativeItem atIndex:nativeIndex];
} else { } else {
[m_nativeMenu addItem: item->nsItem()]; [m_nativeMenu addItem:nativeItem];
} }
item->setMenuParent(this); item->setMenuParent(this);
} }
@ -413,9 +419,8 @@ void QCocoaMenu::syncMenuItem(QPlatformMenuItem *menuItem)
return; return;
} }
bool wasMerged = cocoaItem->isMerged(); const bool wasMerged = cocoaItem->isMerged();
NSMenu *oldMenu = wasMerged ? [[QCocoaMenuLoader sharedMenuLoader] applicationMenu] : m_nativeMenu; NSMenuItem *oldItem = cocoaItem->nsItem();
NSMenuItem *oldItem = [oldMenu itemWithTag:(NSInteger) cocoaItem];
if (cocoaItem->sync() != oldItem) { if (cocoaItem->sync() != oldItem) {
// native item was changed for some reason // native item was changed for some reason

View File

@ -288,7 +288,7 @@ NSMenuItem *QCocoaMenuItem::sync()
} }
default: default:
qWarning() << "menu item" << m_text << "has unsupported role" << (int)m_role; qWarning() << "Menu item" << m_text << "has unsupported role" << m_role;
} }
if (mergeItem) { if (mergeItem) {

View File

@ -3,7 +3,7 @@ TARGET = qdirectfb
QT += \ QT += \
core-private gui-private \ core-private gui-private \
eventdispatcher_support-private service_support-private \ eventdispatcher_support-private service_support-private \
fontdatabase_support-private egl_support-private fontdatabase_support-private
QMAKE_USE += directfb QMAKE_USE += directfb
@ -28,6 +28,7 @@ HEADERS = qdirectfbintegration.h \
# ### port the GL context # ### port the GL context
contains(QT_CONFIG, directfb_egl) { contains(QT_CONFIG, directfb_egl) {
QT += egl_support-private
HEADERS += qdirectfb_egl.h HEADERS += qdirectfb_egl.h
SOURCES += qdirectfb_egl.cpp SOURCES += qdirectfb_egl.cpp
DEFINES += DIRECTFB_GL_EGL DEFINES += DIRECTFB_GL_EGL

View File

@ -44,7 +44,8 @@
#if defined(Q_CC_MINGW) #if defined(Q_CC_MINGW)
# define HAS_UI_VIEW_SETTINGS_INTEROP # define HAS_UI_VIEW_SETTINGS_INTEROP
#elif !defined(Q_CC_MSVC) || _MSC_VER >= 1900 // MSVC2013 is lacking both // Present from MSVC2015 + SDK 10 onwards
#elif (!defined(Q_CC_MSVC) || _MSC_VER >= 1900) && NTDDI_VERSION >= 0xa000000
# define HAS_UI_VIEW_SETTINGS_INTEROP # define HAS_UI_VIEW_SETTINGS_INTEROP
# define HAS_UI_VIEW_SETTINGS # define HAS_UI_VIEW_SETTINGS
#endif #endif

View File

@ -486,6 +486,9 @@ public:
QHash<ApplicationView2CallbackRemover, EventRegistrationToken> view2Tokens; QHash<ApplicationView2CallbackRemover, EventRegistrationToken> view2Tokens;
ComPtr<IApplicationView2> view2; ComPtr<IApplicationView2> view2;
#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) #endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
QAtomicPointer<QWinRTWindow> mouseGrabWindow;
QAtomicPointer<QWinRTWindow> keyboardGrabWindow;
QWindow *currentPressWindow = 0;
}; };
// To be called from the XAML thread // To be called from the XAML thread
@ -877,6 +880,44 @@ void QWinRTScreen::lower(QWindow *window)
handleExpose(); handleExpose();
} }
bool QWinRTScreen::setMouseGrabWindow(QWinRTWindow *window, bool grab)
{
Q_D(QWinRTScreen);
qCDebug(lcQpaWindows) << __FUNCTION__ << window
<< "(" << window->window()->objectName() << "):" << grab;
if (!grab || window == nullptr)
d->mouseGrabWindow = nullptr;
else if (d->mouseGrabWindow != window)
d->mouseGrabWindow = window;
return grab;
}
QWinRTWindow *QWinRTScreen::mouseGrabWindow() const
{
Q_D(const QWinRTScreen);
return d->mouseGrabWindow;
}
bool QWinRTScreen::setKeyboardGrabWindow(QWinRTWindow *window, bool grab)
{
Q_D(QWinRTScreen);
qCDebug(lcQpaWindows) << __FUNCTION__ << window
<< "(" << window->window()->objectName() << "):" << grab;
if (!grab || window == nullptr)
d->keyboardGrabWindow = nullptr;
else if (d->keyboardGrabWindow != window)
d->keyboardGrabWindow = window;
return grab;
}
QWinRTWindow *QWinRTScreen::keyboardGrabWindow() const
{
Q_D(const QWinRTScreen);
return d->keyboardGrabWindow;
}
void QWinRTScreen::updateWindowTitle(const QString &title) void QWinRTScreen::updateWindowTitle(const QString &title)
{ {
Q_D(QWinRTScreen); Q_D(QWinRTScreen);
@ -1022,7 +1063,11 @@ HRESULT QWinRTScreen::onPointerEntered(ICoreWindow *, IPointerEventArgs *args)
pointerPoint->get_Position(&point); pointerPoint->get_Position(&point);
QPoint pos(point.X * d->scaleFactor, point.Y * d->scaleFactor); QPoint pos(point.X * d->scaleFactor, point.Y * d->scaleFactor);
QWindowSystemInterface::handleEnterEvent(topWindow(), pos, pos); QWindow *targetWindow = topWindow();
if (d->mouseGrabWindow)
targetWindow = d->mouseGrabWindow.load()->window();
QWindowSystemInterface::handleEnterEvent(targetWindow, pos, pos);
} }
return S_OK; return S_OK;
} }
@ -1041,7 +1086,11 @@ HRESULT QWinRTScreen::onPointerExited(ICoreWindow *, IPointerEventArgs *args)
d->touchPoints.remove(id); d->touchPoints.remove(id);
QWindowSystemInterface::handleLeaveEvent(0); QWindow *targetWindow = nullptr;
if (d->mouseGrabWindow)
targetWindow = d->mouseGrabWindow.load()->window();
QWindowSystemInterface::handleLeaveEvent(targetWindow);
return S_OK; return S_OK;
} }
@ -1063,7 +1112,12 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
QPointF localPos = pos; QPointF localPos = pos;
const QPoint posPoint = pos.toPoint(); const QPoint posPoint = pos.toPoint();
QWindow *targetWindow = windowAt(posPoint); QWindow *windowUnderPointer = windowAt(posPoint);
QWindow *targetWindow = windowUnderPointer;
if (d->mouseGrabWindow)
targetWindow = d->mouseGrabWindow.load()->window();
if (targetWindow) { if (targetWindow) {
const QPointF globalPosDelta = pos - posPoint; const QPointF globalPosDelta = pos - posPoint;
localPos = targetWindow->mapFromGlobal(posPoint) + globalPosDelta; localPos = targetWindow->mapFromGlobal(posPoint) + globalPosDelta;
@ -1127,6 +1181,22 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
if (isPressed) if (isPressed)
buttons |= Qt::XButton2; buttons |= Qt::XButton2;
// In case of a mouse grab we have to store the target of a press event
// to be able to send one additional release event to this target when the mouse
// button is released. This is a similar approach to AutoMouseCapture in the
// windows qpa backend. Otherwise the release might not be propagated and the original
// press event receiver considers a button to still be pressed, as in Qt Quick Controls 1
// menus.
if (buttons != Qt::NoButton && d->currentPressWindow == nullptr && !d->mouseGrabWindow)
d->currentPressWindow = windowUnderPointer;
if (!isPressed && d->currentPressWindow && d->mouseGrabWindow) {
const QPointF globalPosDelta = pos - posPoint;
const QPointF localPressPos = d->currentPressWindow->mapFromGlobal(posPoint) + globalPosDelta;
QWindowSystemInterface::handleMouseEvent(d->currentPressWindow, localPressPos, pos, buttons, mods);
d->currentPressWindow = nullptr;
}
QWindowSystemInterface::handleMouseEvent(targetWindow, localPos, pos, buttons, mods); QWindowSystemInterface::handleMouseEvent(targetWindow, localPos, pos, buttons, mods);
break; break;

View File

@ -83,6 +83,7 @@ class QTouchDevice;
class QWinRTCursor; class QWinRTCursor;
class QWinRTInputContext; class QWinRTInputContext;
class QWinRTScreenPrivate; class QWinRTScreenPrivate;
class QWinRTWindow;
class QWinRTScreen : public QPlatformScreen class QWinRTScreen : public QPlatformScreen
{ {
public: public:
@ -110,6 +111,12 @@ public:
void raise(QWindow *window); void raise(QWindow *window);
void lower(QWindow *window); void lower(QWindow *window);
bool setMouseGrabWindow(QWinRTWindow *window, bool grab);
QWinRTWindow* mouseGrabWindow() const;
bool setKeyboardGrabWindow(QWinRTWindow *window, bool grab);
QWinRTWindow* keyboardGrabWindow() const;
void updateWindowTitle(const QString &title); void updateWindowTitle(const QString &title);
ABI::Windows::UI::Core::ICoreWindow *coreWindow() const; ABI::Windows::UI::Core::ICoreWindow *coreWindow() const;

View File

@ -191,6 +191,11 @@ QWinRTWindow::~QWinRTWindow()
}); });
RETURN_VOID_IF_FAILED("Failed to completely destroy window resources, likely because the application is shutting down"); RETURN_VOID_IF_FAILED("Failed to completely destroy window resources, likely because the application is shutting down");
if (d->screen->mouseGrabWindow() == this)
d->screen->setMouseGrabWindow(this, false);
if (d->screen->keyboardGrabWindow() == this)
d->screen->setKeyboardGrabWindow(this, false);
d->screen->removeWindow(window()); d->screen->removeWindow(window());
if (!d->surface) if (!d->surface)
@ -384,6 +389,24 @@ void QWinRTWindow::setWindowState(Qt::WindowState state)
d->state = state; d->state = state;
} }
bool QWinRTWindow::setMouseGrabEnabled(bool grab)
{
Q_D(QWinRTWindow);
if (!isActive() && grab) {
qWarning("%s: Not setting mouse grab for invisible window %s/'%s'",
__FUNCTION__, window()->metaObject()->className(),
qPrintable(window()->objectName()));
return false;
}
return d->screen->setMouseGrabWindow(this, grab);
}
bool QWinRTWindow::setKeyboardGrabEnabled(bool grab)
{
Q_D(QWinRTWindow);
return d->screen->setKeyboardGrabWindow(this, grab);
}
EGLSurface QWinRTWindow::eglSurface() const EGLSurface QWinRTWindow::eglSurface() const
{ {
Q_D(const QWinRTWindow); Q_D(const QWinRTWindow);

View File

@ -70,6 +70,9 @@ public:
qreal devicePixelRatio() const override; qreal devicePixelRatio() const override;
void setWindowState(Qt::WindowState state) override; void setWindowState(Qt::WindowState state) override;
bool setMouseGrabEnabled(bool grab) Q_DECL_OVERRIDE;
bool setKeyboardGrabEnabled(bool grab) Q_DECL_OVERRIDE;
EGLSurface eglSurface() const; EGLSurface eglSurface() const;
void createEglSurface(EGLDisplay display, EGLConfig config); void createEglSurface(EGLDisplay display, EGLConfig config);

View File

@ -135,10 +135,12 @@ bool QGtk3Dialog::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWind
GdkWindow *gdkWindow = gtk_widget_get_window(gtkWidget); GdkWindow *gdkWindow = gtk_widget_get_window(gtkWidget);
if (parent) { if (parent) {
GdkDisplay *gdkDisplay = gdk_window_get_display(gdkWindow); if (GDK_IS_X11_WINDOW(gdkWindow)) {
XSetTransientForHint(gdk_x11_display_get_xdisplay(gdkDisplay), GdkDisplay *gdkDisplay = gdk_window_get_display(gdkWindow);
gdk_x11_window_get_xid(gdkWindow), XSetTransientForHint(gdk_x11_display_get_xdisplay(gdkDisplay),
parent->winId()); gdk_x11_window_get_xid(gdkWindow),
parent->winId());
}
} }
if (modality != Qt::NonModal) { if (modality != Qt::NonModal) {

View File

@ -164,7 +164,7 @@ qtConfig(gui) {
SUBDIRS += src_angle SUBDIRS += src_angle
src_gui.depends += src_angle src_gui.depends += src_angle
} }
qtConfig(png) { qtConfig(png):!qtConfig(system-png) {
SUBDIRS += src_3rdparty_libpng SUBDIRS += src_3rdparty_libpng
src_3rdparty_freetype.depends += src_3rdparty_libpng src_3rdparty_freetype.depends += src_3rdparty_libpng
src_gui.depends += src_3rdparty_libpng src_gui.depends += src_3rdparty_libpng

View File

@ -477,9 +477,6 @@ int runMoc(int argc, char **argv)
} }
moc.symbols += pp.preprocessed(moc.filename, &in); moc.symbols += pp.preprocessed(moc.filename, &in);
// We obviously do not support MS extensions
pp.macros.remove("_MSC_EXTENSIONS");
if (!pp.preprocessOnly) { if (!pp.preprocessOnly) {
// 2. parse // 2. parse
moc.parse(); moc.parse();

Binary file not shown.

After

Width:  |  Height:  |  Size: 910 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 910 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 964 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 910 B

View File

@ -188,7 +188,8 @@ private slots:
void exifOrientation(); void exifOrientation();
void exif_QTBUG45865(); void exif_QTBUG45865();
void exif_invalid_data_QTBUG46870(); void exifInvalidData_data();
void exifInvalidData();
void cleanupFunctions(); void cleanupFunctions();
@ -3049,10 +3050,20 @@ void tst_QImage::exif_QTBUG45865()
QCOMPARE(image.size(), QSize(5, 8)); QCOMPARE(image.size(), QSize(5, 8));
} }
void tst_QImage::exif_invalid_data_QTBUG46870() void tst_QImage::exifInvalidData_data()
{
QTest::addColumn<bool>("$never used");
QTest::newRow("QTBUG-46870");
QTest::newRow("back_pointers");
QTest::newRow("past_end");
QTest::newRow("too_many_ifds");
QTest::newRow("too_many_tags");
}
void tst_QImage::exifInvalidData()
{ {
QImage image; QImage image;
QVERIFY(image.load(m_prefix + "jpeg_exif_invalid_data_QTBUG-46870.jpg")); QVERIFY(image.load(m_prefix + "jpeg_exif_invalid_data_" + QTest::currentDataTag() + ".jpg"));
QVERIFY(!image.isNull()); QVERIFY(!image.isNull());
} }

View File

@ -194,6 +194,7 @@ public:
private slots: private slots:
void cleanup(); void cleanup();
void qPointerUniqueId();
void touchDisabledByDefault(); void touchDisabledByDefault();
void touchEventAcceptedByDefault(); void touchEventAcceptedByDefault();
void touchBeginPropagatesWhenIgnored(); void touchBeginPropagatesWhenIgnored();
@ -224,6 +225,44 @@ void tst_QTouchEvent::cleanup()
QVERIFY(QGuiApplication::topLevelWindows().isEmpty()); QVERIFY(QGuiApplication::topLevelWindows().isEmpty());
} }
void tst_QTouchEvent::qPointerUniqueId()
{
QPointingDeviceUniqueId id1, id2;
QCOMPARE(id1.numericId(), Q_INT64_C(-1));
QVERIFY(!id1.isValid());
QVERIFY( id1 == id2);
QVERIFY(!(id1 != id2));
QSet<QPointingDeviceUniqueId> set; // compile test
set.insert(id1);
set.insert(id2);
QCOMPARE(set.size(), 1);
const auto id3 = QPointingDeviceUniqueId::fromNumericId(-1);
QCOMPARE(id3.numericId(), Q_INT64_C(-1));
QVERIFY(!id3.isValid());
QVERIFY( id1 == id3);
QVERIFY(!(id1 != id3));
set.insert(id3);
QCOMPARE(set.size(), 1);
const auto id4 = QPointingDeviceUniqueId::fromNumericId(4);
QCOMPARE(id4.numericId(), Q_INT64_C(4));
QVERIFY(id4.isValid());
QVERIFY( id1 != id4);
QVERIFY(!(id1 == id4));
set.insert(id4);
QCOMPARE(set.size(), 2);
}
void tst_QTouchEvent::touchDisabledByDefault() void tst_QTouchEvent::touchDisabledByDefault()
{ {
// QWidget // QWidget

View File

@ -46,6 +46,8 @@
# include <netinet/in.h> # include <netinet/in.h>
#endif #endif
Q_DECLARE_METATYPE(QHostAddress::SpecialAddress)
class tst_QHostAddress : public QObject class tst_QHostAddress : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -232,51 +234,55 @@ void tst_QHostAddress::setAddress_QString()
void tst_QHostAddress::specialAddresses_data() void tst_QHostAddress::specialAddresses_data()
{ {
QTest::addColumn<QString>("text"); QTest::addColumn<QString>("text");
QTest::addColumn<int>("address"); QTest::addColumn<QHostAddress::SpecialAddress>("address");
QTest::addColumn<bool>("result"); QTest::addColumn<bool>("result");
QTest::newRow("localhost_1") << QString("127.0.0.1") << (int)QHostAddress::LocalHost << true; QTest::newRow("localhost_1") << QString("127.0.0.1") << QHostAddress::LocalHost << true;
QTest::newRow("localhost_2") << QString("127.0.0.2") << (int)QHostAddress::LocalHost << false; QTest::newRow("localhost_2") << QString("127.0.0.2") << QHostAddress::LocalHost << false;
QTest::newRow("localhost_3") << QString("127.0.0.2") << (int)QHostAddress::LocalHostIPv6 << false; QTest::newRow("localhost_3") << QString("127.0.0.2") << QHostAddress::LocalHostIPv6 << false;
QTest::newRow("localhost_ipv6_4") << QString("::1") << (int)QHostAddress::LocalHostIPv6 << true; QTest::newRow("localhost_ipv6_4") << QString("::1") << QHostAddress::LocalHostIPv6 << true;
QTest::newRow("localhost_ipv6_5") << QString("::2") << (int)QHostAddress::LocalHostIPv6 << false; QTest::newRow("localhost_ipv6_5") << QString("::2") << QHostAddress::LocalHostIPv6 << false;
QTest::newRow("localhost_ipv6_6") << QString("::1") << (int)QHostAddress::LocalHost << false; QTest::newRow("localhost_ipv6_6") << QString("::1") << QHostAddress::LocalHost << false;
QTest::newRow("null_1") << QString("") << (int)QHostAddress::Null << true; QTest::newRow("null_1") << QString("") << QHostAddress::Null << true;
QTest::newRow("null_2") << QString("bjarne") << (int)QHostAddress::Null << true; QTest::newRow("null_2") << QString("bjarne") << QHostAddress::Null << true;
QTest::newRow("compare_from_null") << QString("") << (int)QHostAddress::Broadcast << false; QTest::newRow("compare_from_null") << QString("") << QHostAddress::Broadcast << false;
QTest::newRow("broadcast_1") << QString("255.255.255.255") << (int)QHostAddress::Any << false; QTest::newRow("broadcast_1") << QString("255.255.255.255") << QHostAddress::Any << false;
QTest::newRow("broadcast_2") << QString("255.255.255.255") << (int)QHostAddress::Broadcast << true; QTest::newRow("broadcast_2") << QString("255.255.255.255") << QHostAddress::Broadcast << true;
QTest::newRow("any_ipv6") << QString("::") << (int)QHostAddress::AnyIPv6 << true; QTest::newRow("any_ipv6") << QString("::") << QHostAddress::AnyIPv6 << true;
QTest::newRow("any_ipv4") << QString("0.0.0.0") << (int)QHostAddress::AnyIPv4 << true; QTest::newRow("any_ipv4") << QString("0.0.0.0") << QHostAddress::AnyIPv4 << true;
QTest::newRow("dual_not_ipv6") << QString("::") << (int)QHostAddress::Any << false; QTest::newRow("dual_not_ipv6") << QString("::") << QHostAddress::Any << false;
QTest::newRow("dual_not_ipv4") << QString("0.0.0.0") << (int)QHostAddress::Any << false; QTest::newRow("dual_not_ipv4") << QString("0.0.0.0") << QHostAddress::Any << false;
} }
void tst_QHostAddress::specialAddresses() void tst_QHostAddress::specialAddresses()
{ {
QFETCH(QString, text); QFETCH(QString, text);
QFETCH(int, address); QFETCH(QHostAddress::SpecialAddress, address);
QFETCH(bool, result); QFETCH(bool, result);
QVERIFY((QHostAddress(text) == (QHostAddress::SpecialAddress)address) == result); QCOMPARE(QHostAddress(text) == address, result);
//check special address equal to itself (QTBUG-22898), note two overloads of operator== //check special address equal to itself (QTBUG-22898), note two overloads of operator==
QVERIFY(QHostAddress((QHostAddress::SpecialAddress)address) == QHostAddress((QHostAddress::SpecialAddress)address)); QVERIFY(QHostAddress(address) == QHostAddress(address));
QVERIFY(QHostAddress((QHostAddress::SpecialAddress)address) == (QHostAddress::SpecialAddress)address); QVERIFY(QHostAddress(address) == address);
QVERIFY(!(QHostAddress(address) != QHostAddress(address)));
QVERIFY(!(QHostAddress(address) != address));
{
QHostAddress ha;
ha.setAddress(address);
QVERIFY(ha == address);
}
QHostAddress setter; QHostAddress setter;
setter.setAddress(text); setter.setAddress(text);
if (result) { QCOMPARE(setter == address, result);
QVERIFY(setter == (QHostAddress::SpecialAddress) address);
} else {
QVERIFY(!((QHostAddress::SpecialAddress) address == setter));
}
} }
@ -359,6 +365,11 @@ void tst_QHostAddress::isEqual()
QCOMPARE(second.isEqual(first, QHostAddress::ConversionModeFlag(flags)), result); QCOMPARE(second.isEqual(first, QHostAddress::ConversionModeFlag(flags)), result);
} }
QT_WARNING_PUSH
#ifdef QT_WARNING_DISABLE_DEPRECATED
QT_WARNING_DISABLE_DEPRECATED
#endif
void tst_QHostAddress::assignment() void tst_QHostAddress::assignment()
{ {
QHostAddress address; QHostAddress address;
@ -379,6 +390,8 @@ void tst_QHostAddress::assignment()
#endif // !Q_OS_WINRT #endif // !Q_OS_WINRT
} }
QT_WARNING_POP
void tst_QHostAddress::scopeId() void tst_QHostAddress::scopeId()
{ {
QHostAddress address("fe80::2e0:4cff:fefb:662a%eth0"); QHostAddress address("fe80::2e0:4cff:fefb:662a%eth0");

View File

@ -132,6 +132,7 @@ private slots:
void taskQTBUG53205_crashReparentNested(); void taskQTBUG53205_crashReparentNested();
#ifdef Q_OS_MACOS #ifdef Q_OS_MACOS
void taskQTBUG56275_reinsertMenuInParentlessQMenuBar(); void taskQTBUG56275_reinsertMenuInParentlessQMenuBar();
void QTBUG_57404_existingMenuItemException();
#endif #endif
void taskQTBUG55966_subMenuRemoved(); void taskQTBUG55966_subMenuRemoved();
@ -1540,6 +1541,31 @@ void tst_QMenuBar::taskQTBUG56275_reinsertMenuInParentlessQMenuBar()
QVERIFY(tst_qmenubar_taskQTBUG56275(&menubar)); QVERIFY(tst_qmenubar_taskQTBUG56275(&menubar));
} }
void tst_QMenuBar::QTBUG_57404_existingMenuItemException()
{
QMainWindow mw1;
QMainWindow mw2;
mw1.show();
mw2.show();
QMenuBar *mb = new QMenuBar(&mw1);
mw1.setMenuBar(mb);
mb->show();
QMenu *editMenu = new QMenu(QLatin1String("Edit"), &mw1);
mb->addMenu(editMenu);
QAction *copyAction = editMenu->addAction("&Copy");
copyAction->setShortcut(QKeySequence("Ctrl+C"));
QTest::ignoreMessage(QtWarningMsg, "Menu item \"&Copy\" has unsupported role QPlatformMenuItem::MenuRole(NoRole)");
copyAction->setMenuRole(QAction::NoRole);
QVERIFY(QTest::qWaitForWindowExposed(&mw2));
QTest::qWait(100);
mw2.close();
mw1.activateWindow();
QTest::qWait(100);
// No crash, all fine. Ideally, there should be only one warning.
}
#endif // Q_OS_MACOS #endif // Q_OS_MACOS
void tst_QMenuBar::taskQTBUG55966_subMenuRemoved() void tst_QMenuBar::taskQTBUG55966_subMenuRemoved()