summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbin/syncqt.pl4
-rw-r--r--doc/global/html-header-online.qdocconf1
-rw-r--r--doc/global/template/style/online.css8
-rw-r--r--examples/network/fortuneclient/client.cpp2
-rw-r--r--examples/network/fortuneserver/server.cpp2
-rw-r--r--examples/widgets/dialogs/standarddialogs/dialog.cpp16
-rw-r--r--examples/widgets/dialogs/standarddialogs/main.cpp12
-rw-r--r--mkspecs/devices/common/linux_device_pre.conf3
-rw-r--r--mkspecs/devices/linux-arm-generic-g++/qmake.conf9
-rw-r--r--mkspecs/devices/linux-arm-generic-g++/qplatformdefs.h34
-rw-r--r--mkspecs/features/qml_plugin.prf5
-rw-r--r--mkspecs/features/qt_build_config.prf3
-rw-r--r--mkspecs/features/qt_docs.prf23
-rw-r--r--mkspecs/features/qt_tool.prf2
-rw-r--r--mkspecs/features/testcase.prf16
-rw-r--r--qmake/doc/src/qmake-manual.qdoc1
-rw-r--r--qmake/generators/makefiledeps.cpp441
-rw-r--r--qmake/generators/win32/msvc_nmake.cpp22
-rw-r--r--qmake/generators/win32/msvc_vcproj.cpp19
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java1
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtNative.java7
-rw-r--r--src/corelib/io/qprocess_unix.cpp10
-rw-r--r--src/corelib/json/qjsonobject.cpp10
-rw-r--r--src/corelib/json/qjsonobject.h2
-rw-r--r--src/corelib/kernel/qeventdispatcher_winrt.cpp13
-rw-r--r--src/corelib/kernel/qsharedmemory_win.cpp6
-rw-r--r--src/corelib/kernel/qvariant.h4
-rw-r--r--src/corelib/plugin/qlibrary_win.cpp9
-rw-r--r--src/corelib/tools/qsharedpointer_impl.h2
-rw-r--r--src/corelib/tools/qstring.cpp24
-rw-r--r--src/corelib/tools/qstring.h7
-rw-r--r--src/corelib/tools/qtimezone.cpp5
-rw-r--r--src/gui/image/qimage_conversions.cpp11
-rw-r--r--src/gui/kernel/qplatformdialoghelper.h17
-rw-r--r--src/gui/kernel/qplatformmenu.h2
-rw-r--r--src/gui/kernel/qplatformsystemtrayicon.h2
-rw-r--r--src/gui/kernel/qplatformtheme.h2
-rw-r--r--src/gui/kernel/qscreen.cpp4
-rw-r--r--src/gui/kernel/qwindow_p.h2
-rw-r--r--src/gui/opengl/qopengltexture.cpp4
-rw-r--r--src/gui/opengl/qopengltexture_p.h1
-rw-r--r--src/gui/painting/qdrawhelper.cpp28
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp5
-rw-r--r--src/gui/painting/qplatformbackingstore.cpp2
-rw-r--r--src/gui/painting/qregion.cpp33
-rw-r--r--src/gui/text/qfont.cpp6
-rw-r--r--src/gui/text/qfontdatabase.cpp55
-rw-r--r--src/network/kernel/qdnslookup.cpp3
-rw-r--r--src/network/kernel/qdnslookup_p.h2
-rw-r--r--src/network/kernel/qdnslookup_unix.cpp4
-rw-r--r--src/network/kernel/qdnslookup_win.cpp4
-rw-r--r--src/network/kernel/qnetworkinterface_unix.cpp38
-rw-r--r--src/network/socket/qnativesocketengine_winrt_p.h2
-rw-r--r--src/platformheaders/windowsfunctions/qwindowswindowfunctions.h9
-rw-r--r--src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc26
-rw-r--r--src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp3
-rw-r--r--src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp6
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp20
-rw-r--r--src/plugins/platforms/android/qandroidplatformfontdatabase.cpp2
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm6
-rw-r--r--src/plugins/platforms/ios/qioscontext.mm9
-rw-r--r--src/plugins/platforms/ios/qiosmenu.mm17
-rw-r--r--src/plugins/platforms/ios/qiostextresponder.mm61
-rw-r--r--src/plugins/platforms/windows/qwindowsbackingstore.cpp7
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp75
-rw-r--r--src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp15
-rw-r--r--src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h1
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp11
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeinterface.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp21
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h6
-rw-r--r--src/plugins/platforms/winrt/qwinrtfontdatabase.cpp15
-rw-r--r--src/plugins/platforms/winrt/qwinrtfontdatabase.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp273
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h10
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp11
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp49
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h10
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp82
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h3
-rw-r--r--src/widgets/dialogs/qfiledialog.cpp2
-rw-r--r--src/widgets/dialogs/qfilesystemmodel.cpp24
-rw-r--r--src/widgets/doc/src/guibooks.qdoc2
-rw-r--r--src/widgets/itemviews/qlistwidget.cpp2
-rw-r--r--src/widgets/kernel/qaction.cpp4
-rw-r--r--src/widgets/kernel/qwidgetbackingstore.cpp26
-rw-r--r--src/widgets/widgets/qdockarealayout.cpp3
-rw-r--r--src/widgets/widgets/qdockwidget.cpp8
-rw-r--r--src/winmain/qtmain_winrt.cpp20
-rw-r--r--tests/auto/corelib/global/qlogging/qlogging.pro6
-rw-r--r--tests/auto/corelib/global/qlogging/test/test.pro2
-rw-r--r--tests/auto/corelib/io/qsettings/BLACKLIST1
-rw-r--r--tests/auto/corelib/io/qtextstream/tst_qtextstream.cpp2
-rw-r--r--tests/auto/corelib/kernel/qobject/qobject.pro6
-rw-r--r--tests/auto/corelib/kernel/qobject/test/test.pro2
-rw-r--r--tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp41
-rw-r--r--tests/auto/corelib/thread/qthreadstorage/qthreadstorage.pro4
-rw-r--r--tests/auto/corelib/thread/qthreadstorage/test/test.pro2
-rw-r--r--tests/auto/corelib/tools/qlocale/qlocale.pro4
-rw-r--r--tests/auto/corelib/tools/qlocale/test/test.pro2
-rw-r--r--tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp50
-rw-r--r--tests/auto/corelib/tools/qstring/tst_qstring.cpp66
-rw-r--r--tests/auto/gui/kernel/qclipboard/qclipboard.pro2
-rw-r--r--tests/auto/gui/kernel/qclipboard/test/test.pro2
-rw-r--r--tests/auto/gui/kernel/qwindow/tst_qwindow.cpp67
-rw-r--r--tests/auto/network/access/qnetworkreply/qnetworkreply.pro2
-rw-r--r--tests/auto/network/access/qnetworkreply/test/test.pro2
-rw-r--r--tests/auto/network/bearer/qnetworksession/qnetworksession.pro2
-rw-r--r--tests/auto/network/bearer/qnetworksession/test/test.pro2
-rw-r--r--tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp19
-rw-r--r--tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp4
-rw-r--r--tests/auto/other/toolsupport/tst_toolsupport.cpp2
-rw-r--r--tests/auto/testlib/selftests/selftests.pro2
-rw-r--r--tests/auto/testlib/selftests/test/test.pro2
-rw-r--r--tests/auto/tools/qmake/testdata/findDeps/findDeps.pro5
-rw-r--r--tests/auto/tools/qmake/testdata/findDeps/main.cpp50
-rw-r--r--tests/auto/tools/qmake/testdata/findDeps/objecta.h41
-rw-r--r--tests/auto/tools/qmake/testdata/findDeps/objectf.h41
-rw-r--r--tests/auto/tools/qmake/testdata/findMocs/findMocs.pro3
-rw-r--r--tests/auto/tools/qmake/testdata/findMocs/main.cpp5
-rw-r--r--tests/auto/tools/qmake/testdata/findMocs/object1.h4
-rw-r--r--tests/auto/tools/qmake/testdata/findMocs/object2.h4
-rw-r--r--tests/auto/tools/qmake/testdata/findMocs/object3.h4
-rw-r--r--tests/auto/tools/qmake/testdata/findMocs/object4.h3
-rw-r--r--tests/auto/tools/qmake/testdata/findMocs/object7.h1
-rw-r--r--tests/auto/tools/qmake/testdata/findMocs/object8.h50
-rw-r--r--tests/auto/tools/qmake/testdata/findMocs/object9.h41
-rw-r--r--tests/auto/tools/qmake/testdata/rawString/main.cpp38
-rw-r--r--tests/auto/tools/qmake/testdata/rawString/object1.h40
-rw-r--r--tests/auto/tools/qmake/testdata/rawString/rawString.pro4
-rw-r--r--tests/auto/tools/qmake/tst_qmake.cpp19
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp37
-rw-r--r--tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp92
-rw-r--r--tests/auto/widgets/kernel/qapplication/qapplication.pro2
-rw-r--r--tests/auto/widgets/kernel/qapplication/test/test.pro9
-rw-r--r--tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp16
-rw-r--r--tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp24
-rw-r--r--tools/configure/configureapp.cpp12
-rw-r--r--tools/configure/environment.cpp6
-rw-r--r--tools/shared/windows/registry.cpp6
-rw-r--r--tools/shared/windows/registry_p.h8
141 files changed, 2032 insertions, 622 deletions
diff --git a/bin/syncqt.pl b/bin/syncqt.pl
index 4016ea2d7c..cca654e3b4 100755
--- a/bin/syncqt.pl
+++ b/bin/syncqt.pl
@@ -764,7 +764,7 @@ while ( @ARGV ) {
$var = "version";
$val = shift @ARGV;
} elsif($arg =~/^-/) {
- print STDERR "Unknown option: $arg\n\n" if (!$var);
+ print STDERR "ERROR: Unknown option: $arg\n\n" if (!$var);
showUsage();
} else {
$basedir = locateSyncProfile($arg);
@@ -777,7 +777,7 @@ while ( @ARGV ) {
#do something
if(!$var || $var eq "show_help") {
- print STDERR "Unknown option: $arg\n\n" if (!$var);
+ print STDERR "ERROR: Unknown option: $arg\n\n" if (!$var);
showUsage();
} elsif ($var eq "copy") {
if($val eq "yes") {
diff --git a/doc/global/html-header-online.qdocconf b/doc/global/html-header-online.qdocconf
index 450eb1120b..02b7375d32 100644
--- a/doc/global/html-header-online.qdocconf
+++ b/doc/global/html-header-online.qdocconf
@@ -36,6 +36,7 @@ HTML.headerscripts = \
" <script type=\"text/javascript\" src=\"scripts/extras.js\"></script>\n" \
" <script type=\"text/javascript\">\n" \
" \$(function(){\n" \
+ " \$(\"#footer\").load(\"/style/qt-footer.html\");\n" \
" \$(\"#sidebar-content\").load(\"style/qt5-sidebar.html\");\n" \
" });\n" \
" </script>\n" \
diff --git a/doc/global/template/style/online.css b/doc/global/template/style/online.css
index c7758d0ca8..be278a27da 100644
--- a/doc/global/template/style/online.css
+++ b/doc/global/template/style/online.css
@@ -1260,13 +1260,13 @@ li a.active {
}
.mainContent table p {
margin:0px;
- padding:0px
-}
-.mainContent table p {
- margin:0px;
padding:0px;
+ max-width:initial;
min-height:2em
}
+.mainContent table p.centerAlign {
+ text-align:center
+}
.context h2 {
font-size:2.1875em
}
diff --git a/examples/network/fortuneclient/client.cpp b/examples/network/fortuneclient/client.cpp
index b4c3d9328d..42fed30445 100644
--- a/examples/network/fortuneclient/client.cpp
+++ b/examples/network/fortuneclient/client.cpp
@@ -117,7 +117,7 @@ Client::Client(QWidget *parent)
//! [4]
QGridLayout *mainLayout = Q_NULLPTR;
- if (QGuiApplication::styleHints()->showIsFullScreen()) {
+ if (QGuiApplication::styleHints()->showIsFullScreen() || QGuiApplication::styleHints()->showIsMaximized()) {
QVBoxLayout *outerVerticalLayout = new QVBoxLayout(this);
outerVerticalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding));
QHBoxLayout *outerHorizontalLayout = new QHBoxLayout;
diff --git a/examples/network/fortuneserver/server.cpp b/examples/network/fortuneserver/server.cpp
index 28f0230894..089f594cab 100644
--- a/examples/network/fortuneserver/server.cpp
+++ b/examples/network/fortuneserver/server.cpp
@@ -100,7 +100,7 @@ Server::Server(QWidget *parent)
buttonLayout->addStretch(1);
QVBoxLayout *mainLayout = Q_NULLPTR;
- if (QGuiApplication::styleHints()->showIsFullScreen()) {
+ if (QGuiApplication::styleHints()->showIsFullScreen() || QGuiApplication::styleHints()->showIsMaximized()) {
QVBoxLayout *outerVerticalLayout = new QVBoxLayout(this);
outerVerticalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding));
QHBoxLayout *outerHorizontalLayout = new QHBoxLayout;
diff --git a/examples/widgets/dialogs/standarddialogs/dialog.cpp b/examples/widgets/dialogs/standarddialogs/dialog.cpp
index b4232c36f6..b28cf0f934 100644
--- a/examples/widgets/dialogs/standarddialogs/dialog.cpp
+++ b/examples/widgets/dialogs/standarddialogs/dialog.cpp
@@ -98,9 +98,19 @@ int DialogOptionsWidget::value() const
Dialog::Dialog(QWidget *parent)
: QWidget(parent)
{
- QVBoxLayout *mainLayout = new QVBoxLayout(this);
+ QVBoxLayout *verticalLayout;
+ if (QGuiApplication::styleHints()->showIsFullScreen() || QGuiApplication::styleHints()->showIsMaximized()) {
+ QHBoxLayout *horizontalLayout = new QHBoxLayout(this);
+ QGroupBox *groupBox = new QGroupBox(QGuiApplication::applicationDisplayName(), this);
+ horizontalLayout->addWidget(groupBox);
+ horizontalLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored));
+ verticalLayout = new QVBoxLayout(groupBox);
+ } else {
+ verticalLayout = new QVBoxLayout(this);
+ }
+
QToolBox *toolbox = new QToolBox;
- mainLayout->addWidget(toolbox);
+ verticalLayout->addWidget(toolbox);
errorMessageDialog = new QErrorMessage(this);
@@ -291,7 +301,7 @@ Dialog::Dialog(QWidget *parent)
layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding), 5, 0);
toolbox->addItem(page, tr("Message Boxes"));
- setWindowTitle(tr("Standard Dialogs"));
+ setWindowTitle(QGuiApplication::applicationDisplayName());
}
void Dialog::setInteger()
diff --git a/examples/widgets/dialogs/standarddialogs/main.cpp b/examples/widgets/dialogs/standarddialogs/main.cpp
index a13e37905c..8a8ee2ac0b 100644
--- a/examples/widgets/dialogs/standarddialogs/main.cpp
+++ b/examples/widgets/dialogs/standarddialogs/main.cpp
@@ -39,6 +39,7 @@
****************************************************************************/
#include <QApplication>
+#include <QStyleHints>
#include <QDesktopWidget>
#include <QTranslator>
#include <QLocale>
@@ -49,6 +50,7 @@
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
+ QGuiApplication::setApplicationDisplayName(Dialog::tr("Standard Dialogs"));
#ifndef QT_NO_TRANSLATION
QString translatorFileName = QLatin1String("qt_");
@@ -59,10 +61,12 @@ int main(int argc, char *argv[])
#endif
Dialog dialog;
- const QRect availableGeometry = QApplication::desktop()->availableGeometry(&dialog);
- dialog.resize(availableGeometry.width() / 3, availableGeometry.height() * 2 / 3);
- dialog.move((availableGeometry.width() - dialog.width()) / 2,
- (availableGeometry.height() - dialog.height()) / 2);
+ if (!QGuiApplication::styleHints()->showIsFullScreen() && !QGuiApplication::styleHints()->showIsMaximized()) {
+ const QRect availableGeometry = QApplication::desktop()->availableGeometry(&dialog);
+ dialog.resize(availableGeometry.width() / 3, availableGeometry.height() * 2 / 3);
+ dialog.move((availableGeometry.width() - dialog.width()) / 2,
+ (availableGeometry.height() - dialog.height()) / 2);
+ }
dialog.show();
return app.exec();
diff --git a/mkspecs/devices/common/linux_device_pre.conf b/mkspecs/devices/common/linux_device_pre.conf
index 16becbdd52..cfbdc23d63 100644
--- a/mkspecs/devices/common/linux_device_pre.conf
+++ b/mkspecs/devices/common/linux_device_pre.conf
@@ -23,3 +23,6 @@ QMAKE_AR = $${CROSS_COMPILE}ar cqs
QMAKE_OBJCOPY = $${CROSS_COMPILE}objcopy
QMAKE_NM = $${CROSS_COMPILE}nm -P
QMAKE_STRIP = $${CROSS_COMPILE}strip
+
+contains(DISTRO_OPTS, deb-multi-arch): \
+ PKG_CONFIG = $${CROSS_COMPILE}pkg-config
diff --git a/mkspecs/devices/linux-arm-generic-g++/qmake.conf b/mkspecs/devices/linux-arm-generic-g++/qmake.conf
new file mode 100644
index 0000000000..3dbd297b94
--- /dev/null
+++ b/mkspecs/devices/linux-arm-generic-g++/qmake.conf
@@ -0,0 +1,9 @@
+#
+# Generic qmake configuration for building with g++ on arm devices.
+#
+# A minimal configure line could look something like this:
+# ./configure -device arm-generic-g++ -device-option CROSS_COMPILE=arm-linux-gnueabi-
+
+include(../common/linux_device_pre.conf)
+include(../common/linux_arm_device_post.conf)
+load(qt_config)
diff --git a/mkspecs/devices/linux-arm-generic-g++/qplatformdefs.h b/mkspecs/devices/linux-arm-generic-g++/qplatformdefs.h
new file mode 100644
index 0000000000..5ae49b35dd
--- /dev/null
+++ b/mkspecs/devices/linux-arm-generic-g++/qplatformdefs.h
@@ -0,0 +1,34 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the qmake spec of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "../../linux-g++/qplatformdefs.h"
diff --git a/mkspecs/features/qml_plugin.prf b/mkspecs/features/qml_plugin.prf
index 1bc05caefe..daedeca3a0 100644
--- a/mkspecs/features/qml_plugin.prf
+++ b/mkspecs/features/qml_plugin.prf
@@ -90,7 +90,6 @@ load(qt_common)
qmlplugindump = qmlplugindump
importpath.name = QML2_IMPORT_PATH
}
- qtPrepareTool(QMLPLUGINDUMP, $$qmlplugindump)
importpath.value =
for(qmod, QTREPOS) {
qml1_target: \
@@ -100,7 +99,9 @@ load(qt_common)
exists($$qmod): importpath.value += $$shell_path($$qmod)
}
importpath.value = $$unique(importpath.value)
- qtAddToolEnv(QMLPLUGINDUMP, importpath)
+ QT_TOOL_ENV = importpath
+ qtPrepareTool(QMLPLUGINDUMP, $$qmlplugindump)
+ QT_TOOL_ENV =
TARGETPATHBASE = $$replace(TARGETPATH, \\.\\d+\$, )
qmltypes.target = qmltypes
qmltypes.commands = $$QMLPLUGINDUMP -nonrelocatable $$replace(TARGETPATHBASE, /, .) $$IMPORT_VERSION > $$QMLTYPEFILE
diff --git a/mkspecs/features/qt_build_config.prf b/mkspecs/features/qt_build_config.prf
index 7197f84c9a..eaf23cf63a 100644
--- a/mkspecs/features/qt_build_config.prf
+++ b/mkspecs/features/qt_build_config.prf
@@ -55,6 +55,9 @@ QMAKE_DIR_REPLACE_SANE = PRECOMPILED_DIR OBJECTS_DIR MOC_DIR RCC_DIR UI_DIR
cross_compile: \
CONFIG += force_bootstrap
+android|ios|winrt: \
+ CONFIG += builtin_testdata
+
CONFIG += \
create_prl link_prl \
prepare_docs qt_docs_targets \
diff --git a/mkspecs/features/qt_docs.prf b/mkspecs/features/qt_docs.prf
index bcc16ada78..15bd12072a 100644
--- a/mkspecs/features/qt_docs.prf
+++ b/mkspecs/features/qt_docs.prf
@@ -18,7 +18,19 @@ QMAKE_DOCS_TARGET = $$replace(QMAKE_DOCS, ^(.*/)?(.*)\\.qdocconf$, \\2)
isEmpty(QMAKE_DOCS_TARGETDIR): QMAKE_DOCS_TARGETDIR = $$QMAKE_DOCS_TARGET
QMAKE_DOCS_OUTPUTDIR = $$QMAKE_DOCS_BASE_OUTDIR/$$QMAKE_DOCS_TARGETDIR
+qtver.name = QT_VERSION
+qtver.value = $$VERSION
+isEmpty(qtver.value): qtver.value = $$MODULE_VERSION
+isEmpty(qtver.value): error("No version for documentation specified.")
+qtmver.name = QT_VER
+qtmver.value = $$replace(qtver.value, ^(\\d+\\.\\d+).*$, \\1)
+qtvertag.name = QT_VERSION_TAG
+qtvertag.value = $$replace(qtver.value, \.,)
+qtdocs.name = QT_INSTALL_DOCS
+qtdocs.value = $$[QT_INSTALL_DOCS/src]
+QT_TOOL_ENV = qtver qtmver qtvertag qtdocs
qtPrepareTool(QDOC, qdoc)
+QT_TOOL_ENV =
QDOC += -outputdir $$QMAKE_DOCS_OUTPUTDIR
!build_online_docs: \
QDOC += -installdir $$[QT_INSTALL_DOCS]
@@ -43,17 +55,6 @@ DOC_INDEXES =
PREP_DOC_INDEXES += -indexdir $$[QT_INSTALL_DOCS/get]
DOC_INDEXES += -indexdir $$[QT_INSTALL_DOCS/get]
}
-qtver.name = QT_VERSION
-qtver.value = $$VERSION
-isEmpty(qtver.value): qtver.value = $$MODULE_VERSION
-isEmpty(qtver.value): error("No version for documentation specified.")
-qtmver.name = QT_VER
-qtmver.value = $$replace(qtver.value, ^(\\d+\\.\\d+).*$, \\1)
-qtvertag.name = QT_VERSION_TAG
-qtvertag.value = $$replace(qtver.value, \.,)
-qtdocs.name = QT_INSTALL_DOCS
-qtdocs.value = $$[QT_INSTALL_DOCS/src]
-qtAddToolEnv(QDOC, qtver qtmver qtvertag qtdocs)
doc_command = $$QDOC $$QMAKE_DOCS
prepare_docs {
prepare_docs.commands += $$doc_command -prepare $$PREP_DOC_INDEXES -no-link-errors
diff --git a/mkspecs/features/qt_tool.prf b/mkspecs/features/qt_tool.prf
index d9d4df6de5..bdeb59c83d 100644
--- a/mkspecs/features/qt_tool.prf
+++ b/mkspecs/features/qt_tool.prf
@@ -73,3 +73,5 @@ DEFINES *= QT_USE_QSTRINGBUILDER
cache(QT_TOOL.$${MODULE}.$$var, transient)
}
+# The variable is re-used by qtPrepareTool(), and we really don't want that.
+unset(QT_TOOL_ENV)
diff --git a/mkspecs/features/testcase.prf b/mkspecs/features/testcase.prf
index 2f95aafd0a..0340b7ed3c 100644
--- a/mkspecs/features/testcase.prf
+++ b/mkspecs/features/testcase.prf
@@ -79,7 +79,7 @@ isEmpty(BUILDS)|build_pass {
INSTALLS += target
}
-contains(INSTALLS, target) {
+!builtin_testdata:contains(INSTALLS, target) {
# Install testdata and helpers as well, but only if we're actually installing the test.
#
# Testdata is installed relative to the directory containing the testcase
@@ -175,6 +175,20 @@ contains(INSTALLS, target) {
}
}
+builtin_testdata {
+ ALL_TESTDATA = $$TESTDATA $$GENERATED_TESTDATA
+ # RESOURCES does not support wildcards (for good reasons)
+ for(td, ALL_TESTDATA): \
+ testdata.files += $$files($$absolute_path($$td, $$_PRO_FILE_PWD_))
+ !isEmpty(testdata.files) {
+ testdata.base = $$_PRO_FILE_PWD_
+ RESOURCES += testdata
+ }
+
+ !isEmpty(TEST_HELPER_INSTALLS): \
+ error("This platform does not support tests which require helpers.")
+}
+
macx-xcode:bundle:isEmpty(QMAKE_BUNDLE_EXTENSION) {
QMAKE_PBX_PRODUCT_TYPE = com.apple.product-type.bundle.unit-test
QMAKE_PBX_BUNDLE_TYPE = wrapper.cfbundle
diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc
index ff7b7fe1da..89ce3b3504 100644
--- a/qmake/doc/src/qmake-manual.qdoc
+++ b/qmake/doc/src/qmake-manual.qdoc
@@ -2408,7 +2408,6 @@
\row \li .file \li Specify the subproject \c pro file explicitly. Cannot be
used in conjunction with \c .subdir modifier.
\row \li .depends \li This subproject depends on specified subproject.
- Available only on platforms that use makefiles.
\row \li .makefile \li The makefile of subproject.
Available only on platforms that use makefiles.
\row \li .target \li Base string used for makefile targets related to this
diff --git a/qmake/generators/makefiledeps.cpp b/qmake/generators/makefiledeps.cpp
index 0f11745f4c..047d17f18a 100644
--- a/qmake/generators/makefiledeps.cpp
+++ b/qmake/generators/makefiledeps.cpp
@@ -388,6 +388,121 @@ QFileInfo QMakeSourceFileInfo::findFileInfo(const QMakeLocalFileName &dep)
return QFileInfo(dep.real());
}
+static int skipEscapedLineEnds(const char *buffer, int buffer_len, int offset, int *lines)
+{
+ // Join physical lines to make logical lines, as in the C preprocessor
+ while (offset + 1 < buffer_len
+ && buffer[offset] == '\\'
+ && qmake_endOfLine(buffer[offset + 1])) {
+ offset += 2;
+ ++*lines;
+ if (offset < buffer_len
+ && buffer[offset - 1] == '\r'
+ && buffer[offset] == '\n') // CRLF
+ offset++;
+ }
+ return offset;
+}
+
+static bool matchWhileUnsplitting(const char *buffer, int buffer_len, int start,
+ const char *needle, int needle_len,
+ int *matchlen, int *lines)
+{
+ int x = start;
+ for (int n = 0; n < needle_len && x < buffer_len;
+ n++, x = skipEscapedLineEnds(buffer, buffer_len, x + 1, lines)) {
+ if (buffer[x] != needle[n])
+ return false;
+ }
+ // That also skipped any remaining BSNLs immediately after the match.
+
+ // Tell caller how long the match was:
+ *matchlen = x - start;
+
+ return true;
+}
+
+/* Advance from an opening quote at buffer[offset] to the matching close quote. */
+static int scanPastString(char *buffer, int buffer_len, int offset, int *lines)
+{
+ // It might be a C++11 raw string.
+ bool israw = false;
+ if (buffer[offset] == '"' && offset > 0) {
+ int explore = offset - 1;
+ while (explore > 0 && buffer[explore] != 'R') {
+ if (buffer[explore] == '8' || buffer[explore] == 'u' || buffer[explore] == 'U') {
+ explore--;
+ } else if (explore > 1 && qmake_endOfLine(buffer[explore])
+ && buffer[explore - 1] == '\\') {
+ explore -= 2;
+ } else if (explore > 2 && buffer[explore] == '\n'
+ && buffer[explore - 1] == '\r'
+ && buffer[explore - 2] == '\\') {
+ explore -= 3;
+ } else {
+ break;
+ }
+ }
+ israw = (buffer[explore] == 'R');
+ }
+
+ if (israw) {
+#define SKIP_BSNL(pos) skipEscapedLineEnds(buffer, buffer_len, (pos), lines)
+
+ offset = SKIP_BSNL(offset + 1);
+ const char *const delim = buffer + offset;
+ int clean = offset;
+ while (offset < buffer_len && buffer[offset] != '(') {
+ if (clean < offset)
+ buffer[clean++] = buffer[offset];
+ else
+ clean++;
+
+ offset = SKIP_BSNL(offset + 1);
+ }
+ /*
+ Not checking correctness (trust real compiler to do that):
+ - no controls, spaces, '(', ')', '\\' or (presumably) '"' in delim;
+ - at most 16 bytes in delim
+
+ Raw strings are surely defined after phase 2, when BSNLs are resolved;
+ so the delimiter's exclusion of '\\' and space (including newlines)
+ applies too late to save us the need to cope with BSNLs in it.
+ */
+
+ const int delimlen = buffer + clean - delim;
+ int matchlen = delimlen, extralines = 0;
+ while ((offset = SKIP_BSNL(offset + 1)) < buffer_len
+ && (buffer[offset] != ')'
+ || (delimlen > 0 &&
+ !matchWhileUnsplitting(buffer, buffer_len,
+ offset + 1, delim, delimlen,
+ &matchlen, &extralines))
+ || buffer[offset + 1 + matchlen] != '"')) {
+ // skip, but keep track of lines
+ if (qmake_endOfLine(buffer[offset]))
+ ++*lines;
+ extralines = 0;
+ }
+ *lines += extralines; // from the match
+ // buffer[offset] is ')'
+ offset += 1 + matchlen; // 1 for ')', then delim
+ // buffer[offset] is '"'
+
+#undef SKIP_BSNL
+ } else { // Traditional string or char literal:
+ const char term = buffer[offset];
+ while (++offset < buffer_len && buffer[offset] != term) {
+ if (buffer[offset] == '\\')
+ ++offset;
+ else if (qmake_endOfLine(buffer[offset]))
+ ++*lines;
+ }
+ }
+
+ return offset;
+}
+
bool QMakeSourceFileInfo::findDeps(SourceFile *file)
{
if(file->dep_checked || file->type == TYPE_UNKNOWN)
@@ -426,6 +541,18 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file)
file->deps = new SourceDependChildren;
int line_count = 1;
+ enum {
+ /*
+ States of C preprocessing (for TYPE_C only), after backslash-newline
+ elimination and skipping comments and spaces (i.e. in ANSI X3.159-1989
+ section 2.1.1.2's phase 4). We're about to study buffer[x] to decide
+ on which transition to do.
+ */
+ AtStart, // start of logical line; a # may start a preprocessor directive
+ HadHash, // saw a # at start, looking for preprocessor keyword
+ WantName, // saw #include or #import, waiting for name
+ InCode // after directive, parsing non-#include directive or in actual code
+ } cpp_state = AtStart;
for(int x = 0; x < buffer_len; ++x) {
bool try_local = true;
@@ -505,118 +632,164 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file)
++line_count;
} else if(file->type == QMakeSourceFileInfo::TYPE_QRC) {
} else if(file->type == QMakeSourceFileInfo::TYPE_C) {
- for(int beginning=1; x < buffer_len; ++x) {
+ // We've studied all buffer[i] for i < x
+ for (; x < buffer_len; ++x) {
+ // How to handle backslash-newline (BSNL) pairs:
+#define SKIP_BSNL(pos) skipEscapedLineEnds(buffer, buffer_len, (pos), &line_count)
+
// Seek code or directive, skipping comments and space:
for(; x < buffer_len; ++x) {
+ x = SKIP_BSNL(x);
if (buffer[x] == ' ' || buffer[x] == '\t') {
// keep going
- } else if (buffer[x] == '/' && x + 1 < buffer_len &&
- (buffer[x + 1] == '/' || buffer[x + 1] == '*')) {
- ++x;
- if (buffer[x] == '/') { // C++-style comment
- for (; x < buffer_len && !qmake_endOfLine(buffer[x]); ++x) {} // skip
- beginning = 1;
- } else { // C-style comment
+ } else if (buffer[x] == '/') {
+ int extralines = 0;
+ int y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &extralines);
+ if (buffer[y] == '/') { // C++-style comment
+ line_count += extralines;
+ x = SKIP_BSNL(y + 1);
+ while (x < buffer_len && !qmake_endOfLine(buffer[x]))
+ x = SKIP_BSNL(x + 1); // skip
+
+ cpp_state = AtStart;
+ ++line_count;
+ } else if (buffer[y] == '*') { // C-style comment
+ line_count += extralines;
+ x = y;
while (++x < buffer_len) {
+ x = SKIP_BSNL(x);
if (buffer[x] == '*') {
- if (x + 1 < buffer_len && buffer[x + 1] == '/') {
- ++x; // skip '*'; for loop skips '/'.
+ extralines = 0;
+ y = skipEscapedLineEnds(buffer, buffer_len,
+ x + 1, &extralines);
+ if (y < buffer_len && buffer[y] == '/') {
+ line_count += extralines;
+ x = y; // for loop shall step past this
break;
}
} else if (qmake_endOfLine(buffer[x])) {
++line_count;
}
}
+ } else {
+ // buffer[x] is the division operator
+ break;
}
} else if (qmake_endOfLine(buffer[x])) {
++line_count;
- beginning = 1;
+ cpp_state = AtStart;
} else {
+ /* Drop out of phases 1, 2, 3, into phase 4 */
break;
}
}
+ // Phase 4 study of buffer[x]:
if(x >= buffer_len)
break;
- // preprocessor directive
- if (beginning && buffer[x] == '#') {
- // Advance to start of preprocessing directive
- while (++x < buffer_len
- && (buffer[x] == ' ' || buffer[x] == '\t')) {} // skip
-
- if (qmake_endOfLine(buffer[x])) {
- ++line_count;
- beginning = 1;
- continue;
+ switch (cpp_state) {
+ case HadHash:
+ {
+ // Read keyword; buffer[x] starts first preprocessing token after #
+ const char *const keyword = buffer + x;
+ int clean = x;
+ while (x < buffer_len && buffer[x] >= 'a' && buffer[x] <= 'z') {
+ // skip over keyword, consolidating it if it contains BSNLs
+ // (see WantName's similar code consolidating inc, below)
+ if (clean < x)
+ buffer[clean++] = buffer[x];
+ else
+ clean++;
+
+ x = SKIP_BSNL(x + 1);
}
+ const int keyword_len = buffer + clean - keyword;
+ x--; // Still need to study buffer[x] next time round for loop.
+
+ cpp_state =
+ ((keyword_len == 7 && !strncmp(keyword, "include", 7)) // C & Obj-C
+ || (keyword_len == 6 && !strncmp(keyword, "import", 6))) // Obj-C
+ ? WantName : InCode;
break;
}
- // quoted strings
- if (buffer[x] == '\'' || buffer[x] == '"') {
- const char term = buffer[x];
- while (++x < buffer_len) {
- if (buffer[x] == term) {
- ++x;
- break;
- } else if (buffer[x] == '\\') {
- ++x;
- } else if (qmake_endOfLine(buffer[x])) {
+ case WantName:
+ {
+ char term = buffer[x];
+ if (term == '<') {
+ try_local = false;
+ term = '>';
+ } else if (term != '"') {
+ /*
+ Possibly malformed, but this may be something like:
+ #include IDENTIFIER
+ which does work, if #define IDENTIFIER "filename" is
+ in effect. This is beyond this noddy preprocessor's
+ powers of tracking. So give up and resume searching
+ for a directive. We haven't made sense of buffer[x],
+ so back up to ensure we do study it (now as code) next
+ time round the loop.
+ */
+ x--;
+ cpp_state = InCode;
+ continue;
+ }
+
+ x = SKIP_BSNL(x + 1);
+ inc = buffer + x;
+ int clean = x; // offset if we need to clear \-newlines
+ for (; x < buffer_len && buffer[x] != term; x = SKIP_BSNL(x + 1)) {
+ if (qmake_endOfLine(buffer[x])) { // malformed
+ cpp_state = AtStart;
++line_count;
+ break;
}
+
+ /*
+ If we do skip any BSNLs, we need to consolidate the
+ surviving text by copying to lower indices. For that
+ to be possible, we also have to keep 'clean' advanced
+ in step with x even when we've yet to see any BSNLs.
+ */
+ if (clean < x)
+ buffer[clean++] = buffer[x];
+ else
+ clean++;
}
- }
- beginning = 0;
- }
- if(x >= buffer_len)
- break;
+ if (cpp_state == WantName)
+ buffer[clean] = '\0';
+ else // i.e. malformed
+ inc = 0;
- // Got a preprocessor directive
- const char *const keyword = buffer + x;
- for (;
- x < buffer_len && buffer[x] >= 'a' && buffer[x] <= 'z';
- x++) {} // skip over identifier
- int keyword_len = buffer + x - keyword;
- for (;
- x < buffer_len && (buffer[x] == ' ' || buffer[x] == '\t');
- x++) {} // skip spaces after keyword
-
- /* Keyword with nothing after it, e.g. #endif: not interesting. */
- if (qmake_endOfLine(buffer[x]))
- keyword_len = 0;
-
- if((keyword_len == 7 && !strncmp(keyword, "include", 7)) // C & Obj-C
- || (keyword_len == 6 && !strncmp(keyword, "import", 6))) { // Obj-C
- char term = buffer[x];
- if(term == '<') {
- try_local = false;
- term = '>';
- } else if(term != '"') { //wtf?
- continue;
+ cpp_state = InCode; // hereafter
+ break;
}
- x++;
- inc = buffer + x;
- for (;
- buffer[x] != term && !qmake_endOfLine(buffer[x]);
- ++x) {} // skip until end of include name
- buffer[x] = '\0';
- } else if (buffer[x] == '\'' || buffer[x] == '"') {
- const char term = buffer[x++];
- while(x < buffer_len) {
- if (buffer[x] == term)
+
+ case AtStart:
+ // Preprocessor directive?
+ if (buffer[x] == '#') {
+ cpp_state = HadHash;
break;
- if (buffer[x] == '\\') {
- x+=2;
- } else {
- if (qmake_endOfLine(buffer[x]))
- ++line_count;
- ++x;
}
+ cpp_state = InCode;
+ // ... and fall through to handle buffer[x] as such.
+ case InCode:
+ // matching quotes (string literals and character literals)
+ if (buffer[x] == '\'' || buffer[x] == '"') {
+ x = scanPastString(buffer, buffer_len, x, &line_count);
+ // for loop's ++x shall step over the closing quote.
+ }
+ // else: buffer[x] is just some code; move on.
+ break;
}
- } else {
- --x;
+
+ if (inc) // We were in WantName and found a name.
+ break;
+#undef SKIP_BSNL
}
+ if(x >= buffer_len)
+ break;
}
if(inc) {
@@ -699,7 +872,7 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file)
files_changed = true;
file->moc_checked = true;
- int buffer_len;
+ int buffer_len = 0;
char *buffer = 0;
{
struct stat fst;
@@ -717,42 +890,56 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file)
return false; //shouldn't happen
}
buffer = getBuffer(fst.st_size);
- for(int have_read = buffer_len = 0;
- (have_read = QT_READ(fd, buffer + buffer_len, fst.st_size - buffer_len));
- buffer_len += have_read) ;
+ while (int have_read = QT_READ(fd, buffer + buffer_len, fst.st_size - buffer_len))
+ buffer_len += have_read;
+
QT_CLOSE(fd);
}
debug_msg(2, "findMocs: %s", file->file.local().toLatin1().constData());
int line_count = 1;
- bool ignore_qobject = false, ignore_qgadget = false;
+ bool ignore[2] = { false, false }; // [0] for Q_OBJECT, [1] for Q_GADGET
/* qmake ignore Q_GADGET */
/* qmake ignore Q_OBJECT */
for(int x = 0; x < buffer_len; x++) {
+#define SKIP_BSNL(pos) skipEscapedLineEnds(buffer, buffer_len, (pos), &line_count)
+ x = SKIP_BSNL(x);
if (buffer[x] == '/') {
- ++x;
- if(buffer_len >= x) {
- if (buffer[x] == '/') { // C++-style comment
- for (; x < buffer_len && !qmake_endOfLine(buffer[x]); ++x) {} // skip
- } else if (buffer[x] == '*') { // C-style comment
- for(++x; x < buffer_len; ++x) {
+ int extralines = 0;
+ int y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &extralines);
+ if (buffer_len > y) {
+ // If comment, advance to the character that ends it:
+ if (buffer[y] == '/') { // C++-style comment
+ line_count += extralines;
+ x = y;
+ do {
+ x = SKIP_BSNL(x + 1);
+ } while (x < buffer_len && !qmake_endOfLine(buffer[x]));
+
+ } else if (buffer[y] == '*') { // C-style comment
+ line_count += extralines;
+ x = SKIP_BSNL(y + 1);
+ for (; x < buffer_len; x = SKIP_BSNL(x + 1)) {
if (buffer[x] == 't' || buffer[x] == 'q') { // ignore
if(buffer_len >= (x + 20) &&
!strncmp(buffer + x + 1, "make ignore Q_OBJECT", 20)) {
debug_msg(2, "Mocgen: %s:%d Found \"qmake ignore Q_OBJECT\"",
file->file.real().toLatin1().constData(), line_count);
x += 20;
- ignore_qobject = true;
+ ignore[0] = true;
} else if(buffer_len >= (x + 20) &&
!strncmp(buffer + x + 1, "make ignore Q_GADGET", 20)) {
debug_msg(2, "Mocgen: %s:%d Found \"qmake ignore Q_GADGET\"",
file->file.real().toLatin1().constData(), line_count);
x += 20;
- ignore_qgadget = true;
+ ignore[1] = true;
}
} else if (buffer[x] == '*') {
- if (buffer_len >= x + 1 && buffer[x + 1] == '/') {
- ++x;
+ extralines = 0;
+ y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &extralines);
+ if (buffer_len > y && buffer[y] == '/') {
+ line_count += extralines;
+ x = y;
break;
}
} else if (Option::debug_level && qmake_endOfLine(buffer[x])) {
@@ -760,56 +947,44 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file)
}
}
}
+ // else: don't update x, buffer[x] is just the division operator.
}
} else if (buffer[x] == '\'' || buffer[x] == '"') {
- const char term = buffer[x++];
- while(x < buffer_len) {
- if (buffer[x] == term)
- break;
- if (buffer[x] == '\\') {
- x+=2;
- } else {
- if (qmake_endOfLine(buffer[x]))
- ++line_count;
- ++x;
- }
- }
+ x = scanPastString(buffer, buffer_len, x, &line_count);
+ // Leaves us on closing quote; for loop's x++ steps us past it.
}
- if (Option::debug_level && qmake_endOfLine(buffer[x]))
+
+ if (x < buffer_len && Option::debug_level && qmake_endOfLine(buffer[x]))
++line_count;
- if (buffer_len > x + 2 && buffer[x + 1] == 'Q' &&
- buffer[x + 2] == '_' && !isCWordChar(buffer[x])) {
- ++x;
- int match = 0;
- static const char *interesting[] = { "OBJECT", "GADGET" };
- for (int interest = 0, m1, m2; interest < 2; ++interest) {
- if(interest == 0 && ignore_qobject)
- continue;
- else if(interest == 1 && ignore_qgadget)
- continue;
- for (m1 = 0, m2 = 0; interesting[interest][m1]; ++m1) {
- if (interesting[interest][m1] != buffer[x + 2 + m1]) {
- m2 = -1;
- break;
+ if (buffer_len > x + 8 && !isCWordChar(buffer[x])) {
+ int morelines = 0;
+ int y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &morelines);
+ if (buffer[y] == 'Q') {
+ static const char interesting[][9] = { "Q_OBJECT", "Q_GADGET" };
+ for (int interest = 0; interest < 2; ++interest) {
+ if (ignore[interest])
+ continue;
+
+ int matchlen = 0, extralines = 0;
+ if (matchWhileUnsplitting(buffer, buffer_len, y,
+ interesting[interest],
+ strlen(interesting[interest]),
+ &matchlen, &extralines)
+ && y + matchlen < buffer_len
+ && !isCWordChar(buffer[y + matchlen])) {
+ if (Option::debug_level) {
+ buffer[y + matchlen] = '\0';
+ debug_msg(2, "Mocgen: %s:%d Found MOC symbol %s",
+ file->file.real().toLatin1().constData(),
+ line_count + morelines, buffer + y);
+ }
+ file->mocable = true;
+ return true;
}
- ++m2;
- }
- if(m1 == m2) {
- match = m2 + 2;
- break;
- }
- }
- if (match && !isCWordChar(buffer[x + match])) {
- if (Option::debug_level) {
- buffer[x + match] = '\0';
- debug_msg(2, "Mocgen: %s:%d Found MOC symbol %s",
- file->file.real().toLatin1().constData(),
- line_count, buffer + x);
}
- file->mocable = true;
- return true;
}
}
+#undef SKIP_BSNL
}
return true;
}
diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp
index a546e03b59..06c99b6e38 100644
--- a/qmake/generators/win32/msvc_nmake.cpp
+++ b/qmake/generators/win32/msvc_nmake.cpp
@@ -142,18 +142,8 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t)
const bool isPhone = project->isActiveConfig(QStringLiteral("winphone"));
#ifdef Q_OS_WIN
- QString regKeyPrefix;
-#if !defined(Q_OS_WIN64) && _WIN32_WINNT >= 0x0501
- BOOL isWow64;
- IsWow64Process(GetCurrentProcess(), &isWow64);
- if (!isWow64)
- regKeyPrefix = QStringLiteral("Software\\");
- else
-#endif
- regKeyPrefix = QStringLiteral("Software\\Wow6432Node\\");
-
- QString regKey = regKeyPrefix + QStringLiteral("Microsoft\\VisualStudio\\") + msvcVer + ("\\Setup\\VC\\ProductDir");
- const QString vcInstallDir = qt_readRegistryKey(HKEY_LOCAL_MACHINE, regKey);
+ QString regKey = QStringLiteral("Software\\Microsoft\\VisualStudio\\") + msvcVer + ("\\Setup\\VC\\ProductDir");
+ const QString vcInstallDir = qt_readRegistryKey(HKEY_LOCAL_MACHINE, regKey, KEY_WOW64_32KEY);
if (vcInstallDir.isEmpty()) {
fprintf(stderr, "Failed to find the Visual Studio installation directory.\n");
return false;
@@ -161,13 +151,13 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t)
QString windowsPath;
if (isPhone) {
- windowsPath = "Microsoft\\Microsoft SDKs\\WindowsPhoneApp\\v";
+ windowsPath = "Software\\Microsoft\\Microsoft SDKs\\WindowsPhoneApp\\v";
} else {
- windowsPath = "Microsoft\\Microsoft SDKs\\Windows\\v";
+ windowsPath = "Software\\Microsoft\\Microsoft SDKs\\Windows\\v";
}
- regKey = regKeyPrefix + windowsPath + winsdkVer + QStringLiteral("\\InstallationFolder");
- const QString kitDir = qt_readRegistryKey(HKEY_LOCAL_MACHINE, regKey);
+ regKey = windowsPath + winsdkVer + QStringLiteral("\\InstallationFolder");
+ const QString kitDir = qt_readRegistryKey(HKEY_LOCAL_MACHINE, regKey, KEY_WOW64_32KEY);
if (kitDir.isEmpty()) {
fprintf(stderr, "Failed to find the Windows Kit installation directory.\n");
return false;
diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp
index d70480b028..1e187075c8 100644
--- a/qmake/generators/win32/msvc_vcproj.cpp
+++ b/qmake/generators/win32/msvc_vcproj.cpp
@@ -70,21 +70,6 @@ struct DotNetCombo {
const char *versionStr;
const char *regKey;
} dotNetCombo[] = {
-#ifdef Q_OS_WIN64
- {NET2015, "MSVC.NET 2015 (14.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\14.0\\Setup\\VC\\ProductDir"},
- {NET2013, "MSVC.NET 2013 (12.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\12.0\\Setup\\VC\\ProductDir"},
- {NET2013, "MSVC.NET 2013 Express Edition (12.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\12.0\\Setup\\VC\\ProductDir"},
- {NET2012, "MSVC.NET 2012 (11.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\11.0\\Setup\\VC\\ProductDir"},
- {NET2012, "MSVC.NET 2012 Express Edition (11.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\11.0\\Setup\\VC\\ProductDir"},
- {NET2010, "MSVC.NET 2010 (10.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\10.0\\Setup\\VC\\ProductDir"},
- {NET2010, "MSVC.NET 2010 Express Edition (10.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\10.0\\Setup\\VC\\ProductDir"},
- {NET2008, "MSVC.NET 2008 (9.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\9.0\\Setup\\VC\\ProductDir"},
- {NET2008, "MSVC.NET 2008 Express Edition (9.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\9.0\\Setup\\VC\\ProductDir"},
- {NET2005, "MSVC.NET 2005 (8.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\ProductDir"},
- {NET2005, "MSVC.NET 2005 Express Edition (8.0)", "Software\\Wow6432Node\\Microsoft\\VCExpress\\8.0\\Setup\\VC\\ProductDir"},
- {NET2003, "MSVC.NET 2003 (7.1)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\7.1\\Setup\\VC\\ProductDir"},
- {NET2002, "MSVC.NET 2002 (7.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\7.0\\Setup\\VC\\ProductDir"},
-#else
{NET2015, "MSVC.NET 2015 (14.0)", "Software\\Microsoft\\VisualStudio\\14.0\\Setup\\VC\\ProductDir"},
{NET2013, "MSVC.NET 2013 (12.0)", "Software\\Microsoft\\VisualStudio\\12.0\\Setup\\VC\\ProductDir"},
{NET2013, "MSVC.NET 2013 Express Edition (12.0)", "Software\\Microsoft\\VCExpress\\12.0\\Setup\\VC\\ProductDir"},
@@ -98,7 +83,6 @@ struct DotNetCombo {
{NET2005, "MSVC.NET 2005 Express Edition (8.0)", "Software\\Microsoft\\VCExpress\\8.0\\Setup\\VC\\ProductDir"},
{NET2003, "MSVC.NET 2003 (7.1)", "Software\\Microsoft\\VisualStudio\\7.1\\Setup\\VC\\ProductDir"},
{NET2002, "MSVC.NET 2002 (7.0)", "Software\\Microsoft\\VisualStudio\\7.0\\Setup\\VC\\ProductDir"},
-#endif
{NETUnknown, "", ""},
};
@@ -125,7 +109,8 @@ DotNET which_dotnet_version(const QByteArray &preferredVersion = QByteArray())
int installed = 0;
int i = 0;
for(; dotNetCombo[i].version; ++i) {
- QString path = qt_readRegistryKey(HKEY_LOCAL_MACHINE, dotNetCombo[i].regKey);
+ QString path = qt_readRegistryKey(HKEY_LOCAL_MACHINE, dotNetCombo[i].regKey,
+ KEY_WOW64_32KEY);
if (!path.isEmpty() && installPaths.value(dotNetCombo[i].version) != path) {
lowestInstalledVersion = &dotNetCombo[i];
installPaths.insert(lowestInstalledVersion->version, path);
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
index f75b6562af..0a10a12660 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
@@ -904,6 +904,7 @@ public class QtActivityDelegate
public void onDestroy()
{
if (m_quitApp) {
+ QtNative.terminateQt();
if (m_debuggerProcess != null)
m_debuggerProcess.destroy();
System.exit(0);// FIXME remove it or find a better way
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
index 804347e080..5ff5bbc32f 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
@@ -294,7 +294,12 @@ public class QtNative
private static void quitApp()
{
- m_activity.finish();
+ runAction(new Runnable() {
+ @Override
+ public void run() {
+ m_activity.finish();
+ }
+ });
}
//@ANDROID-9
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
index 9a25f56c5f..ab5734a298 100644
--- a/src/corelib/io/qprocess_unix.cpp
+++ b/src/corelib/io/qprocess_unix.cpp
@@ -92,6 +92,7 @@ QT_END_NAMESPACE
#include <private/qthread_p.h>
#include <qfile.h>
#include <qfileinfo.h>
+#include <qdir.h>
#include <qlist.h>
#include <qmutex.h>
#include <qsemaphore.h>
@@ -362,11 +363,14 @@ void QProcessPrivate::startProcess()
static QBasicMutex cfbundleMutex;
QMutexLocker lock(&cfbundleMutex);
QCFType<CFBundleRef> bundle = CFBundleCreate(0, url);
- url = CFBundleCopyExecutableURL(bundle);
+ // 'executableURL' can be either relative or absolute ...
+ QCFType<CFURLRef> executableURL = CFBundleCopyExecutableURL(bundle);
+ // not to depend on caching - make sure it's always absolute.
+ url = CFURLCopyAbsoluteURL(executableURL);
}
if (url) {
- QCFString str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
- encodedProgramName += "/Contents/MacOS/" + QCFString::toQString(str).toUtf8();
+ const QCFString str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
+ encodedProgramName += (QDir::separator() + QDir(program).relativeFilePath(QCFString::toQString(str))).toUtf8();
}
}
#endif
diff --git a/src/corelib/json/qjsonobject.cpp b/src/corelib/json/qjsonobject.cpp
index b7dfe88434..c225606717 100644
--- a/src/corelib/json/qjsonobject.cpp
+++ b/src/corelib/json/qjsonobject.cpp
@@ -693,6 +693,11 @@ QJsonObject::const_iterator QJsonObject::constFind(const QString &key) const
\internal
*/
+/*! \typedef QJsonObject::iterator::pointer
+
+ \internal
+*/
+
/*! \fn QJsonObject::iterator::iterator()
Constructs an uninitialized iterator.
@@ -895,6 +900,11 @@ QJsonObject::const_iterator QJsonObject::constFind(const QString &key) const
\internal
*/
+/*! \typedef QJsonObject::const_iterator::pointer
+
+ \internal
+*/
+
/*! \fn QJsonObject::const_iterator::const_iterator()
Constructs an uninitialized iterator.
diff --git a/src/corelib/json/qjsonobject.h b/src/corelib/json/qjsonobject.h
index 19c938fd83..5b475f52ae 100644
--- a/src/corelib/json/qjsonobject.h
+++ b/src/corelib/json/qjsonobject.h
@@ -104,6 +104,7 @@ public:
typedef int difference_type;
typedef QJsonValue value_type;
typedef QJsonValueRef reference;
+ typedef QJsonValuePtr pointer;
Q_DECL_CONSTEXPR inline iterator() : o(Q_NULLPTR), i(0) {}
Q_DECL_CONSTEXPR inline iterator(QJsonObject *obj, int index) : o(obj), i(index) {}
@@ -146,6 +147,7 @@ public:
typedef int difference_type;
typedef QJsonValue value_type;
typedef QJsonValue reference;
+ typedef QJsonValuePtr pointer;
Q_DECL_CONSTEXPR inline const_iterator() : o(Q_NULLPTR), i(0) {}
Q_DECL_CONSTEXPR inline const_iterator(const QJsonObject *obj, int index)
diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp
index 58b87bd36b..df070dd1ae 100644
--- a/src/corelib/kernel/qeventdispatcher_winrt.cpp
+++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp
@@ -201,14 +201,16 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
{
Q_D(QEventDispatcherWinRT);
+ DWORD waitTime = 0;
do {
// Additional user events have to be handled before timer events, but the function may not
// return yet.
const bool userEventsSent = sendPostedEvents(flags);
- emit aboutToBlock();
const QVector<HANDLE> timerHandles = d->timerIdToHandle.values().toVector();
- DWORD waitResult = WaitForMultipleObjectsEx(timerHandles.count(), timerHandles.constData(), FALSE, 1, TRUE);
+ if (waitTime)
+ emit aboutToBlock();
+ DWORD waitResult = WaitForMultipleObjectsEx(timerHandles.count(), timerHandles.constData(), FALSE, waitTime, TRUE);
if (waitResult >= WAIT_OBJECT_0 && waitResult < WAIT_OBJECT_0 + timerHandles.count()) {
const HANDLE handle = timerHandles.value(waitResult - WAIT_OBJECT_0);
ResetEvent(handle);
@@ -231,6 +233,13 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
if (userEventsSent)
return true;
+
+ // We cannot wait infinitely like on other platforms, as
+ // WaitForMultipleObjectsEx might not return.
+ // For instance win32 uses MsgWaitForMultipleObjects to hook
+ // into the native event loop, while WinRT handles those
+ // via callbacks.
+ waitTime = 1;
} while (flags & QEventLoop::WaitForMoreEvents);
return false;
}
diff --git a/src/corelib/kernel/qsharedmemory_win.cpp b/src/corelib/kernel/qsharedmemory_win.cpp
index 5cc54b1def..f90763d308 100644
--- a/src/corelib/kernel/qsharedmemory_win.cpp
+++ b/src/corelib/kernel/qsharedmemory_win.cpp
@@ -58,7 +58,7 @@ void QSharedMemoryPrivate::setErrorString(QLatin1String function)
errorString = QSharedMemory::tr("%1: already exists").arg(function);
break;
case ERROR_FILE_NOT_FOUND:
-#ifdef Q_OS_WINCE
+#if defined(Q_OS_WINCE) || (defined(Q_OS_WINRT) && _MSC_VER < 1900)
// This happens on CE only if no file is present as CreateFileMappingW
// bails out with this error code
case ERROR_INVALID_PARAMETER:
@@ -101,7 +101,11 @@ HANDLE QSharedMemoryPrivate::handle()
Q_UNIMPLEMENTED();
hand = 0;
#elif defined(Q_OS_WINRT)
+#if _MSC_VER >= 1900
+ hand = OpenFileMappingFromApp(FILE_MAP_ALL_ACCESS, FALSE, reinterpret_cast<PCWSTR>(nativeKey.utf16()));
+#else
hand = CreateFileMappingFromApp(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, (PCWSTR)nativeKey.utf16());
+#endif
#elif defined(Q_OS_WINCE)
// This works for opening a mapping too, but always opens it with read/write access in
// attach as it seems.
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index 4c7e498280..bed0e193db 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -772,7 +772,7 @@ namespace QtPrivate {
QVariantHash l;
l.reserve(iter.size());
for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
- l.insert(it.key().toString(), it.value());
+ l.insertMulti(it.key().toString(), it.value());
return l;
}
return QVariantValueHelper<QVariantHash>::invoke(v);
@@ -788,7 +788,7 @@ namespace QtPrivate {
QAssociativeIterable iter = QVariantValueHelperInterface<QAssociativeIterable>::invoke(v);
QVariantMap l;
for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it)
- l.insert(it.key().toString(), it.value());
+ l.insertMulti(it.key().toString(), it.value());
return l;
}
return QVariantValueHelper<QVariantMap>::invoke(v);
diff --git a/src/corelib/plugin/qlibrary_win.cpp b/src/corelib/plugin/qlibrary_win.cpp
index c1ce198c84..f5604a24bd 100644
--- a/src/corelib/plugin/qlibrary_win.cpp
+++ b/src/corelib/plugin/qlibrary_win.cpp
@@ -124,7 +124,8 @@ bool QLibraryPrivate::load_sys()
SetErrorMode(oldmode);
#endif
if (!pHnd) {
- errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName).arg(qt_error_string());
+ errorString = QLibrary::tr("Cannot load library %1: %2").arg(
+ QDir::toNativeSeparators(fileName)).arg(qt_error_string());
} else {
// Query the actual name of the library that was loaded
errorString.clear();
@@ -148,7 +149,8 @@ bool QLibraryPrivate::load_sys()
bool QLibraryPrivate::unload_sys()
{
if (!FreeLibrary(pHnd)) {
- errorString = QLibrary::tr("Cannot unload library %1: %2").arg(fileName).arg(qt_error_string());
+ errorString = QLibrary::tr("Cannot unload library %1: %2").arg(
+ QDir::toNativeSeparators(fileName)).arg(qt_error_string());
return false;
}
errorString.clear();
@@ -164,7 +166,8 @@ QFunctionPointer QLibraryPrivate::resolve_sys(const char* symbol)
#endif
if (!address) {
errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg(
- QString::fromLatin1(symbol)).arg(fileName).arg(qt_error_string());
+ QString::fromLatin1(symbol)).arg(
+ QDir::toNativeSeparators(fileName)).arg(qt_error_string());
} else {
errorString.clear();
}
diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h
index ace6c5d093..6827483464 100644
--- a/src/corelib/tools/qsharedpointer_impl.h
+++ b/src/corelib/tools/qsharedpointer_impl.h
@@ -500,7 +500,7 @@ private:
template <class X>
inline void enableSharedFromThis(const QEnableSharedFromThis<X> *ptr)
{
- ptr->initializeFromSharedPointer(*this);
+ ptr->initializeFromSharedPointer(constCast<typename QtPrivate::remove_cv<T>::type>());
}
inline void enableSharedFromThis(...) {}
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index b582204d67..2f340477fc 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -1819,6 +1819,17 @@ QString &QString::operator=(const QString &other) Q_DECL_NOTHROW
Assigns the Latin-1 string \a str to this string.
*/
+QString &QString::operator=(QLatin1String other)
+{
+ if (isDetached() && other.size() <= capacity()) { // assumes d->alloc == 0 → !isDetached() (sharedNull)
+ d->size = other.size();
+ d->data()[other.size()] = 0;
+ qt_from_latin1(d->data(), other.latin1(), other.size());
+ } else {
+ *this = fromLatin1(other.latin1(), other.size());
+ }
+ return *this;
+}
/*! \fn QString &QString::operator=(const QByteArray &ba)
@@ -1869,7 +1880,16 @@ QString &QString::operator=(const QString &other) Q_DECL_NOTHROW
*/
QString &QString::operator=(QChar ch)
{
- return operator=(QString(ch));
+ if (isDetached() && capacity() >= 1) { // assumes d->alloc == 0 → !isDetached() (sharedNull)
+ // re-use existing capacity:
+ ushort *dat = d->data();
+ dat[0] = ch.unicode();
+ dat[1] = 0;
+ d->size = 1;
+ } else {
+ operator=(QString(ch));
+ }
+ return *this;
}
/*!
@@ -5667,7 +5687,7 @@ QString QString::rightJustified(int width, QChar fill, bool truncate) const
*/
namespace QUnicodeTables {
-/*!
+/*
\internal
Converts the \a str string starting from the position pointed to by the \a
it iterator, using the Unicode case traits \c Traits, and returns the
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 4ae81f9269..75f94d7f93 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -221,7 +221,7 @@ public:
inline ~QString();
QString &operator=(QChar c);
QString &operator=(const QString &) Q_DECL_NOTHROW;
- inline QString &operator=(QLatin1String latin1);
+ QString &operator=(QLatin1String latin1);
#ifdef Q_COMPILER_RVALUE_REFS
inline QString(QString && other) Q_DECL_NOTHROW : d(other.d) { other.d = Data::sharedNull(); }
inline QString &operator=(QString &&other) Q_DECL_NOTHROW
@@ -885,11 +885,6 @@ inline void QString::detach()
{ if (d->ref.isShared() || (d->offset != sizeof(QStringData))) reallocData(uint(d->size) + 1u); }
inline bool QString::isDetached() const
{ return !d->ref.isShared(); }
-inline QString &QString::operator=(QLatin1String s)
-{
- *this = fromLatin1(s.latin1(), s.size());
- return *this;
-}
inline void QString::clear()
{ if (!isNull()) *this = QString(); }
inline QString::QString(const QString &other) Q_DECL_NOTHROW : d(other.d)
diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/tools/qtimezone.cpp
index 57c1838b76..333a5c3471 100644
--- a/src/corelib/tools/qtimezone.cpp
+++ b/src/corelib/tools/qtimezone.cpp
@@ -695,6 +695,11 @@ QTimeZone::OffsetData QTimeZone::offsetData(const QDateTime &forDateTime) const
/*!
Returns \c true if the system backend supports obtaining transitions.
+
+ Transitions are changes in the time-zone: these happen when DST turns on or
+ off and when authorities alter the offsets for the time-zone.
+
+ \sa nextTransition(), previousTransition(), transitions()
*/
bool QTimeZone::hasTransitions() const
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index cbdcf49da7..cc79e73534 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -2967,15 +2967,6 @@ static void qInitImageConversions()
#endif
}
-class QImageConversionsInitializer {
-public:
- QImageConversionsInitializer()
- {
- qInitImageConversions();
- }
-};
-
-// Ensure initialization if this object file is linked.
-static QImageConversionsInitializer qImageConversionsInitializer;
+Q_CONSTRUCTOR_FUNCTION(qInitImageConversions);
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformdialoghelper.h b/src/gui/kernel/qplatformdialoghelper.h
index 936dbdfa89..5b2f4ece77 100644
--- a/src/gui/kernel/qplatformdialoghelper.h
+++ b/src/gui/kernel/qplatformdialoghelper.h
@@ -104,6 +104,7 @@ public:
};
Q_DECLARE_FLAGS(StandardButtons, StandardButton)
+ Q_FLAG(StandardButtons)
enum ButtonRole {
// keep this in sync with QDialogButtonBox::ButtonRole and QMessageBox::ButtonRole
@@ -128,6 +129,7 @@ public:
Reverse = 0x40000000,
EOL = InvalidRole
};
+ Q_ENUM(ButtonRole)
enum ButtonLayout {
// keep this in sync with QDialogButtonBox::ButtonLayout and QMessageBox::ButtonLayout
@@ -167,6 +169,7 @@ QT_BEGIN_NAMESPACE
class Q_GUI_EXPORT QColorDialogOptions
{
+ Q_GADGET
public:
enum ColorDialogOption {
ShowAlphaChannel = 0x00000001,
@@ -175,6 +178,7 @@ public:
};
Q_DECLARE_FLAGS(ColorDialogOptions, ColorDialogOption)
+ Q_FLAG(ColorDialogOptions)
QColorDialogOptions();
QColorDialogOptions(const QColorDialogOptions &rhs);
@@ -226,6 +230,7 @@ private:
class Q_GUI_EXPORT QFontDialogOptions
{
+ Q_GADGET
public:
enum FontDialogOption {
NoButtons = 0x00000001,
@@ -237,6 +242,7 @@ public:
};
Q_DECLARE_FLAGS(FontDialogOptions, FontDialogOption)
+ Q_FLAG(FontDialogOptions)
QFontDialogOptions();
QFontDialogOptions(const QFontDialogOptions &rhs);
@@ -279,11 +285,19 @@ private:
class Q_GUI_EXPORT QFileDialogOptions
{
+ Q_GADGET
public:
enum ViewMode { Detail, List };
+ Q_ENUM(ViewMode)
+
enum FileMode { AnyFile, ExistingFile, Directory, ExistingFiles, DirectoryOnly };
+ Q_ENUM(FileMode)
+
enum AcceptMode { AcceptOpen, AcceptSave };
+ Q_ENUM(AcceptMode)
+
enum DialogLabel { LookIn, FileName, FileType, Accept, Reject, DialogLabelCount };
+ Q_ENUM(DialogLabel)
enum FileDialogOption
{
@@ -297,6 +311,7 @@ public:
DontUseCustomDirectoryIcons = 0x00000080
};
Q_DECLARE_FLAGS(FileDialogOptions, FileDialogOption)
+ Q_FLAG(FileDialogOptions)
QFileDialogOptions();
QFileDialogOptions(const QFileDialogOptions &rhs);
@@ -396,9 +411,11 @@ private:
class Q_GUI_EXPORT QMessageDialogOptions
{
+ Q_GADGET
public:
// Keep in sync with QMessageBox::Icon
enum Icon { NoIcon, Information, Warning, Critical, Question };
+ Q_ENUM(Icon)
QMessageDialogOptions();
QMessageDialogOptions(const QMessageDialogOptions &rhs);
diff --git a/src/gui/kernel/qplatformmenu.h b/src/gui/kernel/qplatformmenu.h
index 1022d0ed4a..bc0b3a4870 100644
--- a/src/gui/kernel/qplatformmenu.h
+++ b/src/gui/kernel/qplatformmenu.h
@@ -63,6 +63,7 @@ public:
// They could be added as public QAction roles if necessary.
CutRole, CopyRole, PasteRole, SelectAllRole,
RoleCount };
+ Q_ENUM(MenuRole)
virtual void setTag(quintptr tag) = 0;
virtual quintptr tag()const = 0;
@@ -91,6 +92,7 @@ class Q_GUI_EXPORT QPlatformMenu : public QObject
Q_OBJECT
public:
enum MenuType { DefaultMenu = 0, EditMenu };
+ Q_ENUM(MenuType)
virtual void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) = 0;
virtual void removeMenuItem(QPlatformMenuItem *menuItem) = 0;
diff --git a/src/gui/kernel/qplatformsystemtrayicon.h b/src/gui/kernel/qplatformsystemtrayicon.h
index 437f5e02b1..6ef2d1538f 100644
--- a/src/gui/kernel/qplatformsystemtrayicon.h
+++ b/src/gui/kernel/qplatformsystemtrayicon.h
@@ -57,8 +57,10 @@ public:
Trigger,
MiddleClick
};
+ Q_ENUM(ActivationReason)
enum MessageIcon { NoIcon, Information, Warning, Critical };
+ Q_ENUM(MessageIcon)
QPlatformSystemTrayIcon();
~QPlatformSystemTrayIcon();
diff --git a/src/gui/kernel/qplatformtheme.h b/src/gui/kernel/qplatformtheme.h
index 9355e83491..2bd35491fb 100644
--- a/src/gui/kernel/qplatformtheme.h
+++ b/src/gui/kernel/qplatformtheme.h
@@ -164,6 +164,8 @@ public:
SmallFont,
MiniFont,
FixedFont,
+ GroupBoxTitleFont,
+ TabButtonFont,
NFonts
};
diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp
index fb322ae74f..52e7686439 100644
--- a/src/gui/kernel/qscreen.cpp
+++ b/src/gui/kernel/qscreen.cpp
@@ -116,8 +116,8 @@ QScreen::~QScreen()
bool movingFromVirtualSibling = primaryScreen && primaryScreen->handle()->virtualSiblings().contains(handle());
// Move any leftover windows to the primary screen
- foreach (QWindow *window, QGuiApplication::topLevelWindows()) {
- if (window->screen() != this)
+ foreach (QWindow *window, QGuiApplication::allWindows()) {
+ if (!window->isTopLevel() || window->screen() != this)
continue;
const bool wasVisible = window->isVisible();
diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h
index 23a6d800c0..6880edaada 100644
--- a/src/gui/kernel/qwindow_p.h
+++ b/src/gui/kernel/qwindow_p.h
@@ -50,6 +50,7 @@
#include <qpa/qplatformwindow.h>
#include <QtCore/private/qobject_p.h>
+#include <QtCore/qelapsedtimer.h>
#include <QtGui/QIcon>
QT_BEGIN_NAMESPACE
@@ -187,6 +188,7 @@ public:
#endif
bool compositing;
+ QElapsedTimer lastComposeTime;
};
diff --git a/src/gui/opengl/qopengltexture.cpp b/src/gui/opengl/qopengltexture.cpp
index 301b2ad13d..02dee5a90a 100644
--- a/src/gui/opengl/qopengltexture.cpp
+++ b/src/gui/opengl/qopengltexture.cpp
@@ -97,9 +97,11 @@ QOpenGLTexturePrivate::QOpenGLTexturePrivate(QOpenGLTexture::Target textureTarge
break;
case QOpenGLTexture::TargetCubeMap:
bindingTarget = QOpenGLTexture::BindingTargetCubeMap;
+ faces = 6;
break;
case QOpenGLTexture::TargetCubeMapArray:
bindingTarget = QOpenGLTexture::BindingTargetCubeMapArray;
+ faces = 6;
break;
case QOpenGLTexture::Target2DMultisample:
bindingTarget = QOpenGLTexture::BindingTarget2DMultisample;
@@ -175,7 +177,7 @@ bool QOpenGLTexturePrivate::create()
void QOpenGLTexturePrivate::destroy()
{
- if (!context) {
+ if (!textureId) {
// not created or already destroyed
return;
}
diff --git a/src/gui/opengl/qopengltexture_p.h b/src/gui/opengl/qopengltexture_p.h
index ac9d44db42..40ceb1936c 100644
--- a/src/gui/opengl/qopengltexture_p.h
+++ b/src/gui/opengl/qopengltexture_p.h
@@ -156,7 +156,6 @@ public:
bool autoGenerateMipMaps;
bool storageAllocated;
- QPair<int, int> glVersion;
QOpenGLTextureHelper *texFuncs;
QOpenGLTexture::Features features;
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 4e40d250d3..e7b81ebdd3 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -32,11 +32,6 @@
****************************************************************************/
#include <qglobal.h>
-#ifdef Q_OS_IOS
-// We don't build the NEON drawhelpers as they are implemented partly
-// in GAS syntax assembly, which is not supported by the iOS toolchain.
-#undef __ARM_NEON__
-#endif
#include <qstylehints.h>
#include <qguiapplication.h>
@@ -6314,8 +6309,13 @@ void qt_memfill32(quint32 *dest, quint32 color, int count)
template<QtPixelOrder> const uint *QT_FASTCALL convertA2RGB30PMFromARGB32PM_sse4(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *);
#endif
+extern void qInitBlendFunctions();
+
static void qInitDrawhelperFunctions()
{
+ // Set up basic blend function tables.
+ qInitBlendFunctions();
+
#ifdef __SSE2__
qDrawHelper[QImage::Format_RGB32].bitmapBlit = qt_bitmapblit32_sse2;
qDrawHelper[QImage::Format_ARGB32].bitmapBlit = qt_bitmapblit32_sse2;
@@ -6411,7 +6411,7 @@ static void qInitDrawhelperFunctions()
#endif // SSE2
-#if defined(__ARM_NEON__) && !defined(Q_OS_IOS)
+#if defined(__ARM_NEON__)
qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;
@@ -6432,7 +6432,7 @@ static void qInitDrawhelperFunctions()
qt_fetch_radial_gradient = qt_fetch_radial_gradient_neon;
-#if !defined(Q_PROCESSOR_ARM_64)
+#if defined(ENABLE_PIXMAN_DRAWHELPERS)
// The RGB16 helpers are using Arm32 assemblythat has not been ported to AArch64
qBlendFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_rgb16_neon;
qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB16] = qt_blend_rgb16_on_argb32_neon;
@@ -6509,19 +6509,7 @@ static void qInitDrawhelperFunctions()
#endif // QT_COMPILER_SUPPORTS_MIPS_DSP || QT_COMPILER_SUPPORTS_MIPS_DSPR2
}
-extern void qInitBlendFunctions();
-class DrawHelperInitializer {
-public:
- DrawHelperInitializer()
- {
- // Set up basic blend function tables.
- qInitBlendFunctions();
- // Set up architecture optimized methods for the current machine.
- qInitDrawhelperFunctions();
- }
-};
-
// Ensure initialization if this object file is linked.
-static DrawHelperInitializer drawHelperInitializer;
+Q_CONSTRUCTOR_FUNCTION(qInitDrawhelperFunctions);
QT_END_NAMESPACE
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 7f8000c856..8409481ad5 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -3653,8 +3653,9 @@ QImage::Format QRasterBuffer::prepare(QImage *image)
drawHelper = qDrawHelper + format;
if (image->depth() == 1 && image->colorTable().size() == 2) {
monoDestinationWithClut = true;
- destColor0 = qPremultiply(image->colorTable()[0]);
- destColor1 = qPremultiply(image->colorTable()[1]);
+ const QVector<QRgb> colorTable = image->colorTable();
+ destColor0 = qPremultiply(colorTable[0]);
+ destColor1 = qPremultiply(colorTable[1]);
}
return format;
diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp
index 4e26d8f741..cda2446a5e 100644
--- a/src/gui/painting/qplatformbackingstore.cpp
+++ b/src/gui/painting/qplatformbackingstore.cpp
@@ -301,6 +301,8 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
return;
}
+ QWindowPrivate::get(window)->lastComposeTime.start();
+
QOpenGLFunctions *funcs = context->functions();
funcs->glViewport(0, 0, window->width() * window->devicePixelRatio(), window->height() * window->devicePixelRatio());
funcs->glClearColor(0, 0, 0, translucentBackground ? 0 : 1);
diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp
index e6b777a30e..5e648eabf5 100644
--- a/src/gui/painting/qregion.cpp
+++ b/src/gui/painting/qregion.cpp
@@ -41,7 +41,7 @@
#include "qimage.h"
#include "qbitmap.h"
-#include <qdebug.h>
+#include <private/qdebug_p.h>
QT_BEGIN_NAMESPACE
@@ -422,11 +422,32 @@ QDataStream &operator>>(QDataStream &s, QRegion &r)
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug s, const QRegion &r)
{
- QVector<QRect> rects = r.rects();
- s.nospace() << "QRegion(size=" << rects.size() << "), "
- << "bounds = " << r.boundingRect() << '\n';
- for (int i=0; i<rects.size(); ++i)
- s << "- " << i << rects.at(i) << '\n';
+ QDebugStateSaver saver(s);
+ s.nospace();
+ s << "QRegion(";
+ if (r.isNull()) {
+ s << "null";
+ } else if (r.isEmpty()) {
+ s << "empty";
+ } else {
+ const QVector<QRect> rects = r.rects();
+ const int count = rects.size();
+ if (count > 1)
+ s << "size=" << count << ", bounds=(";
+ QtDebugUtils::formatQRect(s, r.boundingRect());
+ if (count > 1) {
+ s << ") - [";
+ for (int i = 0; i < count; ++i) {
+ if (i)
+ s << ", ";
+ s << '(';
+ QtDebugUtils::formatQRect(s, rects.at(i));
+ s << ')';
+ }
+ s << ']';
+ }
+ }
+ s << ')';
return s;
}
#endif
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index a0a64cae01..ed4a932a32 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -2110,6 +2110,9 @@ QString QFont::lastResortFamily() const
return QString::fromLatin1("helvetica");
}
+extern QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style,
+ QFont::StyleHint styleHint, QChar::Script script);
+
/*!
\fn QString QFont::defaultFamily() const
@@ -2120,8 +2123,7 @@ QString QFont::lastResortFamily() const
*/
QString QFont::defaultFamily() const
{
- QPlatformFontDatabase *fontDB = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
- const QStringList fallbacks = fontDB->fallbacksForFamily(QString(), QFont::StyleNormal
+ const QStringList fallbacks = qt_fallbacksForFamily(QString(), QFont::StyleNormal
, QFont::StyleHint(d->request.styleHint), QChar::Script_Common);
if (!fallbacks.isEmpty())
return fallbacks.first();
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index 8916705c0e..2f8af2315d 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -47,6 +47,7 @@
#include <qpa/qplatformfontdatabase.h>
#include <qpa/qplatformtheme.h>
+#include <QtCore/qcache.h>
#include <QtCore/qmath.h>
#include <stdlib.h>
@@ -413,11 +414,45 @@ void QtFontFamily::ensurePopulated()
Q_ASSERT_X(populated, Q_FUNC_INFO, qPrintable(name));
}
+
+struct FallbacksCacheKey {
+ QString family;
+ QFont::Style style;
+ QFont::StyleHint styleHint;
+ QChar::Script script;
+};
+
+inline bool operator==(const FallbacksCacheKey &lhs, const FallbacksCacheKey &rhs) Q_DECL_NOTHROW
+{
+ return lhs.script == rhs.script &&
+ lhs.styleHint == rhs.styleHint &&
+ lhs.style == rhs.style &&
+ lhs.family == rhs.family;
+}
+
+inline bool operator!=(const FallbacksCacheKey &lhs, const FallbacksCacheKey &rhs) Q_DECL_NOTHROW
+{
+ return !operator==(lhs, rhs);
+}
+
+inline uint qHash(const FallbacksCacheKey &key, uint seed = 0) Q_DECL_NOTHROW
+{
+ QtPrivate::QHashCombine hash;
+ seed = hash(seed, key.family);
+ seed = hash(seed, int(key.style));
+ seed = hash(seed, int(key.styleHint));
+ seed = hash(seed, int(key.script));
+ return seed;
+}
+
+
class QFontDatabasePrivate
{
public:
QFontDatabasePrivate()
- : count(0), families(0), reregisterAppFonts(false)
+ : count(0), families(0),
+ fallbacksCache(64),
+ reregisterAppFonts(false)
{ }
~QFontDatabasePrivate() {
@@ -443,6 +478,7 @@ public:
int count;
QtFontFamily **families;
+ QCache<FallbacksCacheKey, QStringList> fallbacksCache;
struct ApplicationFont {
@@ -461,6 +497,8 @@ public:
void QFontDatabasePrivate::invalidate()
{
QFontCache::instance()->clear();
+
+ fallbacksCache.clear();
free();
QGuiApplicationPrivate::platformIntegration()->fontDatabase()->invalidate();
emit static_cast<QGuiApplication *>(QCoreApplication::instance())->fontDatabaseChanged();
@@ -680,8 +718,10 @@ Q_GLOBAL_STATIC_WITH_ARGS(QMutex, fontDatabaseMutex, (QMutex::Recursive))
void qt_cleanupFontDatabase()
{
QFontDatabasePrivate *db = privateDb();
- if (db)
+ if (db) {
+ db->fallbacksCache.clear();
db->free();
+ }
}
// used in qfontengine_x11.cpp
@@ -800,9 +840,15 @@ QStringList QPlatformFontDatabase::fallbacksForFamily(const QString &family, QFo
QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script)
{
+ QFontDatabasePrivate *db = privateDb();
+
+ const FallbacksCacheKey cacheKey = { family, style, styleHint, script };
+
+ if (const QStringList *fallbacks = db->fallbacksCache.object(cacheKey))
+ return *fallbacks;
+
// make sure that the db has all fallback families
QStringList retList = QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script);
- QFontDatabasePrivate *db = privateDb();
QStringList::iterator i;
for (i = retList.begin(); i != retList.end(); ++i) {
@@ -818,6 +864,9 @@ QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFo
--i;
}
}
+
+ db->fallbacksCache.insert(cacheKey, new QStringList(retList));
+
return retList;
}
diff --git a/src/network/kernel/qdnslookup.cpp b/src/network/kernel/qdnslookup.cpp
index 150beb4d39..4a275f0700 100644
--- a/src/network/kernel/qdnslookup.cpp
+++ b/src/network/kernel/qdnslookup.cpp
@@ -148,6 +148,9 @@ static void qt_qdnsservicerecord_sort(QList<QDnsServiceRecord> &records)
}
}
+const char *QDnsLookupPrivate::msgNoIpV6NameServerAdresses =
+ QT_TRANSLATE_NOOP("QDnsLookupRunnable", "IPv6 addresses for nameservers are currently not supported");
+
/*!
\class QDnsLookup
\brief The QDnsLookup class represents a DNS lookup.
diff --git a/src/network/kernel/qdnslookup_p.h b/src/network/kernel/qdnslookup_p.h
index 0ac37f6636..3c8c4d5824 100644
--- a/src/network/kernel/qdnslookup_p.h
+++ b/src/network/kernel/qdnslookup_p.h
@@ -89,6 +89,8 @@ public:
void _q_lookupFinished(const QDnsLookupReply &reply);
+ static const char *msgNoIpV6NameServerAdresses;
+
bool isFinished;
QString name;
QDnsLookup::Type type;
diff --git a/src/network/kernel/qdnslookup_unix.cpp b/src/network/kernel/qdnslookup_unix.cpp
index cb8129efc5..b78db338ce 100644
--- a/src/network/kernel/qdnslookup_unix.cpp
+++ b/src/network/kernel/qdnslookup_unix.cpp
@@ -168,9 +168,9 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN
ns->sin6_addr.s6_addr[i] = ipv6Address[i];
}
#else
- qWarning("IPv6 addresses for nameservers is currently not supported");
+ qWarning("%s", QDnsLookupPrivate::msgNoIpV6NameServerAdresses);
reply->error = QDnsLookup::ResolverError;
- reply->errorString = tr("IPv6 addresses for nameservers is currently not supported");
+ reply->errorString = tr(QDnsLookupPrivate::msgNoIpV6NameServerAdresses);
return;
#endif
}
diff --git a/src/network/kernel/qdnslookup_win.cpp b/src/network/kernel/qdnslookup_win.cpp
index 4a6c631983..df0203bebb 100644
--- a/src/network/kernel/qdnslookup_win.cpp
+++ b/src/network/kernel/qdnslookup_win.cpp
@@ -60,9 +60,9 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN
// For supoprting IPv6 nameserver addresses, we'll need to switch
// from DnsQuey() to DnsQueryEx() as it supports passing an IPv6
// address in the nameserver list
- qWarning("IPv6 addresses for nameservers are currently not supported");
+ qWarning("%s", QDnsLookupPrivate::msgNoIpV6NameServerAdresses);
reply->error = QDnsLookup::ResolverError;
- reply->errorString = tr("IPv6 addresses for nameservers are currently not supported");
+ reply->errorString = tr(QDnsLookupPrivate::msgNoIpV6NameServerAdresses);
return;
}
}
diff --git a/src/network/kernel/qnetworkinterface_unix.cpp b/src/network/kernel/qnetworkinterface_unix.cpp
index dca9aa2c93..e7b62effcb 100644
--- a/src/network/kernel/qnetworkinterface_unix.cpp
+++ b/src/network/kernel/qnetworkinterface_unix.cpp
@@ -360,10 +360,15 @@ static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
{
QList<QNetworkInterfacePrivate *> interfaces;
QSet<QString> seenInterfaces;
-
- // on Linux, AF_PACKET addresses carry the hardware address and interface index;
- // scan for them first (they're usually first, but we have no guarantee this
- // will be the case forever)
+ QVarLengthArray<int, 16> seenIndexes; // faster than QSet<int>
+
+ // On Linux, glibc, uClibc and MUSL obtain the address listing via two
+ // netlink calls: first an RTM_GETLINK to obtain the interface listing,
+ // then one RTM_GETADDR to get all the addresses (uClibc implementation is
+ // copied from glibc; Bionic currently doesn't support getifaddrs). They
+ // synthesize AF_PACKET addresses from the RTM_GETLINK responses, which
+ // means by construction they currently show up first in the interface
+ // listing.
for (ifaddrs *ptr = rawList; ptr; ptr = ptr->ifa_next) {
if (ptr->ifa_addr && ptr->ifa_addr->sa_family == AF_PACKET) {
sockaddr_ll *sll = (sockaddr_ll *)ptr->ifa_addr;
@@ -374,23 +379,30 @@ static QList<QNetworkInterfacePrivate *> createInterfaces(ifaddrs *rawList)
iface->flags = convertFlags(ptr->ifa_flags);
iface->hardwareAddress = iface->makeHwAddress(sll->sll_halen, (uchar*)sll->sll_addr);
+ Q_ASSERT(!seenIndexes.contains(iface->index));
+ seenIndexes.append(iface->index);
seenInterfaces.insert(iface->name);
}
}
// see if we missed anything:
- // virtual interfaces with no HW address have no AF_PACKET
+ // - virtual interfaces with no HW address have no AF_PACKET
+ // - interface labels have no AF_PACKET, but shouldn't be shown as a new interface
for (ifaddrs *ptr = rawList; ptr; ptr = ptr->ifa_next) {
if (ptr->ifa_addr && ptr->ifa_addr->sa_family != AF_PACKET) {
QString name = QString::fromLatin1(ptr->ifa_name);
if (seenInterfaces.contains(name))
continue;
+ int ifindex = if_nametoindex(ptr->ifa_name);
+ if (seenIndexes.contains(ifindex))
+ continue;
+
QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate;
interfaces << iface;
iface->name = name;
iface->flags = convertFlags(ptr->ifa_flags);
- iface->index = if_nametoindex(ptr->ifa_name);
+ iface->index = ifindex;
}
}
@@ -469,7 +481,7 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
interfaces = createInterfaces(interfaceListing);
for (ifaddrs *ptr = interfaceListing; ptr; ptr = ptr->ifa_next) {
- // Get the interface index
+ // Find the interface
QString name = QString::fromLatin1(ptr->ifa_name);
QNetworkInterfacePrivate *iface = 0;
QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin();
@@ -479,6 +491,18 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
iface = *if_it;
break;
}
+
+ if (!iface) {
+ // it may be an interface label, search by interface index
+ int ifindex = if_nametoindex(ptr->ifa_name);
+ for (if_it = interfaces.begin(); if_it != interfaces.end(); ++if_it)
+ if ((*if_it)->index == ifindex) {
+ // found this interface already
+ iface = *if_it;
+ break;
+ }
+ }
+
if (!iface) {
// skip all non-IP interfaces
continue;
diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h
index 912b7db973..c48b0e85d9 100644
--- a/src/network/socket/qnativesocketengine_winrt_p.h
+++ b/src/network/socket/qnativesocketengine_winrt_p.h
@@ -96,7 +96,7 @@ public:
qint64 read(char *data, qint64 maxlen);
qint64 write(const char *data, qint64 len);
- qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader *, PacketHeaderOptions);
+ qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader * = 0, PacketHeaderOptions = WantNone);
qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &header);
bool hasPendingDatagrams() const;
qint64 pendingDatagramSize() const;
diff --git a/src/platformheaders/windowsfunctions/qwindowswindowfunctions.h b/src/platformheaders/windowsfunctions/qwindowswindowfunctions.h
index 4c6d01cc52..720f7f31be 100644
--- a/src/platformheaders/windowsfunctions/qwindowswindowfunctions.h
+++ b/src/platformheaders/windowsfunctions/qwindowswindowfunctions.h
@@ -60,6 +60,15 @@ public:
if (func)
func(window, type);
}
+
+ typedef void (*SetHasBorderInFullScreen)(QWindow *window, bool border);
+ static const QByteArray setHasBorderInFullScreenIdentifier() { return QByteArrayLiteral("WindowsSetHasBorderInFullScreen"); }
+ static void setHasBorderInFullScreen(QWindow *window, bool border)
+ {
+ SetHasBorderInFullScreen func = reinterpret_cast<SetHasBorderInFullScreen>(QGuiApplication::platformFunction(setHasBorderInFullScreenIdentifier()));
+ if (func)
+ func(window, border);
+ }
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QWindowsWindowFunctions::TouchWindowTouchTypes)
diff --git a/src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc b/src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc
index 84fae2f56d..d6b8764e7b 100644
--- a/src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc
+++ b/src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc
@@ -69,3 +69,29 @@
This is a convenience function that can be used directly instead of resolving the function pointer.
\a window and \a type will be relayed to the function retrieved by QGuiApplication
*/
+
+/*!
+ \typedef QWindowsWindowFunctions::SetHasBorderInFullScreen
+
+ This is the typedef for the function returned by QGuiApplication::platformFunction when passed setHasBorderInFullScreenIdentifier.
+*/
+
+/*!
+ \fn QByteArray QWindowsWindowFunctions::setHasBorderInFullScreenIdentifier()
+ \since 5.6
+
+ This function returns the bytearray that can be used to query
+ QGuiApplication::platformFunction to retrieve the SetHasBorderInFullScreen function.
+*/
+
+/*!
+ \fn void QWindowsWindowFunctions::setHasBorderInFullScreen(QWindow *window, bool border)
+ \since 5.6
+
+ This is a convenience function that can be used directly instead of resolving the function pointer.
+ \a window and \a border will be relayed to the function retrieved by QGuiApplication. When \a border
+ is true then it will enable the WS_BORDER flag in full screen mode to enable other top level windows
+ inside the application to appear on top when required.
+
+ See also \l [QtDoc] {Fullscreen OpenGL Based Windows}
+*/
diff --git a/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp b/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp
index 6f71fb637f..fee3146f04 100644
--- a/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp
+++ b/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp
@@ -35,6 +35,7 @@
#include <QtGui/QWindow>
#include <QtGui/QPainter>
#include <qpa/qplatformbackingstore.h>
+#include <private/qwindow_p.h>
#include "qopenglcompositorbackingstore_p.h"
#include "qopenglcompositor_p.h"
@@ -198,6 +199,8 @@ void QOpenGLCompositorBackingStore::composeAndFlush(QWindow *window, const QRegi
dstCtx->makeCurrent(dstWin);
+ QWindowPrivate::get(window)->lastComposeTime.start();
+
m_textures->clear();
for (int i = 0; i < textures->count(); ++i)
m_textures->appendTexture(textures->source(i), textures->textureId(i), textures->geometry(i),
diff --git a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp
index ad9877eb25..4126456f90 100644
--- a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp
+++ b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp
@@ -263,11 +263,11 @@ QString TableGenerator::findComposeFile()
{
// check if XCOMPOSEFILE points to a Compose file
if (qEnvironmentVariableIsSet("XCOMPOSEFILE")) {
- QString path(qgetenv("XCOMPOSEFILE"));
- if (path.endsWith(QLatin1String("Compose")))
+ const QString path = QFile::decodeName(qgetenv("XCOMPOSEFILE"));
+ if (QFile::exists(path))
return path;
else
- qWarning("Qt Warning: XCOMPOSEFILE doesn't point to a valid Compose file");
+ qWarning("$XCOMPOSEFILE doesn't point to an existing file");
}
// check if user’s home directory has a file named .XCompose
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp
index 2bc3b0dc7d..7045533fca 100644
--- a/src/plugins/platforms/android/androidjnimain.cpp
+++ b/src/plugins/platforms/android/androidjnimain.cpp
@@ -34,6 +34,7 @@
#include <dlfcn.h>
#include <pthread.h>
+#include <semaphore.h>
#include <qplugin.h>
#include <qdebug.h>
@@ -91,6 +92,8 @@ extern "C" typedef int (*Main)(int, char **); //use the standard main method to
static Main m_main = nullptr;
static void *m_mainLibraryHnd = nullptr;
static QList<QByteArray> m_applicationParams;
+pthread_t m_qtAppThread = 0;
+static sem_t m_exitSemaphore, m_terminateSemaphore;
struct SurfaceData
{
@@ -454,6 +457,10 @@ static void *startMainMethod(void */*data*/)
if (vm != 0)
vm->DetachCurrentThread();
+ sem_post(&m_terminateSemaphore);
+ sem_wait(&m_exitSemaphore);
+ sem_destroy(&m_exitSemaphore);
+
// We must call exit() to ensure that all global objects will be destructed
exit(ret);
return 0;
@@ -503,8 +510,13 @@ static jboolean startQtApplication(JNIEnv *env, jobject /*object*/, jstring para
return false;
}
- pthread_t appThread;
- return pthread_create(&appThread, nullptr, startMainMethod, nullptr) == 0;
+ if (sem_init(&m_exitSemaphore, 0, 0) == -1)
+ return false;
+
+ if (sem_init(&m_terminateSemaphore, 0, 0) == -1)
+ return false;
+
+ return pthread_create(&m_qtAppThread, nullptr, startMainMethod, nullptr) == 0;
}
@@ -518,6 +530,8 @@ static void quitQtAndroidPlugin(JNIEnv *env, jclass /*clazz*/)
static void terminateQt(JNIEnv *env, jclass /*clazz*/)
{
+ sem_wait(&m_terminateSemaphore);
+ sem_destroy(&m_terminateSemaphore);
env->DeleteGlobalRef(m_applicationClass);
env->DeleteGlobalRef(m_classLoaderObject);
if (m_resourcesObj)
@@ -535,6 +549,8 @@ static void terminateQt(JNIEnv *env, jclass /*clazz*/)
m_androidPlatformIntegration = nullptr;
delete m_androidAssetsFileEngineHandler;
m_androidAssetsFileEngineHandler = nullptr;
+ sem_post(&m_exitSemaphore);
+ pthread_join(m_qtAppThread, nullptr);
}
static void setSurface(JNIEnv *env, jobject /*thiz*/, jint id, jobject jSurface, jint w, jint h)
diff --git a/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp b/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp
index 835ca8a10a..a21aac51b4 100644
--- a/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp
+++ b/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp
@@ -74,7 +74,7 @@ QStringList QAndroidPlatformFontDatabase::fallbacksForFamily(const QString &fami
result.append(QString(qgetenv("QT_ANDROID_FONTS_SERIF")).split(QLatin1Char(';')));
else
result.append(QString(qgetenv("QT_ANDROID_FONTS")).split(QLatin1Char(';')));
- result.append(QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script));
+ result.append(QBasicFontDatabase::fallbacksForFamily(family, style, styleHint, script));
return result;
}
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 18abaddfd7..2d8abba189 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -502,7 +502,11 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect)
QMacAutoReleasePool pool;
if (m_contentViewIsEmbedded) {
- QPlatformWindow::setGeometry(rect);
+ if (m_qtView) {
+ [m_qtView setFrame:NSMakeRect(0, 0, rect.width(), rect.height())];
+ } else {
+ QPlatformWindow::setGeometry(rect);
+ }
return;
}
diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm
index fe0ca33c13..8bdb4bcdb3 100644
--- a/src/plugins/platforms/ios/qioscontext.mm
+++ b/src/plugins/platforms/ios/qioscontext.mm
@@ -45,12 +45,15 @@
QIOSContext::QIOSContext(QOpenGLContext *context)
: QPlatformOpenGLContext()
, m_sharedContext(static_cast<QIOSContext *>(context->shareHandle()))
+ , m_eaglContext(0)
, m_format(context->format())
{
m_format.setRenderableType(QSurfaceFormat::OpenGLES);
- m_eaglContext = [[EAGLContext alloc]
- initWithAPI:EAGLRenderingAPI(m_format.majorVersion())
- sharegroup:m_sharedContext ? [m_sharedContext->m_eaglContext sharegroup] : nil];
+
+ EAGLSharegroup *shareGroup = m_sharedContext ? [m_sharedContext->m_eaglContext sharegroup] : nil;
+ const int preferredVersion = m_format.majorVersion() == 1 ? kEAGLRenderingAPIOpenGLES1 : kEAGLRenderingAPIOpenGLES3;
+ for (int version = preferredVersion; !m_eaglContext && version >= m_format.majorVersion(); --version)
+ m_eaglContext = [[EAGLContext alloc] initWithAPI:EAGLRenderingAPI(version) sharegroup:shareGroup];
if (m_eaglContext != nil) {
EAGLContext *originalContext = [EAGLContext currentContext];
diff --git a/src/plugins/platforms/ios/qiosmenu.mm b/src/plugins/platforms/ios/qiosmenu.mm
index f68321fb3b..5f9346816a 100644
--- a/src/plugins/platforms/ios/qiosmenu.mm
+++ b/src/plugins/platforms/ios/qiosmenu.mm
@@ -62,11 +62,23 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_";
{
if (self = [super init]) {
[self setVisibleMenuItems:visibleMenuItems];
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(menuClosed)
+ name:UIMenuControllerDidHideMenuNotification object:nil];
}
return self;
}
+-(void)dealloc
+{
+ [[NSNotificationCenter defaultCenter]
+ removeObserver:self
+ name:UIMenuControllerDidHideMenuNotification object:nil];
+ [super dealloc];
+}
+
- (void)setVisibleMenuItems:(const QIOSMenuItemList &)visibleMenuItems
{
m_visibleMenuItems = visibleMenuItems;
@@ -86,6 +98,11 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_";
[[UIMenuController sharedMenuController] setMenuVisible:YES animated:NO];
}
+-(void)menuClosed
+{
+ QIOSMenu::currentMenu()->dismiss();
+}
+
- (id)targetForAction:(SEL)action withSender:(id)sender
{
Q_UNUSED(sender);
diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm
index 9ca5e22b90..320b1cac61 100644
--- a/src/plugins/platforms/ios/qiostextresponder.mm
+++ b/src/plugins/platforms/ios/qiostextresponder.mm
@@ -318,7 +318,11 @@
// a regular responder transfer to another window. In the former case, iOS
// will set the new first-responder to our next-responder, and in the latter
// case we'll have an active responder candidate.
- if ([UIResponder currentFirstResponder] == [self nextResponder]) {
+ if (![UIResponder currentFirstResponder]) {
+ // No first responder set anymore, sync this with Qt by clearing the
+ // focus object.
+ m_inputContext->clearCurrentFocusObject();
+ } else if ([UIResponder currentFirstResponder] == [self nextResponder]) {
// We have resigned the keyboard, and transferred first responder back to the parent view
Q_ASSERT(!FirstResponderCandidate::currentCandidate());
if ([self currentImeState:Qt::ImEnabled].toBool()) {
@@ -364,6 +368,32 @@
[self sendKeyPressRelease:key modifiers:modifiers];
}
+- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
+{
+ bool isEditAction = (action == @selector(cut:)
+ || action == @selector(copy:)
+ || action == @selector(paste:)
+ || action == @selector(delete:)
+ || action == @selector(toggleBoldface:)
+ || action == @selector(toggleItalics:)
+ || action == @selector(toggleUnderline:)
+ || action == @selector(undo)
+ || action == @selector(redo));
+
+ bool isSelectAction = (action == @selector(select:)
+ || action == @selector(selectAll:)
+ || action == @selector(paste:)
+ || action == @selector(undo)
+ || action == @selector(redo));
+
+ const bool unknownAction = !isEditAction && !isSelectAction;
+ const bool hasSelection = ![self selectedTextRange].empty;
+
+ if (unknownAction)
+ return [super canPerformAction:action withSender:sender];
+ return (hasSelection && isEditAction) || (!hasSelection && isSelectAction);
+}
+
- (void)cut:(id)sender
{
Q_UNUSED(sender);
@@ -382,6 +412,13 @@
[self sendShortcut:QKeySequence::Paste];
}
+- (void)select:(id)sender
+{
+ Q_UNUSED(sender);
+ [self sendShortcut:QKeySequence::MoveToPreviousWord];
+ [self sendShortcut:QKeySequence::SelectNextWord];
+}
+
- (void)selectAll:(id)sender
{
Q_UNUSED(sender);
@@ -580,7 +617,8 @@
- (UITextPosition *)endOfDocument
{
- int endPosition = [self currentImeState:Qt::ImSurroundingText].toString().length();
+ QString surroundingText = [self currentImeState:Qt::ImSurroundingText].toString();
+ int endPosition = surroundingText.length() + m_markedText.length();
return [QUITextPosition positionWithIndex:endPosition];
}
@@ -611,9 +649,18 @@
- (NSString *)textInRange:(UITextRange *)range
{
+ QString text = [self currentImeState:Qt::ImSurroundingText].toString();
+ if (!m_markedText.isEmpty()) {
+ // [UITextInput textInRange] is sparsely documented, but it turns out that unconfirmed
+ // marked text should be seen as a part of the text document. This is different from
+ // ImSurroundingText, which excludes it.
+ int cursorPos = [self currentImeState:Qt::ImCursorPosition].toInt();
+ text = text.left(cursorPos) + m_markedText + text.mid(cursorPos);
+ }
+
int s = static_cast<QUITextPosition *>([range start]).index;
int e = static_cast<QUITextPosition *>([range end]).index;
- return [self currentImeState:Qt::ImSurroundingText].toString().mid(s, e - s).toNSString();
+ return text.mid(s, e - s).toNSString();
}
- (void)setMarkedText:(NSString *)markedText selectedRange:(NSRange)selectedRange
@@ -882,6 +929,14 @@
if ([text isEqualToString:@"\n"]) {
[self sendKeyPressRelease:Qt::Key_Return modifiers:Qt::NoModifier];
+ // An onEnter handler of a TextInput might move to the next input by calling
+ // nextInput.forceActiveFocus() which changes the focusObject.
+ // In that case we don't want to hide the VKB.
+ if (focusObject != QGuiApplication::focusObject()) {
+ qImDebug() << "focusObject already changed, not resigning first responder.";
+ return;
+ }
+
if (self.returnKeyType == UIReturnKeyDone || self.returnKeyType == UIReturnKeyGo
|| self.returnKeyType == UIReturnKeySend || self.returnKeyType == UIReturnKeySearch)
[self resignFirstResponder];
diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp
index bd5c35037d..135c9eb601 100644
--- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp
+++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp
@@ -96,7 +96,12 @@ void QWindowsBackingStore::flush(QWindow *window, const QRegion &region,
RECT dirty = {dirtyRect.x(), dirtyRect.y(),
dirtyRect.x() + dirtyRect.width(), dirtyRect.y() + dirtyRect.height()};
UPDATELAYEREDWINDOWINFO info = {sizeof(info), NULL, &ptDst, &size, m_image->hdc(), &ptSrc, 0, &blend, ULW_ALPHA, &dirty};
- QWindowsContext::user32dll.updateLayeredWindowIndirect(rw->handle(), &info);
+ const BOOL result = QWindowsContext::user32dll.updateLayeredWindowIndirect(rw->handle(), &info);
+ if (!result)
+ qErrnoWarning("UpdateLayeredWindowIndirect failed for ptDst=(%d, %d),"
+ " size=(%dx%d), dirty=(%dx%d %d, %d)", r.x(), r.y(),
+ r.width(), r.height(), dirtyRect.width(), dirtyRect.height(),
+ dirtyRect.x(), dirtyRect.y());
} else {
QWindowsContext::user32dll.updateLayeredWindow(rw->handle(), NULL, &ptDst, &size, m_image->hdc(), &ptSrc, 0, &blend, ULW_ALPHA);
}
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
index 361e7f4445..183c198806 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
@@ -192,7 +192,14 @@ typedef struct {
quint16 stringOffset;
} NAME_RECORD;
-static QString fontNameFromTTFile(const QString &filename)
+typedef struct {
+ quint32 tag;
+ quint16 majorVersion;
+ quint16 minorVersion;
+ quint32 numFonts;
+} TTC_TABLE_HEADER;
+
+static QString fontNameFromTTFile(const QString &filename, int startPos = 0)
{
QFile f(filename);
QString retVal;
@@ -200,6 +207,7 @@ static QString fontNameFromTTFile(const QString &filename)
qint64 bytesToRead;
if (f.open(QIODevice::ReadOnly)) {
+ f.seek(startPos);
OFFSET_TABLE ttOffsetTable;
bytesToRead = sizeof(OFFSET_TABLE);
bytesRead = f.read((char*)&ttOffsetTable, bytesToRead);
@@ -280,6 +288,37 @@ static QString fontNameFromTTFile(const QString &filename)
return retVal;
}
+static QStringList fontNamesFromTTCFile(const QString &filename)
+{
+ QFile f(filename);
+ QStringList retVal;
+ qint64 bytesRead;
+ qint64 bytesToRead;
+
+ if (f.open(QIODevice::ReadOnly)) {
+ TTC_TABLE_HEADER ttcTableHeader;
+ bytesToRead = sizeof(TTC_TABLE_HEADER);
+ bytesRead = f.read((char*)&ttcTableHeader, bytesToRead);
+ if (bytesToRead != bytesRead)
+ return retVal;
+ ttcTableHeader.majorVersion = qFromBigEndian(ttcTableHeader.majorVersion);
+ ttcTableHeader.minorVersion = qFromBigEndian(ttcTableHeader.minorVersion);
+ ttcTableHeader.numFonts = qFromBigEndian(ttcTableHeader.numFonts);
+
+ if (ttcTableHeader.majorVersion < 1 || ttcTableHeader.majorVersion > 2)
+ return retVal;
+ QVarLengthArray<quint32> offsetTable(ttcTableHeader.numFonts);
+ bytesToRead = sizeof(offsetTable) * ttcTableHeader.numFonts;
+ bytesRead = f.read((char*)offsetTable.data(), bytesToRead);
+ if (bytesToRead != bytesRead)
+ return retVal;
+ f.close();
+ for (int i = 0; i < (int)ttcTableHeader.numFonts; ++i)
+ retVal << fontNameFromTTFile(filename, qFromBigEndian(offsetTable[i]));
+ }
+ return retVal;
+}
+
static inline QString fontSettingsOrganization() { return QStringLiteral("Qt-Project"); }
static inline QString fontSettingsApplication() { return QStringLiteral("Qtbase"); }
static inline QString fontSettingsGroup() { return QStringLiteral("CEFontCache"); }
@@ -306,20 +345,28 @@ static QString findFontFile(const QString &faceName)
//empty the cache first, as it seems that it is dirty
settings.remove(QString());
- QDirIterator it(QStringLiteral("/Windows"), QStringList(QStringLiteral("*.ttf")), QDir::Files | QDir::Hidden | QDir::System);
-
+ QDirIterator it(QStringLiteral("/Windows"), QStringList() << QStringLiteral("*.ttf") << QStringLiteral("*.ttc"), QDir::Files | QDir::Hidden | QDir::System);
+ const QLatin1Char lowerF('f');
+ const QLatin1Char upperF('F');
while (it.hasNext()) {
const QString fontFile = it.next();
- const QString fontName = fontNameFromTTFile(fontFile);
- if (fontName.isEmpty())
- continue;
- fontCache.insert(fontName, fontFile);
- settings.setValue(fontName, fontFile);
-
- if (localizedName(fontName)) {
- QString englishFontName = getEnglishName(fontName);
- fontCache.insert(englishFontName, fontFile);
- settings.setValue(englishFontName, fontFile);
+ QStringList fontNames;
+ const QChar c = fontFile[fontFile.size() - 1];
+ if (c == lowerF || c == upperF)
+ fontNames << fontNameFromTTFile(fontFile);
+ else
+ fontNames << fontNamesFromTTCFile(fontFile);
+ foreach (const QString fontName, fontNames) {
+ if (fontName.isEmpty())
+ continue;
+ fontCache.insert(fontName, fontFile);
+ settings.setValue(fontName, fontFile);
+
+ if (localizedName(fontName)) {
+ QString englishFontName = getEnglishName(fontName);
+ fontCache.insert(englishFontName, fontFile);
+ settings.setValue(englishFontName, fontFile);
+ }
}
}
settings.endGroup();
@@ -675,7 +722,7 @@ QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString &family, QF
result.append(QWindowsFontDatabase::extraTryFontsForFamily(family));
- result.append(QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script));
+ result.append(QBasicFontDatabase::fallbacksForFamily(family, style, styleHint, script));
qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint
<< script << result;
diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp
index 593ac7d810..5e2e9f6454 100644
--- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp
@@ -485,9 +485,9 @@ qreal QWindowsFontEngineDirectWrite::maxCharWidth() const
return 0;
}
-QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition)
+QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t)
{
- QImage im = imageForGlyph(glyph, subPixelPosition, 0, QTransform());
+ QImage im = alphaRGBMapForGlyph(glyph, subPixelPosition, t);
QImage alphaMap(im.width(), im.height(), QImage::Format_Alpha8);
@@ -504,6 +504,11 @@ QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed sub
return alphaMap;
}
+QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition)
+{
+ return alphaMapForGlyph(glyph, subPixelPosition, QTransform());
+}
+
bool QWindowsFontEngineDirectWrite::supportsSubPixelPositions() const
{
return true;
@@ -709,9 +714,9 @@ QString QWindowsFontEngineDirectWrite::fontNameSubstitute(const QString &familyN
glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph, QFixed pos, const QTransform &matrix, GlyphFormat format)
{
Q_UNUSED(pos);
- int margin = 0;
- if (format == QFontEngine::Format_A32 || format == QFontEngine::Format_ARGB)
- margin = glyphMargin(QFontEngine::Format_A32);
+ Q_UNUSED(format);
+
+ int margin = glyphMargin(QFontEngine::Format_A32);
glyph_metrics_t gm = QFontEngine::boundingBox(glyph, matrix);
gm.width += margin * 2;
gm.height += margin * 2;
diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
index da772469e9..cee8691d69 100644
--- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
+++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
@@ -86,6 +86,7 @@ public:
bool supportsSubPixelPositions() const;
QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition);
+ QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t);
QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform);
QFontEngine *cloneWithSize(qreal pixelSize) const;
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index 4c0b94e6e7..c5dff60114 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -86,10 +86,15 @@ QT_BEGIN_NAMESPACE
The code originates from \c qkeymapper_win.cpp.
*/
+static void clearKeyRecorderOnApplicationInActive(Qt::ApplicationState state);
+
QWindowsKeyMapper::QWindowsKeyMapper()
: m_useRTLExtensions(false), m_keyGrabber(0)
{
memset(keyLayout, 0, sizeof(keyLayout));
+ QGuiApplication *app = static_cast<QGuiApplication *>(QGuiApplication::instance());
+ QObject::connect(app, &QGuiApplication::applicationStateChanged,
+ app, clearKeyRecorderOnApplicationInActive);
}
QWindowsKeyMapper::~QWindowsKeyMapper()
@@ -144,6 +149,12 @@ struct KeyRecorder
};
static KeyRecorder key_recorder;
+static void clearKeyRecorderOnApplicationInActive(Qt::ApplicationState state)
+{
+ if (state == Qt::ApplicationInactive)
+ key_recorder.clearKeys();
+}
+
KeyRecord *KeyRecorder::findKey(int code, bool remove)
{
KeyRecord *result = 0;
diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
index 5b0f6f637e..c5c60aa882 100644
--- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
+++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
@@ -245,6 +245,8 @@ QFunctionPointer QWindowsNativeInterface::platformFunction(const QByteArray &fun
{
if (function == QWindowsWindowFunctions::setTouchWindowTouchTypeIdentifier())
return QFunctionPointer(QWindowsWindow::setTouchWindowTouchTypeStatic);
+ else if (function == QWindowsWindowFunctions::setHasBorderInFullScreenIdentifier())
+ return QFunctionPointer(QWindowsWindow::setHasBorderInFullScreenStatic);
return Q_NULLPTR;
}
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 611d586b19..cac8ec5ecc 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -1720,7 +1720,7 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
if (!m_savedStyle) {
m_savedStyle = style();
#ifndef Q_OS_WINCE
- if (oldState == Qt::WindowMinimized) {
+ if (oldState == Qt::WindowMinimized || oldState == Qt::WindowMaximized) {
const QRect nf = normalFrameGeometry(m_data.hwnd);
if (nf.isValid())
m_savedFrameGeometry = nf;
@@ -1735,6 +1735,8 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
newStyle |= WS_SYSMENU;
if (visible)
newStyle |= WS_VISIBLE;
+ if (testFlag(HasBorderInFullScreen))
+ newStyle |= WS_BORDER;
setStyle(newStyle);
// Use geometry of QWindow::screen() within creation or the virtual screen the
// window is in (QTBUG-31166, QTBUG-30724).
@@ -1769,7 +1771,7 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
// preserve maximized state
if (visible) {
setFlag(WithinMaximize);
- ShowWindow(m_data.hwnd, (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE);
+ ShowWindow(m_data.hwnd, (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNA);
clearFlag(WithinMaximize);
}
m_savedStyle = 0;
@@ -2371,4 +2373,19 @@ void QWindowsWindow::aboutToMakeCurrent()
#endif
}
+void QWindowsWindow::setHasBorderInFullScreenStatic(QWindow *window, bool border)
+{
+ if (!window->handle())
+ return;
+ static_cast<QWindowsWindow *>(window->handle())->setHasBorderInFullScreen(border);
+}
+
+void QWindowsWindow::setHasBorderInFullScreen(bool border)
+{
+ if (border)
+ setFlag(HasBorderInFullScreen);
+ else
+ clearFlag(HasBorderInFullScreen);
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index 4172a3d850..710cab8597 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -137,7 +137,8 @@ public:
WithinMaximize = 0x40000,
MaximizeToFullScreen = 0x80000,
InputMethodDisabled = 0x100000,
- Compositing = 0x200000
+ Compositing = 0x200000,
+ HasBorderInFullScreen = 0x400000
};
QWindowsWindow(QWindow *window, const QWindowsWindowData &data);
@@ -251,7 +252,8 @@ public:
static void setTouchWindowTouchTypeStatic(QWindow *window, QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes);
void registerTouchWindow(QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes = QWindowsWindowFunctions::NormalTouch);
-
+ static void setHasBorderInFullScreenStatic(QWindow *window, bool border);
+ void setHasBorderInFullScreen(bool border);
private:
inline void show_sys() const;
inline void hide_sys() const;
diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp
index c348faf015..793256a83f 100644
--- a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp
+++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp
@@ -428,6 +428,21 @@ QFontEngine *QWinRTFontDatabase::fontEngine(const QFontDef &fontDef, void *handl
return engine;
}
+QStringList QWinRTFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style,
+ QFont::StyleHint styleHint,
+ QChar::Script script) const
+{
+ Q_UNUSED(style)
+ Q_UNUSED(styleHint)
+ Q_UNUSED(script)
+
+ QStringList result;
+ if (family == QLatin1String("Helvetica"))
+ result.append(QStringLiteral("Arial"));
+ result.append(QBasicFontDatabase::fallbacksForFamily(family, style, styleHint, script));
+ return result;
+}
+
void QWinRTFontDatabase::releaseHandle(void *handle)
{
if (!handle)
diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.h b/src/plugins/platforms/winrt/qwinrtfontdatabase.h
index a88092e432..41619f5bd8 100644
--- a/src/plugins/platforms/winrt/qwinrtfontdatabase.h
+++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.h
@@ -60,6 +60,8 @@ public:
void populateFontDatabase() Q_DECL_OVERRIDE;
void populateFamily(const QString &familyName) Q_DECL_OVERRIDE;
QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) Q_DECL_OVERRIDE;
+ QStringList fallbacksForFamily(const QString &family, QFont::Style style,
+ QFont::StyleHint styleHint, QChar::Script script) const Q_DECL_OVERRIDE;
void releaseHandle(void *handle) Q_DECL_OVERRIDE;
private:
QHash<IDWriteFontFile *, FontDescription> m_fonts;
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 1d20432bd4..e28d84cf92 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -179,42 +179,6 @@ QXcbScreen* QXcbConnection::findScreenForOutput(xcb_window_t rootWindow, xcb_ran
return 0;
}
-QXcbScreen* QXcbConnection::createScreen(QXcbVirtualDesktop* virtualDesktop,
- xcb_randr_output_t outputId,
- xcb_randr_get_output_info_reply_t *output)
-{
- QString name;
- if (output)
- name = QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output),
- xcb_randr_get_output_info_name_length(output));
- else {
- QByteArray displayName = m_displayName;
- int dotPos = displayName.lastIndexOf('.');
- if (dotPos != -1)
- displayName.truncate(dotPos);
- name = QString::fromLocal8Bit(displayName) + QLatin1Char('.') + QString::number(virtualDesktop->number());
- }
-
- return new QXcbScreen(this, virtualDesktop, outputId, output, name);
-}
-
-bool QXcbConnection::checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output)
-{
- xcb_generic_error_t *error = 0;
- xcb_randr_get_output_primary_cookie_t primaryCookie =
- xcb_randr_get_output_primary(xcb_connection(), rootWindow);
- QScopedPointer<xcb_randr_get_output_primary_reply_t, QScopedPointerPodDeleter> primary (
- xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error));
- if (!primary || error) {
- qWarning("failed to get the primary output of the screen");
- free(error);
- error = NULL;
- }
- const bool isPrimary = primary ? (primary->output == output) : false;
-
- return isPrimary;
-}
-
QXcbVirtualDesktop* QXcbConnection::virtualDesktopForRootWindow(xcb_window_t rootWindow)
{
foreach (QXcbVirtualDesktop *virtualDesktop, m_virtualDesktops) {
@@ -237,8 +201,9 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
// Not for us
return;
- qCDebug(lcQpaScreen) << "QXcbConnection: XCB_RANDR_NOTIFY_CRTC_CHANGE:" << crtc.crtc;
QXcbScreen *screen = findScreenForCrtc(crtc.window, crtc.crtc);
+ qCDebug(lcQpaScreen) << "QXcbConnection: XCB_RANDR_NOTIFY_CRTC_CHANGE:" << crtc.crtc
+ << "mode" << crtc.mode << "relevant screen" << screen;
// Only update geometry when there's a valid mode on the CRTC
// CRTC with node mode could mean that output has been disabled, and we'll
// get RRNotifyOutputChange notification for that.
@@ -260,16 +225,7 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
if (screen && output.connection == XCB_RANDR_CONNECTION_DISCONNECTED) {
qCDebug(lcQpaScreen) << "screen" << screen->name() << "has been disconnected";
-
- // Known screen removed -> delete it
- m_screens.removeOne(screen);
- virtualDesktop->removeScreen(screen);
-
- QXcbIntegration::instance()->destroyScreen(screen);
-
- // QTBUG-40174, QTBUG-42985: If all screens are removed, wait
- // and start rendering again later if a screen becomes available.
-
+ destroyScreen(screen);
} else if (!screen && output.connection == XCB_RANDR_CONNECTION_CONNECTED) {
// New XRandR output is available and it's enabled
if (output.crtc != XCB_NONE && output.mode != XCB_NONE) {
@@ -278,59 +234,142 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> outputInfo(
xcb_randr_get_output_info_reply(xcb_connection(), outputInfoCookie, NULL));
- screen = createScreen(virtualDesktop, output.output, outputInfo.data());
- qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled";
-
- screen->setPrimary(checkOutputIsPrimary(output.window, output.output));
- virtualDesktop->addScreen(screen);
- m_screens << screen;
- QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
+ // Find a fake screen
+ foreach (QPlatformScreen *scr, virtualDesktop->screens()) {
+ QXcbScreen *xcbScreen = (QXcbScreen *)scr;
+ if (xcbScreen->output() == XCB_NONE) {
+ screen = xcbScreen;
+ break;
+ }
+ }
- // Windows which had null screens have already had expose events by now.
- // They need to be told the screen is back, it's OK to render.
- foreach (QWindow *window, QGuiApplication::topLevelWindows()) {
- QXcbWindow *xcbWin = static_cast<QXcbWindow*>(window->handle());
- if (xcbWin)
- xcbWin->maybeSetScreen(screen);
+ if (screen) {
+ QString nameWas = screen->name();
+ // Transform the fake screen into a physical screen
+ screen->setOutput(output.output, outputInfo.data());
+ updateScreen(screen, output);
+ qCDebug(lcQpaScreen) << "output" << screen->name()
+ << "is connected and enabled; was fake:" << nameWas;
+ } else {
+ screen = createScreen(virtualDesktop, output, outputInfo.data());
+ qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled";
}
}
- // else ignore disabled screens
} else if (screen) {
- // Screen has been disabled -> remove
if (output.crtc == XCB_NONE && output.mode == XCB_NONE) {
+ // Screen has been disabled
xcb_randr_get_output_info_cookie_t outputInfoCookie =
xcb_randr_get_output_info(xcb_connection(), output.output, output.config_timestamp);
QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> outputInfo(
xcb_randr_get_output_info_reply(xcb_connection(), outputInfoCookie, NULL));
if (outputInfo->crtc == XCB_NONE) {
qCDebug(lcQpaScreen) << "output" << screen->name() << "has been disabled";
- m_screens.removeOne(screen);
- virtualDesktop->removeScreen(screen);
- QXcbIntegration::instance()->destroyScreen(screen);
+ destroyScreen(screen);
} else {
qCDebug(lcQpaScreen) << "output" << screen->name() << "has been temporarily disabled for the mode switch";
+ // Reset crtc to skip RRCrtcChangeNotify events,
+ // because they may be invalid in the middle of the mode switch
+ screen->setCrtc(XCB_NONE);
}
} else {
- // Just update existing screen
- screen->updateGeometry(output.config_timestamp);
- const bool wasPrimary = screen->isPrimary();
- screen->setPrimary(checkOutputIsPrimary(output.window, output.output));
- if (screen->mode() != output.mode)
- screen->updateRefreshRate(output.mode);
-
- // If the screen became primary, reshuffle the order in QGuiApplicationPrivate
- if (!wasPrimary && screen->isPrimary()) {
- const int idx = m_screens.indexOf(screen);
- m_screens.swap(0, idx);
- QXcbIntegration::instance()->setPrimaryScreen(screen);
- }
+ updateScreen(screen, output);
qCDebug(lcQpaScreen) << "output has changed" << screen;
}
}
+
+ qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name();
+ }
+}
+
+bool QXcbConnection::checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output)
+{
+ xcb_generic_error_t *error = 0;
+ xcb_randr_get_output_primary_cookie_t primaryCookie =
+ xcb_randr_get_output_primary(xcb_connection(), rootWindow);
+ QScopedPointer<xcb_randr_get_output_primary_reply_t, QScopedPointerPodDeleter> primary (
+ xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error));
+ if (!primary || error) {
+ qWarning("failed to get the primary output of the screen");
+ free(error);
+ error = NULL;
+ }
+ const bool isPrimary = primary ? (primary->output == output) : false;
+
+ return isPrimary;
+}
+
+void QXcbConnection::updateScreen(QXcbScreen *screen, const xcb_randr_output_change_t &outputChange)
+{
+ screen->setCrtc(outputChange.crtc); // Set the new crtc, because it can be invalid
+ screen->updateGeometry(outputChange.config_timestamp);
+ if (screen->mode() != outputChange.mode)
+ screen->updateRefreshRate(outputChange.mode);
+ // Only screen which belongs to the primary virtual desktop can be a primary screen
+ if (screen->screenNumber() == m_primaryScreenNumber) {
+ if (!screen->isPrimary() && checkOutputIsPrimary(outputChange.window, outputChange.output)) {
+ screen->setPrimary(true);
+
+ // If the screen became primary, reshuffle the order in QGuiApplicationPrivate
+ const int idx = m_screens.indexOf(screen);
+ if (idx > 0) {
+ m_screens.first()->setPrimary(false);
+ m_screens.swap(0, idx);
+ }
+ screen->virtualDesktop()->setPrimaryScreen(screen);
+ QXcbIntegration::instance()->setPrimaryScreen(screen);
+ }
+ }
+}
+
+QXcbScreen *QXcbConnection::createScreen(QXcbVirtualDesktop *virtualDesktop,
+ const xcb_randr_output_change_t &outputChange,
+ xcb_randr_get_output_info_reply_t *outputInfo)
+{
+ QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, outputChange.output, outputInfo);
+ // Only screen which belongs to the primary virtual desktop can be a primary screen
+ if (screen->screenNumber() == m_primaryScreenNumber)
+ screen->setPrimary(checkOutputIsPrimary(outputChange.window, outputChange.output));
+
+ if (screen->isPrimary()) {
if (!m_screens.isEmpty())
- qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name();
- else
- qCDebug(lcQpaScreen) << "no outputs";
+ m_screens.first()->setPrimary(false);
+
+ m_screens.prepend(screen);
+ } else {
+ m_screens.append(screen);
+ }
+ virtualDesktop->addScreen(screen);
+ QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
+
+ return screen;
+}
+
+void QXcbConnection::destroyScreen(QXcbScreen *screen)
+{
+ QXcbVirtualDesktop *virtualDesktop = screen->virtualDesktop();
+ if (virtualDesktop->screens().count() == 1) {
+ // If there are no other screens on the same virtual desktop,
+ // then transform the physical screen into a fake screen.
+ const QString nameWas = screen->name();
+ screen->setOutput(XCB_NONE, Q_NULLPTR);
+ qCDebug(lcQpaScreen) << "transformed" << nameWas << "to fake" << screen;
+ } else {
+ // There is more than one screen on the same virtual desktop, remove the screen
+ m_screens.removeOne(screen);
+ virtualDesktop->removeScreen(screen);
+
+ // When primary screen is removed, set the new primary screen
+ // which belongs to the primary virtual desktop.
+ if (screen->isPrimary()) {
+ QXcbScreen *newPrimary = (QXcbScreen *)virtualDesktop->screens().at(0);
+ newPrimary->setPrimary(true);
+ const int idx = m_screens.indexOf(newPrimary);
+ if (idx > 0)
+ m_screens.swap(0, idx);
+ QXcbIntegration::instance()->setPrimaryScreen(newPrimary);
+ }
+
+ QXcbIntegration::instance()->destroyScreen(screen);
}
}
@@ -338,8 +377,7 @@ void QXcbConnection::initializeScreens()
{
xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup);
int xcbScreenNumber = 0; // screen number in the xcb sense
- QXcbScreen* primaryScreen = Q_NULLPTR;
- bool hasOutputs = false;
+ QXcbScreen *primaryScreen = Q_NULLPTR;
while (it.rem) {
// Each "screen" in xcb terminology is a virtual desktop,
// potentially a collection of separate juxtaposed monitors.
@@ -348,8 +386,6 @@ void QXcbConnection::initializeScreens()
xcb_screen_t *xcbScreen = it.data;
QXcbVirtualDesktop *virtualDesktop = new QXcbVirtualDesktop(this, xcbScreen, xcbScreenNumber);
m_virtualDesktops.append(virtualDesktop);
- QList<QPlatformScreen *> siblings;
- int outputCount = 0;
if (has_randr_extension) {
xcb_generic_error_t *error = NULL;
// RRGetScreenResourcesCurrent is fast but it may return nothing if the
@@ -366,7 +402,7 @@ void QXcbConnection::initializeScreens()
} else {
xcb_timestamp_t timestamp;
xcb_randr_output_t *outputs = Q_NULLPTR;
- outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources_current.data());
+ int outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources_current.data());
if (outputCount) {
timestamp = resources_current->config_timestamp;
outputs = xcb_randr_get_screen_resources_current_outputs(resources_current.data());
@@ -393,6 +429,7 @@ void QXcbConnection::initializeScreens()
qWarning("failed to get the primary output of the screen");
free(error);
} else {
+ QList<QPlatformScreen *> siblings;
for (int i = 0; i < outputCount; i++) {
QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> output(
xcb_randr_get_output_info_reply(xcb_connection(),
@@ -416,9 +453,8 @@ void QXcbConnection::initializeScreens()
continue;
}
- QXcbScreen *screen = createScreen(virtualDesktop, outputs[i], output.data());
+ QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, outputs[i], output.data());
siblings << screen;
- hasOutputs = true;
m_screens << screen;
// There can be multiple outputs per screen, use either
@@ -435,11 +471,23 @@ void QXcbConnection::initializeScreens()
}
}
}
+ virtualDesktop->setScreens(siblings);
}
}
}
}
- virtualDesktop->setScreens(siblings);
+ if (virtualDesktop->screens().isEmpty()) {
+ // If there are no XRandR outputs or XRandR extension is missing,
+ // then create a fake/legacy screen.
+ QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, XCB_NONE, Q_NULLPTR);
+ qCDebug(lcQpaScreen) << "created fake screen" << screen;
+ m_screens << screen;
+ if (m_primaryScreenNumber == xcbScreenNumber) {
+ primaryScreen = screen;
+ primaryScreen->setPrimary(true);
+ }
+ virtualDesktop->addScreen(screen);
+ }
xcb_screen_next(&it);
++xcbScreenNumber;
} // for each xcb screen
@@ -447,39 +495,25 @@ void QXcbConnection::initializeScreens()
foreach (QXcbVirtualDesktop *virtualDesktop, m_virtualDesktops)
virtualDesktop->subscribeToXFixesSelectionNotify();
- // If there's no randr extension, or there was some error above, or we found a
- // screen which doesn't have outputs for some other reason (e.g. on VNC or ssh -X),
- // but the dimensions are known anyway, and we don't already have any lingering
- // (possibly disconnected) screens, then showing windows should be possible,
- // so create one screen. (QTBUG-31389)
- QXcbVirtualDesktop *virtualDesktop = m_virtualDesktops.value(0);
- if (virtualDesktop && !hasOutputs && !virtualDesktop->size().isEmpty() && m_screens.isEmpty()) {
- QXcbScreen *screen = createScreen(virtualDesktop, 0, Q_NULLPTR);
- virtualDesktop->setScreens(QList<QPlatformScreen *>() << screen);
- m_screens << screen;
- primaryScreen = screen;
- primaryScreen->setPrimary(true);
- qCDebug(lcQpaScreen) << "found a screen with zero outputs" << screen;
- }
-
- // Ensure the primary screen is first in the list
- if (primaryScreen) {
- Q_ASSERT(!m_screens.isEmpty());
- if (m_screens.first() != primaryScreen) {
- m_screens.removeOne(primaryScreen);
- m_screens.prepend(primaryScreen);
+ if (m_virtualDesktops.isEmpty()) {
+ qFatal("QXcbConnection: no screens available");
+ } else {
+ // Ensure the primary screen is first on the list
+ if (primaryScreen) {
+ if (m_screens.first() != primaryScreen) {
+ m_screens.removeOne(primaryScreen);
+ m_screens.prepend(primaryScreen);
+ }
}
- }
- // Push the screens to QApplication
- QXcbIntegration *integration = QXcbIntegration::instance();
- foreach (QXcbScreen* screen, m_screens) {
- qCDebug(lcQpaScreen) << "adding" << screen << "(Primary:" << screen->isPrimary() << ')';
- integration->screenAdded(screen, screen->isPrimary());
- }
+ // Push the screens to QGuiApplication
+ foreach (QXcbScreen *screen, m_screens) {
+ qCDebug(lcQpaScreen) << "adding" << screen << "(Primary:" << screen->isPrimary() << ")";
+ QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
+ }
- if (!m_screens.isEmpty())
qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name();
+ }
}
QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, xcb_visualid_t defaultVisualId, const char *displayName)
@@ -553,9 +587,6 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
initializeXFixes();
initializeScreens();
- if (Q_UNLIKELY(m_screens.isEmpty()))
- qFatal("QXcbConnection: no screens available");
-
initializeXRender();
m_xi2Enabled = false;
#if defined(XCB_USE_XINPUT2)
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index cf50076f98..4acca7d374 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -518,15 +518,17 @@ private:
void initializeXShape();
void initializeXKB();
void handleClientMessageEvent(const xcb_client_message_event_t *event);
- QXcbScreen* createScreen(QXcbVirtualDesktop *virtualDesktop,
- xcb_randr_output_t outputId = XCB_NONE,
- xcb_randr_get_output_info_reply_t *output = 0);
QXcbScreen* findScreenForCrtc(xcb_window_t rootWindow, xcb_randr_crtc_t crtc);
QXcbScreen* findScreenForOutput(xcb_window_t rootWindow, xcb_randr_output_t output);
QXcbVirtualDesktop* virtualDesktopForRootWindow(xcb_window_t rootWindow);
+ void updateScreens(const xcb_randr_notify_event_t *event);
bool checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output);
+ void updateScreen(QXcbScreen *screen, const xcb_randr_output_change_t &outputChange);
+ QXcbScreen *createScreen(QXcbVirtualDesktop *virtualDesktop,
+ const xcb_randr_output_change_t &outputChange,
+ xcb_randr_get_output_info_reply_t *outputInfo);
+ void destroyScreen(QXcbScreen *screen);
void initializeScreens();
- void updateScreens(const xcb_randr_notify_event_t *event);
bool compressEvent(xcb_generic_event_t *event, int currentIndex, QXcbEventArray *eventqueue) const;
bool m_xi2Enabled;
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index 8097cce709..1a123703a5 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -406,6 +406,9 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
#endif // XCB_USE_XINPUT22
case XIValuatorClass: {
XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo);
+ // Some devices (mice) report a resolution of 0; they will be excluded later,
+ // for now just prevent a division by zero
+ const int vciResolution = vci->resolution ? vci->resolution : 1;
if (vci->label == atom(QXcbAtom::AbsMTPositionX))
caps |= QTouchDevice::Position | QTouchDevice::NormalizedPosition;
else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor))
@@ -414,16 +417,16 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
caps |= QTouchDevice::Pressure;
else if (vci->label == atom(QXcbAtom::RelX)) {
hasRelativeCoords = true;
- dev->size.setWidth((vci->max - vci->min) * 1000.0 / vci->resolution);
+ dev->size.setWidth((vci->max - vci->min) * 1000.0 / vciResolution);
} else if (vci->label == atom(QXcbAtom::RelY)) {
hasRelativeCoords = true;
- dev->size.setHeight((vci->max - vci->min) * 1000.0 / vci->resolution);
+ dev->size.setHeight((vci->max - vci->min) * 1000.0 / vciResolution);
} else if (vci->label == atom(QXcbAtom::AbsX)) {
caps |= QTouchDevice::Position;
- dev->size.setHeight((vci->max - vci->min) * 1000.0 / vci->resolution);
+ dev->size.setHeight((vci->max - vci->min) * 1000.0 / vciResolution);
} else if (vci->label == atom(QXcbAtom::AbsY)) {
caps |= QTouchDevice::Position;
- dev->size.setWidth((vci->max - vci->min) * 1000.0 / vci->resolution);
+ dev->size.setWidth((vci->max - vci->min) * 1000.0 / vciResolution);
}
break;
}
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index db7d837e01..9b1b9fcbb0 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -81,6 +81,13 @@ void QXcbVirtualDesktop::addScreen(QPlatformScreen *s)
((QXcbScreen *) s)->isPrimary() ? m_screens.prepend(s) : m_screens.append(s);
}
+void QXcbVirtualDesktop::setPrimaryScreen(QPlatformScreen *s)
+{
+ const int idx = m_screens.indexOf(s);
+ Q_ASSERT(idx > -1);
+ m_screens.swap(0, idx);
+}
+
QXcbXSettings *QXcbVirtualDesktop::xSettings() const
{
if (!m_xSettings) {
@@ -149,16 +156,15 @@ void QXcbVirtualDesktop::updateWorkArea()
}
QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop,
- xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output,
- QString outputName)
+ xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output)
: QXcbObject(connection)
, m_virtualDesktop(virtualDesktop)
, m_output(outputId)
- , m_crtc(output ? output->crtc : 0)
+ , m_crtc(output ? output->crtc : XCB_NONE)
, m_mode(XCB_NONE)
, m_primary(false)
, m_rotation(XCB_RANDR_ROTATION_ROTATE_0)
- , m_outputName(outputName)
+ , m_outputName(getOutputName(output))
, m_outputSizeMillimeters(output ? QSize(output->mm_width, output->mm_height) : QSize())
, m_virtualSize(virtualDesktop->size())
, m_virtualSizeMillimeters(virtualDesktop->physicalSize())
@@ -266,6 +272,22 @@ QXcbScreen::~QXcbScreen()
delete m_cursor;
}
+QString QXcbScreen::getOutputName(xcb_randr_get_output_info_reply_t *outputInfo)
+{
+ QString name;
+ if (outputInfo) {
+ name = QString::fromUtf8((const char*)xcb_randr_get_output_info_name(outputInfo),
+ xcb_randr_get_output_info_name_length(outputInfo));
+ } else {
+ QByteArray displayName = connection()->displayName();
+ int dotPos = displayName.lastIndexOf('.');
+ if (dotPos != -1)
+ displayName.truncate(dotPos);
+ name = QString::fromLocal8Bit(displayName) + QLatin1Char('.')
+ + QString::number(m_virtualDesktop->number());
+ }
+ return name;
+}
QWindow *QXcbScreen::topLevelAt(const QPoint &p) const
{
@@ -390,6 +412,16 @@ QPlatformCursor *QXcbScreen::cursor() const
return m_cursor;
}
+void QXcbScreen::setOutput(xcb_randr_output_t outputId,
+ xcb_randr_get_output_info_reply_t *outputInfo)
+{
+ m_output = outputId;
+ m_crtc = outputInfo ? outputInfo->crtc : XCB_NONE;
+ m_mode = XCB_NONE;
+ m_outputName = getOutputName(outputInfo);
+ // TODO: Send an event to the QScreen instance that the screen changed its name
+}
+
/*!
\brief handle the XCB screen change event and update properties
@@ -458,19 +490,10 @@ void QXcbScreen::handleScreenChange(xcb_randr_screen_change_notify_event_t *chan
updateGeometry(change_event->timestamp);
- QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry());
QWindowSystemInterface::handleScreenOrientationChange(QPlatformScreen::screen(), m_orientation);
QDpi ldpi = logicalDpi();
QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(QPlatformScreen::screen(), ldpi.first, ldpi.second);
-
- // Windows which had null screens have already had expose events by now.
- // They need to be told the screen is back, it's OK to render.
- foreach (QWindow *window, QGuiApplication::topLevelWindows()) {
- QXcbWindow *xcbWin = static_cast<QXcbWindow*>(window->handle());
- if (xcbWin)
- xcbWin->maybeSetScreen(this);
- }
}
void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp)
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
index c68c290791..79620f40ec 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -72,6 +72,7 @@ public:
void setScreens(QList<QPlatformScreen *> sl) { m_screens = sl; }
void removeScreen(QPlatformScreen *s) { m_screens.removeOne(s); }
void addScreen(QPlatformScreen *s);
+ void setPrimaryScreen(QPlatformScreen *s);
QXcbXSettings *xSettings() const;
@@ -101,10 +102,11 @@ class Q_XCB_EXPORT QXcbScreen : public QXcbObject, public QPlatformScreen
{
public:
QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop,
- xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output,
- QString outputName);
+ xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *outputInfo);
~QXcbScreen();
+ QString getOutputName(xcb_randr_get_output_info_reply_t *outputInfo);
+
QPixmap grabWindow(WId window, int x, int y, int width, int height) const Q_DECL_OVERRIDE;
QWindow *topLevelAt(const QPoint &point) const Q_DECL_OVERRIDE;
@@ -137,6 +139,10 @@ public:
xcb_randr_crtc_t crtc() const { return m_crtc; }
xcb_randr_mode_t mode() const { return m_mode; }
+ void setOutput(xcb_randr_output_t outputId,
+ xcb_randr_get_output_info_reply_t *outputInfo);
+ void setCrtc(xcb_randr_crtc_t crtc) { m_crtc = crtc; }
+
void windowShown(QXcbWindow *window);
QString windowManagerName() const { return m_windowManagerName; }
bool syncRequestSupported() const { return m_syncRequestSupported; }
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 3e01a90402..ae81674eca 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -143,7 +143,7 @@ const quint32 XEMBED_VERSION = 0;
QXcbScreen *QXcbWindow::parentScreen()
{
- return parent() ? static_cast<QXcbWindow*>(parent())->parentScreen() : m_xcbScreen;
+ return parent() ? static_cast<QXcbWindow*>(parent())->parentScreen() : xcbScreen();
}
// Returns \c true if we should set WM_TRANSIENT_FOR on \a w
@@ -266,7 +266,6 @@ static const char *wm_window_type_property_id = "_q_xcb_wm_window_type";
QXcbWindow::QXcbWindow(QWindow *window)
: QPlatformWindow(window)
, m_window(0)
- , m_xcbScreen(0)
, m_syncCounter(0)
, m_gravity(XCB_GRAVITY_STATIC)
, m_mapped(false)
@@ -322,7 +321,6 @@ void QXcbWindow::create()
QRect rect = windowGeometry();
QXcbScreen *platformScreen = parent() ? parentScreen() : static_cast<QXcbScreen*>(screenForGeometry(rect));
- m_xcbScreen = platformScreen;
if (type == Qt::Desktop) {
m_window = platformScreen->root();
m_depth = platformScreen->screen()->root_depth;
@@ -624,27 +622,18 @@ void QXcbWindow::destroy()
m_pendingSyncRequest->invalidate();
}
-void QXcbWindow::maybeSetScreen(QXcbScreen *screen)
-{
- if (!window()->screen() && screen->geometry().contains(geometry().topLeft())) {
- QWindowSystemInterface::handleWindowScreenChanged(window(), static_cast<QPlatformScreen *>(screen)->screen());
- QWindowSystemInterface::handleExposeEvent(window(), QRegion(QRect(QPoint(0, 0), window()->size())));
- }
-}
-
void QXcbWindow::setGeometry(const QRect &rect)
{
QPlatformWindow::setGeometry(rect);
propagateSizeHints();
- QXcbScreen *currentScreen = m_xcbScreen;
+ QXcbScreen *currentScreen = xcbScreen();
QXcbScreen *newScreen = parent() ? parentScreen() : static_cast<QXcbScreen*>(screenForGeometry(rect));
if (!newScreen)
newScreen = xcbScreen();
- m_xcbScreen = newScreen;
const QRect wmGeometry = windowToWmGeometry(rect);
if (newScreen && newScreen != currentScreen)
@@ -848,15 +837,13 @@ void QXcbWindow::hide()
Q_XCB_CALL(xcb_unmap_window(xcb_connection(), m_window));
// send synthetic UnmapNotify event according to icccm 4.1.4
- if (xcbScreen()) {
- xcb_unmap_notify_event_t event;
- event.response_type = XCB_UNMAP_NOTIFY;
- event.event = xcbScreen()->root();
- event.window = m_window;
- event.from_configure = false;
- Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xcbScreen()->root(),
- XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
- }
+ xcb_unmap_notify_event_t event;
+ event.response_type = XCB_UNMAP_NOTIFY;
+ event.event = xcbScreen()->root();
+ event.window = m_window;
+ event.from_configure = false;
+ Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xcbScreen()->root(),
+ XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
xcb_flush(xcb_connection());
@@ -1185,8 +1172,6 @@ void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two)
event.data.data32[3] = 0;
event.data.data32[4] = 0;
- if (!xcbScreen())
- return;
Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
}
@@ -1448,8 +1433,6 @@ void QXcbWindow::setParent(const QPlatformWindow *parent)
xcb_parent_id = qXcbParent->xcb_window();
m_embedded = qXcbParent->window()->type() == Qt::ForeignWindow;
} else {
- if (!xcbScreen())
- return;
xcb_parent_id = xcbScreen()->root();
m_embedded = false;
}
@@ -2005,7 +1988,7 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
{
bool fromSendEvent = (event->response_type & 0x80);
QPoint pos(event->x, event->y);
- if (!parent() && !fromSendEvent && xcbScreen()) {
+ if (!parent() && !fromSendEvent) {
// Do not trust the position, query it instead.
xcb_translate_coordinates_cookie_t cookie = xcb_translate_coordinates(xcb_connection(), xcb_window(),
xcbScreen()->root(), 0, 0);
@@ -2017,21 +2000,38 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
}
}
- const QRect rect = QRect(pos, QSize(event->width, event->height));
- QPlatformScreen *newScreen = parent() ? parent()->screen() : screenForGeometry(rect);
+ // The original geometry requested by setGeometry() might be different
+ // from what we end up with after applying window constraints.
+ QRect requestedGeometry = geometry();
- QXcbScreen *currentScreen = m_xcbScreen;
- m_xcbScreen = static_cast<QXcbScreen*>(newScreen);
+ const QRect actualGeometry = QRect(pos, QSize(event->width, event->height));
+ QPlatformScreen *newScreen = parent() ? parent()->screen() : screenForGeometry(actualGeometry);
if (!newScreen)
return;
- QPlatformWindow::setGeometry(rect);
- QWindowSystemInterface::handleGeometryChange(window(), rect);
- if (newScreen != currentScreen)
- QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
+ // Persist the actual geometry so that QWindow::geometry() can
+ // be queried in the resize event.
+ QPlatformWindow::setGeometry(actualGeometry);
- if (m_mapped)
- QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
+ // FIXME: In the case of the requestedGeometry not matching the actualGeometry due
+ // to e.g. the window manager applying restrictions to the geometry, the application
+ // will never see a move/resize event if the actualGeometry is the same as the current
+ // geometry, and may think the requested geometry was fulfilled.
+ QWindowSystemInterface::handleGeometryChange(window(), actualGeometry);
+
+ // QPlatformScreen::screen() is updated asynchronously, so we can't compare it
+ // with the newScreen. Just send the WindowScreenChanged event and QGuiApplication
+ // will make the comparison later.
+ QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
+
+ // For expose events we have no way of telling QGuiApplication to used the locally
+ // cached version of the previous state, so we may in some situations end up with
+ // an additional expose event.
+ QRect previousGeometry = requestedGeometry != actualGeometry ?
+ requestedGeometry : qt_window_private(window())->geometry;
+
+ if (m_mapped && actualGeometry.size() != previousGeometry.size())
+ QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), actualGeometry.size()));
if (m_usingSyncProtocol && m_syncState == SyncReceived)
m_syncState = SyncAndConfigureReceived;
@@ -2298,8 +2298,6 @@ void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event)
return;
const QPoint local(event->event_x, event->event_y);
- if (!xcbScreen())
- return;
QPoint global = QPoint(event->root_x, event->root_y);
QWindowSystemInterface::handleEnterEvent(window(), local, global);
}
@@ -2317,8 +2315,6 @@ void QXcbWindow::handleLeaveNotifyEvent(const xcb_leave_notify_event_t *event)
if (enterWindow) {
QPoint local(enter->event_x, enter->event_y);
- if (!xcbScreen())
- return;
QPoint global = QPoint(event->root_x, event->root_y);
QWindowSystemInterface::handleEnterLeaveEvent(enterWindow->window(), window(), local, global);
@@ -2334,8 +2330,6 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev
connection()->setTime(event->time);
const bool propertyDeleted = event->state == XCB_PROPERTY_DELETE;
- if (!xcbScreen())
- return;
if (event->atom == atom(QXcbAtom::_NET_WM_STATE) || event->atom == atom(QXcbAtom::WM_STATE)) {
if (propertyDeleted)
@@ -2655,8 +2649,6 @@ bool QXcbWindow::needsSync() const
void QXcbWindow::postSyncWindowRequest()
{
- if (!xcbScreen())
- return;
if (!m_pendingSyncRequest) {
QXcbSyncWindowRequest *e = new QXcbSyncWindowRequest(this);
m_pendingSyncRequest = e;
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index c42c98c205..587be22915 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -167,7 +167,6 @@ public:
virtual void create();
virtual void destroy();
- void maybeSetScreen(QXcbScreen *screen);
QXcbScreen *screenForNativeGeometry(const QRect &newGeometry) const;
public Q_SLOTS:
@@ -215,8 +214,6 @@ protected:
xcb_window_t m_window;
- QXcbScreen *m_xcbScreen;
-
uint m_depth;
QImage::Format m_imageFormat;
bool m_imageRgbSwap;
diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp
index 07d1ab0add..62022e6ef2 100644
--- a/src/widgets/dialogs/qfiledialog.cpp
+++ b/src/widgets/dialogs/qfiledialog.cpp
@@ -3795,7 +3795,7 @@ bool QFileDialogPrivate::itemViewKeyboardEvent(QKeyEvent *event) {
Q_Q(QFileDialog);
if (event->matches(QKeySequence::Cancel)) {
- q->hide();
+ q->reject();
return true;
}
diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp
index c1d0ecf33b..90d7db7bd1 100644
--- a/src/widgets/dialogs/qfilesystemmodel.cpp
+++ b/src/widgets/dialogs/qfilesystemmodel.cpp
@@ -198,13 +198,14 @@ QFileInfo QFileSystemModel::fileInfo(const QModelIndex &index) const
bool QFileSystemModel::remove(const QModelIndex &aindex)
{
const QString path = filePath(aindex);
+ const bool success = QFileInfo(path).isFile() ? QFile::remove(path) : QDir(path).removeRecursively();
#ifndef QT_NO_FILESYSTEMWATCHER
- QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func());
- d->fileInfoGatherer.removePath(path);
+ if (success) {
+ QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func());
+ d->fileInfoGatherer.removePath(path);
+ }
#endif
- if (QFileInfo(path).isFile())
- return QFile::remove(path);
- return QDir(path).removeRecursively();
+ return success;
}
/*!
@@ -1620,11 +1621,14 @@ bool QFileSystemModel::event(QEvent *event)
bool QFileSystemModel::rmdir(const QModelIndex &aindex)
{
QString path = filePath(aindex);
+ const bool success = QDir().rmdir(path);
#ifndef QT_NO_FILESYSTEMWATCHER
- QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func());
- d->fileInfoGatherer.removePath(path);
+ if (success) {
+ QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func());
+ d->fileInfoGatherer.removePath(path);
+ }
#endif
- return QDir().rmdir(path);
+ return success;
}
/*!
@@ -1800,10 +1804,6 @@ void QFileSystemModelPrivate::_q_fileSystemChanged(const QString &path, const QV
node->fileName = fileName;
}
- if (info.size() == -1 && !info.isSymLink()) {
- removeNode(parentNode, fileName);
- continue;
- }
if (*node != info ) {
node->populate(info);
bypassFilters.remove(node);
diff --git a/src/widgets/doc/src/guibooks.qdoc b/src/widgets/doc/src/guibooks.qdoc
index 8a1198c328..b3afe06961 100644
--- a/src/widgets/doc/src/guibooks.qdoc
+++ b/src/widgets/doc/src/guibooks.qdoc
@@ -76,7 +76,7 @@
advises against will produce more easily comprehensible software.
Doing what it tells you to do may also help.
- \b{\l{http://www.amazon.com/exec/obidos/ASIN/047159900X/trolltech/t}{The
+ \b{\l{http://www.amazon.com/New-Windows-Interface-Microsoft-Press/dp/1556156790/}{The
Microsoft Windows User Experience}}, ISBN 1-55615-679-0,
is Microsoft's look and feel bible. Indispensable for everyone who
has customers that worship Microsoft, and it's quite good, too.
diff --git a/src/widgets/itemviews/qlistwidget.cpp b/src/widgets/itemviews/qlistwidget.cpp
index 00ac2b54bf..275fc2a1f1 100644
--- a/src/widgets/itemviews/qlistwidget.cpp
+++ b/src/widgets/itemviews/qlistwidget.cpp
@@ -1262,7 +1262,7 @@ void QListWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
activated when the user clicks or double clicks on it, depending on the
system configuration. It is also activated when the user presses the
activation key (on Windows and X11 this is the \uicontrol Return key, on Mac OS
- X it is \uicontrol{Ctrl+0}).
+ X it is \uicontrol{Command+O}).
*/
/*!
diff --git a/src/widgets/kernel/qaction.cpp b/src/widgets/kernel/qaction.cpp
index 3306754623..66e8e5379f 100644
--- a/src/widgets/kernel/qaction.cpp
+++ b/src/widgets/kernel/qaction.cpp
@@ -255,7 +255,7 @@ void QActionPrivate::setShortcutEnabled(bool enable, QShortcutMap &map)
\value TextHeuristicRole This action should be put in the application menu based on the action's text
as described in the QMenuBar documentation.
\value ApplicationSpecificRole This action should be put in the application menu with an application specific role
- \value AboutQtRole This action matches handles the "About Qt" menu item.
+ \value AboutQtRole This action handles the "About Qt" menu item.
\value AboutRole This action should be placed where the "About" menu item is in the application menu. The text of
the menu item will be set to "About <application name>". The application name is fetched from the
\c{Info.plist} file in the application's bundle (See \l{Qt for OS X - Deployment}).
@@ -1231,7 +1231,7 @@ void QAction::activate(ActionEvent event)
\since 4.2
This indicates what role the action serves in the application menu on Mac
- OS X. By default all action have the TextHeuristicRole, which means that
+ OS X. By default all actions have the TextHeuristicRole, which means that
the action is added based on its text (see QMenuBar for more information).
The menu role can only be changed before the actions are put into the menu
diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp
index d5c8691459..63419ea093 100644
--- a/src/widgets/kernel/qwidgetbackingstore.cpp
+++ b/src/widgets/kernel/qwidgetbackingstore.cpp
@@ -448,6 +448,26 @@ void QWidgetBackingStore::sendUpdateRequest(QWidget *widget, UpdateTime updateTi
if (!widget)
return;
+#ifndef QT_NO_OPENGL
+ // Having every repaint() leading to a sync/flush is bad as it causes
+ // compositing and waiting for vsync each and every time. Change to
+ // UpdateLater, except for approx. once per frame to prevent starvation in
+ // case the control does not get back to the event loop.
+ QWidget *w = widget->window();
+ if (updateTime == UpdateNow && w && w->windowHandle() && QWindowPrivate::get(w->windowHandle())->compositing) {
+ int refresh = 60;
+ QScreen *ws = w->windowHandle()->screen();
+ if (ws)
+ refresh = ws->refreshRate();
+ QWindowPrivate *wd = QWindowPrivate::get(w->windowHandle());
+ if (wd->lastComposeTime.isValid()) {
+ const qint64 elapsed = wd->lastComposeTime.elapsed();
+ if (elapsed <= qint64(1000.0f / refresh))
+ updateTime = UpdateLater;
+ }
+ }
+#endif
+
switch (updateTime) {
case UpdateLater:
updateRequestSent = true;
@@ -621,7 +641,11 @@ void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget,
const QRect widgetRect = widget->d_func()->effectiveRectFor(rect);
- const QRect translatedRect(widgetRect.translated(widget->mapTo(tlw, QPoint())));
+ QRect translatedRect = widgetRect;
+ if (widget != tlw)
+ translatedRect.translate(widget->mapTo(tlw, QPoint()));
+ // Graphics effects may exceed window size, clamp.
+ translatedRect = translatedRect.intersected(QRect(QPoint(), tlw->size()));
if (qt_region_strictContains(dirty, translatedRect)) {
if (updateTime == UpdateNow)
sendUpdateRequest(tlw, updateTime);
diff --git a/src/widgets/widgets/qdockarealayout.cpp b/src/widgets/widgets/qdockarealayout.cpp
index 8523f43328..07efbafb31 100644
--- a/src/widgets/widgets/qdockarealayout.cpp
+++ b/src/widgets/widgets/qdockarealayout.cpp
@@ -1816,7 +1816,8 @@ void QDockAreaLayoutInfo::saveState(QDataStream &stream) const
stream << flags;
if (w->isWindow()) {
- stream << w->x() << w->y() << w->width() << w->height();
+ const QRect geometry = w->geometry();
+ stream << geometry.x() << geometry.y() << geometry.width() << geometry.height();
} else {
stream << item.pos << item.size << pick(o, item.minimumSize())
<< pick(o, item.maximumSize());
diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp
index 292681584d..67eb466ba8 100644
--- a/src/widgets/widgets/qdockwidget.cpp
+++ b/src/widgets/widgets/qdockwidget.cpp
@@ -1093,14 +1093,8 @@ void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect
q->setWindowFlags(flags);
- if (!rect.isNull()) {
- if (floating) {
- q->resize(rect.size());
- q->move(rect.topLeft());
- } else {
+ if (!rect.isNull())
q->setGeometry(rect);
- }
- }
updateButtons();
diff --git a/src/winmain/qtmain_winrt.cpp b/src/winmain/qtmain_winrt.cpp
index 473c41ab8e..098ae45dc8 100644
--- a/src/winmain/qtmain_winrt.cpp
+++ b/src/winmain/qtmain_winrt.cpp
@@ -140,6 +140,8 @@ public:
hr = applicationFactory->CreateInstance(this, &base, &core);
RETURN_VOID_IF_FAILED("Failed to create application container instance");
+
+ pidFile = INVALID_HANDLE_VALUE;
}
~AppContainer()
@@ -157,6 +159,13 @@ public:
int argc = app->args.count();
char **argv = app->args.data();
const int res = main(argc, argv);
+ if (app->pidFile != INVALID_HANDLE_VALUE) {
+ const QByteArray resString = QByteArray::number(res);
+ WriteFile(app->pidFile, reinterpret_cast<LPCVOID>(resString.constData()),
+ resString.size(), NULL, NULL);
+ FlushFileBuffers(app->pidFile);
+ CloseHandle(app->pidFile);
+ }
app->core->Exit();
return res;
}, this, CREATE_SUSPENDED, nullptr);
@@ -234,6 +243,9 @@ private:
}
}
+ if (args.count() >= 2 && strncmp(args.at(1), "-ServerName:", 12) == 0)
+ args.remove(1);
+
bool develMode = false;
bool debugWait = false;
foreach (const char *arg, args) {
@@ -248,11 +260,10 @@ private:
.absoluteFilePath(QString::number(uint(GetCurrentProcessId())) + QStringLiteral(".pid"));
CREATEFILE2_EXTENDED_PARAMETERS params = {
sizeof(CREATEFILE2_EXTENDED_PARAMETERS),
- FILE_ATTRIBUTE_NORMAL, FILE_FLAG_DELETE_ON_CLOSE
+ FILE_ATTRIBUTE_NORMAL
};
- // (Unused) handle will automatically be closed when the app exits
- CreateFile2(reinterpret_cast<LPCWSTR>(pidFileName.utf16()),
- 0, FILE_SHARE_READ|FILE_SHARE_DELETE, CREATE_ALWAYS, &params);
+ pidFile = CreateFile2(reinterpret_cast<LPCWSTR>(pidFileName.utf16()),
+ GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, CREATE_ALWAYS, &params);
// Install the develMode message handler
#ifndef Q_OS_WINPHONE
defaultMessageHandler = qInstallMessageHandler(devMessageHandler);
@@ -315,6 +326,7 @@ private:
QByteArray commandLine;
QVarLengthArray<char *> args;
HANDLE mainThread;
+ HANDLE pidFile;
};
// Main entry point for Appx containers
diff --git a/tests/auto/corelib/global/qlogging/qlogging.pro b/tests/auto/corelib/global/qlogging/qlogging.pro
index 4d3823cdbe..f1ca6570a0 100644
--- a/tests/auto/corelib/global/qlogging/qlogging.pro
+++ b/tests/auto/corelib/global/qlogging/qlogging.pro
@@ -1,6 +1,6 @@
TEMPLATE = subdirs
CONFIG += ordered
-SUBDIRS += \
- app \
- test
+!winrt: SUBDIRS += app
+
+SUBDIRS += test
diff --git a/tests/auto/corelib/global/qlogging/test/test.pro b/tests/auto/corelib/global/qlogging/test/test.pro
index df002c5728..b5b75be3a6 100644
--- a/tests/auto/corelib/global/qlogging/test/test.pro
+++ b/tests/auto/corelib/global/qlogging/test/test.pro
@@ -7,5 +7,5 @@ QT = core testlib
SOURCES = ../tst_qlogging.cpp
DEFINES += QT_MESSAGELOGCONTEXT
-TEST_HELPER_INSTALLS = ../app/app
+!winrt: TEST_HELPER_INSTALLS = ../app/app
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/corelib/io/qsettings/BLACKLIST b/tests/auto/corelib/io/qsettings/BLACKLIST
index 1cba99b66c..317e97730e 100644
--- a/tests/auto/corelib/io/qsettings/BLACKLIST
+++ b/tests/auto/corelib/io/qsettings/BLACKLIST
@@ -1,2 +1,3 @@
[isWritable:native]
osx-10.10
+osx-10.11
diff --git a/tests/auto/corelib/io/qtextstream/tst_qtextstream.cpp b/tests/auto/corelib/io/qtextstream/tst_qtextstream.cpp
index 24cde14459..7ebccbc252 100644
--- a/tests/auto/corelib/io/qtextstream/tst_qtextstream.cpp
+++ b/tests/auto/corelib/io/qtextstream/tst_qtextstream.cpp
@@ -2729,7 +2729,7 @@ void tst_QTextStream::readBomSeekBackReadBomAgain()
QFile::remove("utf8bom");
QFile file("utf8bom");
QVERIFY(file.open(QFile::ReadWrite));
- file.write("\xef\xbb\xbf" "Andreas");
+ file.write("\xef\xbb\xbf""Andreas");
file.seek(0);
QCOMPARE(file.pos(), qint64(0));
diff --git a/tests/auto/corelib/kernel/qobject/qobject.pro b/tests/auto/corelib/kernel/qobject/qobject.pro
index 6a7cf07f51..bd83396ca0 100644
--- a/tests/auto/corelib/kernel/qobject/qobject.pro
+++ b/tests/auto/corelib/kernel/qobject/qobject.pro
@@ -1,6 +1,6 @@
TEMPLATE = subdirs
CONFIG += ordered
-SUBDIRS += \
- signalbug \
- test
+!winrt: SUBDIRS+= signalbug
+
+SUBDIRS += test
diff --git a/tests/auto/corelib/kernel/qobject/test/test.pro b/tests/auto/corelib/kernel/qobject/test/test.pro
index e9c1537fa7..f3bc045455 100644
--- a/tests/auto/corelib/kernel/qobject/test/test.pro
+++ b/tests/auto/corelib/kernel/qobject/test/test.pro
@@ -3,5 +3,5 @@ TARGET = ../tst_qobject
QT = core-private network testlib
SOURCES = ../tst_qobject.cpp
-TEST_HELPER_INSTALLS = ../signalbug/signalbug
+!winrt: TEST_HELPER_INSTALLS = ../signalbug/signalbug
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
index 0c4efcd0c2..846f560214 100644
--- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
+++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
@@ -2,6 +2,7 @@
**
** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
+** Copyright (C) 2015 Intel Corporation.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -2516,14 +2517,26 @@ void tst_QVariant::variantMap()
QVariant v = map;
QVariantMap map2 = qvariant_cast<QVariantMap>(v);
+ QCOMPARE(map2.value("test").toInt(), 42);
+ QCOMPARE(map2, map);
+ map2 = v.toMap();
QCOMPARE(map2.value("test").toInt(), 42);
+ QCOMPARE(map2, map);
QVariant v2 = QVariant(QMetaType::type("QVariantMap"), &map);
QCOMPARE(qvariant_cast<QVariantMap>(v2).value("test").toInt(), 42);
QVariant v3 = QVariant(QMetaType::type("QMap<QString, QVariant>"), &map);
QCOMPARE(qvariant_cast<QVariantMap>(v3).value("test").toInt(), 42);
+
+ // multi-keys
+ map.insertMulti("test", 47);
+ v = map;
+ map2 = qvariant_cast<QVariantMap>(v);
+ QCOMPARE(map2, map);
+ map2 = v.toMap();
+ QCOMPARE(map2, map);
}
void tst_QVariant::variantHash()
@@ -2533,14 +2546,26 @@ void tst_QVariant::variantHash()
QVariant v = hash;
QVariantHash hash2 = qvariant_cast<QVariantHash>(v);
+ QCOMPARE(hash2.value("test").toInt(), 42);
+ QCOMPARE(hash2, hash);
+ hash2 = v.toHash();
QCOMPARE(hash2.value("test").toInt(), 42);
+ QCOMPARE(hash2, hash);
QVariant v2 = QVariant(QMetaType::type("QVariantHash"), &hash);
QCOMPARE(qvariant_cast<QVariantHash>(v2).value("test").toInt(), 42);
QVariant v3 = QVariant(QMetaType::type("QHash<QString, QVariant>"), &hash);
QCOMPARE(qvariant_cast<QVariantHash>(v3).value("test").toInt(), 42);
+
+ // multi-keys
+ hash.insertMulti("test", 47);
+ v = hash;
+ hash2 = qvariant_cast<QVariantHash>(v);
+ QCOMPARE(hash2, hash);
+ hash2 = v.toHash();
+ QCOMPARE(hash2, hash);
}
class CustomQObject : public QObject {
@@ -3258,24 +3283,40 @@ void tst_QVariant::convertIterables() const
map.insert("3", 4);
QCOMPARE(QVariant::fromValue(map).value<QVariantHash>().count(), map.count());
QCOMPARE(QVariant::fromValue(map).value<QVariantMap>().count(), map.count());
+
+ map.insertMulti("3", 5);
+ QCOMPARE(QVariant::fromValue(map).value<QVariantHash>().count(), map.count());
+ QCOMPARE(QVariant::fromValue(map).value<QVariantMap>().count(), map.count());
}
{
QVariantMap map;
map.insert("3", 4);
QCOMPARE(QVariant::fromValue(map).value<QVariantHash>().count(), map.count());
QCOMPARE(QVariant::fromValue(map).value<QVariantMap>().count(), map.count());
+
+ map.insertMulti("3", 5);
+ QCOMPARE(QVariant::fromValue(map).value<QVariantHash>().count(), map.count());
+ QCOMPARE(QVariant::fromValue(map).value<QVariantMap>().count(), map.count());
}
{
QHash<QString, int> hash;
hash.insert("3", 4);
QCOMPARE(QVariant::fromValue(hash).value<QVariantHash>().count(), hash.count());
QCOMPARE(QVariant::fromValue(hash).value<QVariantMap>().count(), hash.count());
+
+ hash.insertMulti("3", 5);
+ QCOMPARE(QVariant::fromValue(hash).value<QVariantHash>().count(), hash.count());
+ QCOMPARE(QVariant::fromValue(hash).value<QVariantMap>().count(), hash.count());
}
{
QVariantHash hash;
hash.insert("3", 4);
QCOMPARE(QVariant::fromValue(hash).value<QVariantHash>().count(), hash.count());
QCOMPARE(QVariant::fromValue(hash).value<QVariantMap>().count(), hash.count());
+
+ hash.insertMulti("3", 5);
+ QCOMPARE(QVariant::fromValue(hash).value<QVariantHash>().count(), hash.count());
+ QCOMPARE(QVariant::fromValue(hash).value<QVariantMap>().count(), hash.count());
}
}
diff --git a/tests/auto/corelib/thread/qthreadstorage/qthreadstorage.pro b/tests/auto/corelib/thread/qthreadstorage/qthreadstorage.pro
index d821e56366..b9bc456dcf 100644
--- a/tests/auto/corelib/thread/qthreadstorage/qthreadstorage.pro
+++ b/tests/auto/corelib/thread/qthreadstorage/qthreadstorage.pro
@@ -1,5 +1,7 @@
TEMPLATE = subdirs
SUBDIRS = \
- crashonexit \
test
+
+!winrt: SUBDIRS += crashonexit
+
CONFIG += ordered
diff --git a/tests/auto/corelib/thread/qthreadstorage/test/test.pro b/tests/auto/corelib/thread/qthreadstorage/test/test.pro
index 729241f891..b9d661a9af 100644
--- a/tests/auto/corelib/thread/qthreadstorage/test/test.pro
+++ b/tests/auto/corelib/thread/qthreadstorage/test/test.pro
@@ -5,5 +5,5 @@ CONFIG += console
QT = core testlib
SOURCES = ../tst_qthreadstorage.cpp
-TEST_HELPER_INSTALLS = ../crashonexit/crashonexit
+!winrt: TEST_HELPER_INSTALLS = ../crashonexit/crashonexit
diff --git a/tests/auto/corelib/tools/qlocale/qlocale.pro b/tests/auto/corelib/tools/qlocale/qlocale.pro
index abbe31d1ef..5161200260 100644
--- a/tests/auto/corelib/tools/qlocale/qlocale.pro
+++ b/tests/auto/corelib/tools/qlocale/qlocale.pro
@@ -1,4 +1,4 @@
TEMPLATE = subdirs
-SUBDIRS += test \
- syslocaleapp
+SUBDIRS += test
+!winrt: SUBDIRS+=syslocaleapp
diff --git a/tests/auto/corelib/tools/qlocale/test/test.pro b/tests/auto/corelib/tools/qlocale/test/test.pro
index 4777030dd7..d9004d1eb6 100644
--- a/tests/auto/corelib/tools/qlocale/test/test.pro
+++ b/tests/auto/corelib/tools/qlocale/test/test.pro
@@ -17,4 +17,4 @@ win32 {
}
}
-TEST_HELPER_INSTALLS = ../syslocaleapp/syslocaleapp
+!winrt: TEST_HELPER_INSTALLS = ../syslocaleapp/syslocaleapp
diff --git a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp
index d88a70c1e5..76341db701 100644
--- a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp
+++ b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp
@@ -95,18 +95,18 @@ private slots:
void creatingQObject();
void mixTrackingPointerCode();
void reentrancyWhileDestructing();
+ void map();
+ void hash();
+ void qvariantCast();
+ void sharedFromThis();
void threadStressTest_data();
void threadStressTest();
- void map();
- void hash();
void validConstructs();
void invalidConstructs_data();
void invalidConstructs();
-
- void qvariantCast();
- void sharedFromThis();
-
+ // let invalidConstructs be the last test, because it's the slowest;
+ // add new tests above this block
public slots:
void cleanup() { safetyCheck(); }
@@ -232,6 +232,14 @@ void tst_QSharedPointer::basics()
QCOMPARE(sizeof(weakref), 2*sizeof(void*));
}
+ {
+ QSharedPointer<const Data> ptr;
+ QWeakPointer<const Data> weakref;
+
+ QCOMPARE(sizeof(ptr), 2*sizeof(void*));
+ QCOMPARE(sizeof(weakref), 2*sizeof(void*));
+ }
+
QFETCH(bool, isNull);
Data *aData = 0;
if (!isNull)
@@ -2232,6 +2240,16 @@ void tst_QSharedPointer::sharedFromThis()
QVERIFY(const_scp.isNull());
QCOMPARE(Data::generationCounter, generations + 1);
QCOMPARE(Data::destructorCounter, destructions);
+
+ QWeakPointer<SomeClass> wcp = sc.sharedFromThis();
+ QVERIFY(wcp.isNull());
+ QCOMPARE(Data::generationCounter, generations + 1);
+ QCOMPARE(Data::destructorCounter, destructions);
+
+ QWeakPointer<const SomeClass> const_wcp = sc.sharedFromThis();
+ QVERIFY(const_wcp.isNull());
+ QCOMPARE(Data::generationCounter, generations + 1);
+ QCOMPARE(Data::destructorCounter, destructions);
}
QCOMPARE(Data::generationCounter, generations + 1);
@@ -2243,6 +2261,11 @@ void tst_QSharedPointer::sharedFromThis()
QVERIFY(const_scp.isNull());
QCOMPARE(Data::generationCounter, generations + 2);
QCOMPARE(Data::destructorCounter, destructions + 1);
+
+ QWeakPointer<const SomeClass> const_wcp = sc.sharedFromThis();
+ QVERIFY(const_wcp.isNull());
+ QCOMPARE(Data::generationCounter, generations + 2);
+ QCOMPARE(Data::destructorCounter, destructions + 1);
}
QCOMPARE(Data::generationCounter, generations + 2);
@@ -2434,6 +2457,21 @@ void tst_QSharedPointer::sharedFromThis()
QCOMPARE(Data::generationCounter, generations + 5);
QCOMPARE(Data::destructorCounter, destructions + 5);
+
+ {
+ QSharedPointer<const SomeClass> scp2(new SomeClass());
+ QVERIFY(!scp2.isNull());
+ QCOMPARE(Data::generationCounter, generations + 6);
+ QCOMPARE(Data::destructorCounter, destructions + 5);
+
+ QWeakPointer<const SomeClass> wcp2(scp2.constCast<SomeClass>());
+ QVERIFY(!wcp2.isNull());
+ QCOMPARE(Data::generationCounter, generations + 6);
+ QCOMPARE(Data::destructorCounter, destructions + 5);
+ }
+
+ QCOMPARE(Data::generationCounter, generations + 6);
+ QCOMPARE(Data::destructorCounter, destructions + 6);
}
namespace ReentrancyWhileDestructing {
diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp
index 9556dfbd51..f8a4d8a00a 100644
--- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp
+++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp
@@ -583,6 +583,7 @@ private slots:
void compareQLatin1Strings();
void fromQLatin1StringWithLength();
void assignQLatin1String();
+ void assignQChar();
void isRightToLeft_data();
void isRightToLeft();
void unicodeStrings();
@@ -6623,6 +6624,71 @@ void tst_QString::assignQLatin1String()
QCOMPARE(foo.size(), latin1subfoo.size());
QCOMPARE(foo, QString::fromLatin1("foo"));
+ // check capacity re-use:
+ QString s;
+ QCOMPARE(s.capacity(), 0);
+
+ // assign to null QString:
+ s = latin1foo;
+ QCOMPARE(s, QString::fromLatin1("foo"));
+ QCOMPARE(s.capacity(), 3);
+
+ // assign to non-null QString with enough capacity:
+ s = QString::fromLatin1("foofoo");
+ const int capacity = s.capacity();
+ s = latin1foo;
+ QCOMPARE(s, QString::fromLatin1("foo"));
+ QCOMPARE(s.capacity(), capacity);
+
+ // assign to shared QString (enough capacity, but can't use):
+ s = QString::fromLatin1("foofoo");
+ QString s2 = s;
+ s = latin1foo;
+ QCOMPARE(s, QString::fromLatin1("foo"));
+ QCOMPARE(s.capacity(), 3);
+
+ // assign to QString with too little capacity:
+ s = QString::fromLatin1("fo");
+ QCOMPARE(s.capacity(), 2);
+ s = latin1foo;
+ QCOMPARE(s, QString::fromLatin1("foo"));
+ QCOMPARE(s.capacity(), 3);
+
+}
+
+void tst_QString::assignQChar()
+{
+ const QChar sp = QLatin1Char(' ');
+ QString s;
+ QCOMPARE(s.capacity(), 0);
+
+ // assign to null QString:
+ s = sp;
+ QCOMPARE(s, QString(sp));
+ QCOMPARE(s.capacity(), 1);
+
+ // assign to non-null QString with enough capacity:
+ s = QLatin1String("foo");
+ const int capacity = s.capacity();
+ QCOMPARE(capacity, 3);
+ s = sp;
+ QCOMPARE(s, QString(sp));
+ QCOMPARE(s.capacity(), capacity);
+
+ // assign to shared QString (enough capacity, but can't use):
+ s = QLatin1String("foo");
+ QString s2 = s;
+ s = sp;
+ QCOMPARE(s, QString(sp));
+ QCOMPARE(s.capacity(), 1);
+
+ // assign to empty QString:
+ s = QString("");
+ s.detach();
+ QCOMPARE(s.capacity(), 0);
+ s = sp;
+ QCOMPARE(s, QString(sp));
+ QCOMPARE(s.capacity(), 1);
}
void tst_QString::isRightToLeft_data()
diff --git a/tests/auto/gui/kernel/qclipboard/qclipboard.pro b/tests/auto/gui/kernel/qclipboard/qclipboard.pro
index d97c58dea0..b9fd2080e7 100644
--- a/tests/auto/gui/kernel/qclipboard/qclipboard.pro
+++ b/tests/auto/gui/kernel/qclipboard/qclipboard.pro
@@ -1,4 +1,4 @@
TEMPLATE = subdirs
-SUBDIRS = copier paster
+!winrt: SUBDIRS = copier paster
test.depends += $$SUBDIRS
SUBDIRS += test
diff --git a/tests/auto/gui/kernel/qclipboard/test/test.pro b/tests/auto/gui/kernel/qclipboard/test/test.pro
index 586404871f..f27c582de2 100644
--- a/tests/auto/gui/kernel/qclipboard/test/test.pro
+++ b/tests/auto/gui/kernel/qclipboard/test/test.pro
@@ -15,6 +15,6 @@ wince* {
DEPLOYMENT += rsc reg_resource
}
-TEST_HELPER_INSTALLS = \
+!winrt: TEST_HELPER_INSTALLS = \
../copier/copier \
../paster/paster
diff --git a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp
index aa7dced0ab..d764b88ef7 100644
--- a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp
+++ b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp
@@ -100,6 +100,8 @@ private slots:
void windowsTransientChildren();
void requestUpdate();
void initTestCase();
+ void stateChange_data();
+ void stateChange();
void cleanup();
private:
@@ -390,6 +392,18 @@ static inline bool qFuzzyCompareWindowPosition(const QPoint &p1, const QPoint p2
return (p1 - p2).manhattanLength() <= fuzz;
}
+static inline bool qFuzzyCompareWindowSize(const QSize &s1, const QSize &s2, int fuzz)
+{
+ const int manhattanLength = qAbs(s1.width() - s2.width()) + qAbs(s1.height() - s2.height());
+ return manhattanLength <= fuzz;
+}
+
+static inline bool qFuzzyCompareWindowGeometry(const QRect &r1, const QRect &r2, int fuzz)
+{
+ return qFuzzyCompareWindowPosition(r1.topLeft(), r2.topLeft(), fuzz)
+ && qFuzzyCompareWindowSize(r1.size(), r2.size(), fuzz);
+}
+
static QString msgPointMismatch(const QPoint &p1, const QPoint p2)
{
QString result;
@@ -397,6 +411,13 @@ static QString msgPointMismatch(const QPoint &p1, const QPoint p2)
return result;
}
+static QString msgRectMismatch(const QRect &r1, const QRect &r2)
+{
+ QString result;
+ QDebug(&result) << r1 << "!=" << r2;
+ return result;
+}
+
void tst_QWindow::positioning()
{
if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(
@@ -561,6 +582,52 @@ void tst_QWindow::childWindowPositioning()
QCOMPARE(childWindowAfter.framePosition(), topLeftOrigin);
}
+// QTBUG-49709: Verify that the normal geometry is correctly restored
+// when executing a sequence of window state changes. So far, Windows
+// only where state changes have immediate effect.
+
+typedef QList<Qt::WindowState> WindowStateList;
+
+Q_DECLARE_METATYPE(WindowStateList)
+
+void tst_QWindow::stateChange_data()
+{
+ QTest::addColumn<WindowStateList>("stateSequence");
+
+ QTest::newRow("normal->min->normal") <<
+ (WindowStateList() << Qt::WindowMinimized << Qt::WindowNoState);
+ QTest::newRow("normal->maximized->normal") <<
+ (WindowStateList() << Qt::WindowMaximized << Qt::WindowNoState);
+ QTest::newRow("normal->fullscreen->normal") <<
+ (WindowStateList() << Qt::WindowFullScreen << Qt::WindowNoState);
+ QTest::newRow("normal->maximized->fullscreen->normal") <<
+ (WindowStateList() << Qt::WindowMaximized << Qt::WindowFullScreen << Qt::WindowNoState);
+}
+
+void tst_QWindow::stateChange()
+{
+ QFETCH(WindowStateList, stateSequence);
+
+ if (QGuiApplication::platformName().compare(QLatin1String("windows"), Qt::CaseInsensitive))
+ QSKIP("Windows-only test");
+
+ Window window;
+ window.setTitle(QLatin1String(QTest::currentTestFunction()) + QLatin1Char(' ') + QLatin1String(QTest::currentDataTag()));
+ const QRect normalGeometry(m_availableTopLeft + QPoint(40, 40), m_testWindowSize);
+ window.setGeometry(normalGeometry);
+ // explicitly use non-fullscreen show. show() can be fullscreen on some platforms
+ window.showNormal();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+ foreach (Qt::WindowState state, stateSequence) {
+ window.setWindowState(state);
+ QCoreApplication::processEvents();
+ }
+ const QRect geometry = window.geometry();
+ const int fuzz = int(QHighDpiScaling::factor(&window));
+ QVERIFY2(qFuzzyCompareWindowGeometry(geometry, normalGeometry, fuzz),
+ qPrintable(msgRectMismatch(geometry, normalGeometry)));
+}
+
class PlatformWindowFilter : public QObject
{
Q_OBJECT
diff --git a/tests/auto/network/access/qnetworkreply/qnetworkreply.pro b/tests/auto/network/access/qnetworkreply/qnetworkreply.pro
index 7cb6fddbaf..bd10c77252 100644
--- a/tests/auto/network/access/qnetworkreply/qnetworkreply.pro
+++ b/tests/auto/network/access/qnetworkreply/qnetworkreply.pro
@@ -1,5 +1,5 @@
TEMPLATE = subdirs
-!wince: SUBDIRS += echo
+!winrt:!wince: SUBDIRS += echo
test.depends += $$SUBDIRS
SUBDIRS += test
diff --git a/tests/auto/network/access/qnetworkreply/test/test.pro b/tests/auto/network/access/qnetworkreply/test/test.pro
index b683f620df..772bb55990 100644
--- a/tests/auto/network/access/qnetworkreply/test/test.pro
+++ b/tests/auto/network/access/qnetworkreply/test/test.pro
@@ -13,4 +13,4 @@ TESTDATA += ../empty ../rfc3252.txt ../resource ../bigfile ../*.jpg ../certs \
contains(QT_CONFIG,xcb): CONFIG+=insignificant_test # unstable, QTBUG-21102
win32:CONFIG += insignificant_test # QTBUG-24226
-TEST_HELPER_INSTALLS = ../echo/echo
+!winrt: TEST_HELPER_INSTALLS = ../echo/echo
diff --git a/tests/auto/network/bearer/qnetworksession/qnetworksession.pro b/tests/auto/network/bearer/qnetworksession/qnetworksession.pro
index f1cb47d14e..cd480fb73b 100644
--- a/tests/auto/network/bearer/qnetworksession/qnetworksession.pro
+++ b/tests/auto/network/bearer/qnetworksession/qnetworksession.pro
@@ -1,4 +1,4 @@
TEMPLATE = subdirs
-SUBDIRS = lackey
+!winrt:SUBDIRS = lackey
test.depends = $$SUBDIRS
SUBDIRS += test
diff --git a/tests/auto/network/bearer/qnetworksession/test/test.pro b/tests/auto/network/bearer/qnetworksession/test/test.pro
index dd7618b4ad..c95baa2b81 100644
--- a/tests/auto/network/bearer/qnetworksession/test/test.pro
+++ b/tests/auto/network/bearer/qnetworksession/test/test.pro
@@ -15,4 +15,4 @@ CONFIG(debug_and_release) {
DESTDIR = ..
}
-TEST_HELPER_INSTALLS = ../lackey/lackey
+!winrt: TEST_HELPER_INSTALLS = ../lackey/lackey
diff --git a/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp b/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp
index 2a0552b770..cc3b99ff76 100644
--- a/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp
+++ b/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp
@@ -55,6 +55,7 @@ private slots:
void initTestCase();
void cleanupTestCase();
void dump();
+ void consistencyCheck();
void loopbackIPv4();
void loopbackIPv6();
void localAddress();
@@ -148,6 +149,24 @@ void tst_QNetworkInterface::dump()
}
}
+void tst_QNetworkInterface::consistencyCheck()
+{
+ QList<QNetworkInterface> ifaces = QNetworkInterface::allInterfaces();
+ QSet<QString> interfaceNames;
+ QVector<int> interfaceIndexes;
+
+ foreach (const QNetworkInterface &iface, ifaces) {
+ QVERIFY2(!interfaceNames.contains(iface.name()),
+ "duplicate name = " + iface.name().toLocal8Bit());
+ interfaceNames << iface.name();
+
+ QVERIFY2(!interfaceIndexes.contains(iface.index()),
+ "duplicate index = " + QByteArray::number(iface.index()));
+ if (iface.index())
+ interfaceIndexes << iface.index();
+ }
+}
+
void tst_QNetworkInterface::loopbackIPv4()
{
QList<QHostAddress> all = QNetworkInterface::allAddresses();
diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
index fc2848e488..3e127e8111 100644
--- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
+++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
@@ -461,7 +461,9 @@ void tst_QSslSocket::constructing()
QCOMPARE(socket.peerAddress(), QHostAddress());
QVERIFY(socket.peerName().isEmpty());
QCOMPARE(socket.peerPort(), quint16(0));
+#ifndef QT_NO_NETWORKPROXY
QCOMPARE(socket.proxy().type(), QNetworkProxy::DefaultProxy);
+#endif
QCOMPARE(socket.readBufferSize(), qint64(0));
QCOMPARE(socket.socketDescriptor(), (qintptr)-1);
QCOMPARE(socket.socketType(), QAbstractSocket::TcpSocket);
@@ -2182,6 +2184,7 @@ void tst_QSslSocket::disconnectFromHostWhenConnected()
void tst_QSslSocket::resetProxy()
{
+#ifndef QT_NO_NETWORKPROXY
QFETCH_GLOBAL(bool, setProxy);
if (setProxy)
return;
@@ -2221,6 +2224,7 @@ void tst_QSslSocket::resetProxy()
socket2.setProxy(goodProxy);
socket2.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
QVERIFY2(socket2.waitForConnected(10000), qPrintable(socket.errorString()));
+#endif // QT_NO_NETWORKPROXY
}
void tst_QSslSocket::ignoreSslErrorsList_data()
diff --git a/tests/auto/other/toolsupport/tst_toolsupport.cpp b/tests/auto/other/toolsupport/tst_toolsupport.cpp
index a5b85ef221..fdbb6e13d4 100644
--- a/tests/auto/other/toolsupport/tst_toolsupport.cpp
+++ b/tests/auto/other/toolsupport/tst_toolsupport.cpp
@@ -124,7 +124,7 @@ void tst_toolsupport::offsets_data()
if (sizeof(void *) == 8) {
QTestData &data = QTest::newRow("QFilePrivate::fileName")
<< pmm_to_offsetof(&QFilePrivate::fileName);
- data << -1 << 248;
+ data << 168 << 248;
}
#endif
diff --git a/tests/auto/testlib/selftests/selftests.pro b/tests/auto/testlib/selftests/selftests.pro
index 32d66c019d..7a61916535 100644
--- a/tests/auto/testlib/selftests/selftests.pro
+++ b/tests/auto/testlib/selftests/selftests.pro
@@ -1,6 +1,6 @@
TEMPLATE = subdirs
-include(selftests.pri)
+!winrt: include(selftests.pri)
SUBDIRS = $$SUBPROGRAMS test
diff --git a/tests/auto/testlib/selftests/test/test.pro b/tests/auto/testlib/selftests/test/test.pro
index 106787b64d..a2a1dd3f0b 100644
--- a/tests/auto/testlib/selftests/test/test.pro
+++ b/tests/auto/testlib/selftests/test/test.pro
@@ -15,5 +15,5 @@ win32 {
RESOURCES += ../selftests.qrc
include(../selftests.pri)
-for(file, SUBPROGRAMS): TEST_HELPER_INSTALLS += "../$${file}/$${file}"
+!winrt: for(file, SUBPROGRAMS): TEST_HELPER_INSTALLS += "../$${file}/$${file}"
diff --git a/tests/auto/tools/qmake/testdata/findDeps/findDeps.pro b/tests/auto/tools/qmake/testdata/findDeps/findDeps.pro
index 2713296f5b..afb3f65297 100644
--- a/tests/auto/tools/qmake/testdata/findDeps/findDeps.pro
+++ b/tests/auto/tools/qmake/testdata/findDeps/findDeps.pro
@@ -1,4 +1,5 @@
DESTDIR = ./
+gcc: QMAKE_CXXFLAGS += -Wno-comment
HEADERS += object1.h \
object2.h \
@@ -8,5 +9,7 @@ HEADERS += object1.h \
object6.h \
object7.h \
object8.h \
- object9.h
+ object9.h \
+ objecta.h \
+ objectf.h
SOURCES += main.cpp needed.cpp
diff --git a/tests/auto/tools/qmake/testdata/findDeps/main.cpp b/tests/auto/tools/qmake/testdata/findDeps/main.cpp
index 0df3f9b7c3..3f4f5def3c 100644
--- a/tests/auto/tools/qmake/testdata/findDeps/main.cpp
+++ b/tests/auto/tools/qmake/testdata/findDeps/main.cpp
@@ -35,24 +35,56 @@
/ #include "needed.cpp"
// if not ignored, symbol needed() won't be available ...
- #include <moc_object1.cpp>
-/**/ #include <moc_object2.cpp>
-/**//**/ #include <moc_object3.cpp>
-/*'*/ #include <moc_object4.cpp>
-/*
-*/ #include <moc_object5.cpp>
+// Check we're not confused by string juxtaposition:
+static const char text[] = "lorem ""ipsum /*";
-//
+ #include <moc_object1.cpp>
+/**/ #include "\
+moc_object2.cpp\
+"
+/**//**/ #include <moc_\
+o\
+b\
+j\
+e\
+c\
+t\
+3\
+.cpp>
+/*'"*/ #include <moc_object4.cpp>
+/*"'
+*/ #include <moc_object5.cpp> /*
+#include "missing.cpp"
+*/// a backslash newline does make the next line part of this comment \
+/* so this text is in last line's C++-style comment, not a C-comment !
#include <moc_object6.cpp>
+#if 0
+#pragma "ignore me" '&' L"me"
+#line 4321 "main.cpp" more /* preprocessing */ tokens
+#endif
static void function1();
-#include <moc_object7.cpp>
+#include/* every comment
+gets replaced (in phase 3) by a single
+space */<moc_object7.cpp>
static void function2(); /**/
-#include <moc_object8.cpp>
+#include \
+<moc_object8.cpp>
static void function3(); //
#include <moc_object9.cpp>
+/* backslash-newline elimination happens in phase 2 *\
+/ # /* and that's valid here, too. *\
+/ include/* and, of course, here *\
+/<moc_objecta.cpp>// while we're here, ... \
+#include "needed.cpp"
int main () {
extern int needed(void);
return needed();
}
+
+/*
+ Deliberately end file in a #include, with nothing after it but the mandatory
+ (unescaped) newline at the end of every source file.
+*/
+#include "moc_objectf.cpp"
diff --git a/tests/auto/tools/qmake/testdata/findDeps/objecta.h b/tests/auto/tools/qmake/testdata/findDeps/objecta.h
new file mode 100644
index 0000000000..b9813b9e18
--- /dev/null
+++ b/tests/auto/tools/qmake/testdata/findDeps/objecta.h
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QObject>
+
+class ObjectA : public QObject
+{
+ Q_OBJECT
+};
+
diff --git a/tests/auto/tools/qmake/testdata/findDeps/objectf.h b/tests/auto/tools/qmake/testdata/findDeps/objectf.h
new file mode 100644
index 0000000000..5dead815a0
--- /dev/null
+++ b/tests/auto/tools/qmake/testdata/findDeps/objectf.h
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QObject>
+
+class ObjectF : public QObject
+{
+ Q_OBJECT
+};
+
diff --git a/tests/auto/tools/qmake/testdata/findMocs/findMocs.pro b/tests/auto/tools/qmake/testdata/findMocs/findMocs.pro
index a4a7dc987d..af672c2621 100644
--- a/tests/auto/tools/qmake/testdata/findMocs/findMocs.pro
+++ b/tests/auto/tools/qmake/testdata/findMocs/findMocs.pro
@@ -1,4 +1,5 @@
DESTDIR = ./
-HEADERS += object1.h object2.h object3.h object4.h object5.h object6.h object7.h
+HEADERS += object1.h object2.h object3.h object4.h \
+ object5.h object6.h object7.h object8.h object9.h
SOURCES += main.cpp
diff --git a/tests/auto/tools/qmake/testdata/findMocs/main.cpp b/tests/auto/tools/qmake/testdata/findMocs/main.cpp
index 8e0ef9fc41..3f566c4af4 100644
--- a/tests/auto/tools/qmake/testdata/findMocs/main.cpp
+++ b/tests/auto/tools/qmake/testdata/findMocs/main.cpp
@@ -39,6 +39,7 @@
#include <moc_object5.cpp>
#include <moc_object6.cpp>
#include <moc_object7.cpp>
+#include "object8.h"
+#include <moc_object9.cpp>
-int main () {}
-
+int main() { return 0; }
diff --git a/tests/auto/tools/qmake/testdata/findMocs/object1.h b/tests/auto/tools/qmake/testdata/findMocs/object1.h
index e0857f4297..1fcac5f511 100644
--- a/tests/auto/tools/qmake/testdata/findMocs/object1.h
+++ b/tests/auto/tools/qmake/testdata/findMocs/object1.h
@@ -37,6 +37,6 @@
class Object1 : public QObject
{
- Q_OBJECT
+ Q\
+_OBJECT
};
-
diff --git a/tests/auto/tools/qmake/testdata/findMocs/object2.h b/tests/auto/tools/qmake/testdata/findMocs/object2.h
index cc60269cd3..a52489b44c 100644
--- a/tests/auto/tools/qmake/testdata/findMocs/object2.h
+++ b/tests/auto/tools/qmake/testdata/findMocs/object2.h
@@ -36,6 +36,6 @@
class Object2 : public QObject
{
- Q_OBJECT
+ Q_\
+OBJECT
};
-
diff --git a/tests/auto/tools/qmake/testdata/findMocs/object3.h b/tests/auto/tools/qmake/testdata/findMocs/object3.h
index c66edee6e1..c481a0796d 100644
--- a/tests/auto/tools/qmake/testdata/findMocs/object3.h
+++ b/tests/auto/tools/qmake/testdata/findMocs/object3.h
@@ -37,6 +37,6 @@
class Object3 : public QObject
{
- Q_OBJECT
+ Q_OBJ\
+ECT
};
-
diff --git a/tests/auto/tools/qmake/testdata/findMocs/object4.h b/tests/auto/tools/qmake/testdata/findMocs/object4.h
index 73bf9cdaa3..eb38652f14 100644
--- a/tests/auto/tools/qmake/testdata/findMocs/object4.h
+++ b/tests/auto/tools/qmake/testdata/findMocs/object4.h
@@ -44,10 +44,9 @@ class Object4 : public QObject
Comment ends there --> /*/
// Now we poison moc, just to make sure this doesn't get moc'ed :)
-class NonMocObject
+class NonMocObject4
/* : QObject */
{
/* qmake ignore Q_OBJECT */
Q_OBJECT
};
-
diff --git a/tests/auto/tools/qmake/testdata/findMocs/object7.h b/tests/auto/tools/qmake/testdata/findMocs/object7.h
index 92b4672d6b..3922a542e0 100644
--- a/tests/auto/tools/qmake/testdata/findMocs/object7.h
+++ b/tests/auto/tools/qmake/testdata/findMocs/object7.h
@@ -33,6 +33,7 @@
/**//*'*/
#include <QObject>
+#define bogon /"/*"
class Object7 : public QObject
{
diff --git a/tests/auto/tools/qmake/testdata/findMocs/object8.h b/tests/auto/tools/qmake/testdata/findMocs/object8.h
new file mode 100644
index 0000000000..51096e4c27
--- /dev/null
+++ b/tests/auto/tools/qmake/testdata/findMocs/object8.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QObject>
+#define Q_OBJECTOID_THING // empty
+
+class Object8 : public QObject
+{
+ Q_OBJECT\
+OID_THING
+};
+
+// Now we poison moc, just to make sure this doesn't get moc'ed :)
+class NonMocObject8
+/* : QObject */
+{
+ /* qmake ignore Q_OBJECT */
+ Q_OBJECT
+};
diff --git a/tests/auto/tools/qmake/testdata/findMocs/object9.h b/tests/auto/tools/qmake/testdata/findMocs/object9.h
new file mode 100644
index 0000000000..bda50355d9
--- /dev/null
+++ b/tests/auto/tools/qmake/testdata/findMocs/object9.h
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QObject>
+#define juxtaposed "lorem ""ipsum /*"
+
+class Object9 : public QObject
+{
+ Q_OBJECT
+};
diff --git a/tests/auto/tools/qmake/testdata/rawString/main.cpp b/tests/auto/tools/qmake/testdata/rawString/main.cpp
new file mode 100644
index 0000000000..604986666a
--- /dev/null
+++ b/tests/auto/tools/qmake/testdata/rawString/main.cpp
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+static const char raw[] = R"blah(lorem " ipsum /*)blah"\
+;
+#include <moc_object1.cpp>
+
+int main () { return 0; }
diff --git a/tests/auto/tools/qmake/testdata/rawString/object1.h b/tests/auto/tools/qmake/testdata/rawString/object1.h
new file mode 100644
index 0000000000..1435624f7b
--- /dev/null
+++ b/tests/auto/tools/qmake/testdata/rawString/object1.h
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#define rawstring R"blah(lorem " ipsum /*)blah";
+#include <QObject>
+
+class Object1 : public QObject
+{
+ Q_OBJECT
+};
diff --git a/tests/auto/tools/qmake/testdata/rawString/rawString.pro b/tests/auto/tools/qmake/testdata/rawString/rawString.pro
new file mode 100644
index 0000000000..d2d8132ceb
--- /dev/null
+++ b/tests/auto/tools/qmake/testdata/rawString/rawString.pro
@@ -0,0 +1,4 @@
+DESTDIR = ./
+
+HEADERS += object1.h
+SOURCES += main.cpp
diff --git a/tests/auto/tools/qmake/tst_qmake.cpp b/tests/auto/tools/qmake/tst_qmake.cpp
index bd6fc63701..a891e2c20d 100644
--- a/tests/auto/tools/qmake/tst_qmake.cpp
+++ b/tests/auto/tools/qmake/tst_qmake.cpp
@@ -72,6 +72,7 @@ private slots:
void one_space();
void findMocs();
void findDeps();
+ void rawString();
#if defined(Q_OS_MAC)
void bundle_spaces();
#endif
@@ -386,6 +387,24 @@ void tst_qmake::findDeps()
QVERIFY( test_compiler.removeMakefile(workDir) );
}
+void tst_qmake::rawString()
+{
+#ifdef Q_COMPILER_RAW_STRINGS
+ QString workDir = base_path + "/testdata/rawString";
+
+ QVERIFY( test_compiler.qmake(workDir, "rawString") );
+ QVERIFY( test_compiler.make(workDir) );
+ QVERIFY( test_compiler.exists(workDir, "rawString", Exe, "1.0.0" ) );
+ QVERIFY( test_compiler.makeClean(workDir) );
+ QVERIFY( test_compiler.exists(workDir, "rawString", Exe, "1.0.0" ) );
+ QVERIFY( test_compiler.makeDistClean(workDir ) );
+ QVERIFY( !test_compiler.exists(workDir, "rawString", Exe, "1.0.0" ) );
+ QVERIFY( test_compiler.removeMakefile(workDir) );
+#else
+ QSKIP("Test for C++11 raw strings depends on compiler support for them");
+#endif
+}
+
struct TempFile
: QFile
{
diff --git a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp
index 35f4e406e0..e36c44db17 100644
--- a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp
+++ b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp
@@ -128,6 +128,7 @@ private slots:
#endif
void completionOnLevelAfterRoot();
void task233037_selectingDirectory();
+ void task235069_hideOnEscape_data();
void task235069_hideOnEscape();
void task203703_returnProperSeparator();
void task228844_ensurePreviousSorting();
@@ -764,26 +765,38 @@ void tst_QFileDialog2::task233037_selectingDirectory()
current.rmdir("test");
}
+void tst_QFileDialog2::task235069_hideOnEscape_data()
+{
+ QTest::addColumn<QString>("childName");
+ QTest::addColumn<QFileDialog::ViewMode>("viewMode");
+ QTest::newRow("listView") << QStringLiteral("listView") << QFileDialog::List;
+ QTest::newRow("fileNameEdit") << QStringLiteral("fileNameEdit") << QFileDialog::List;
+ QTest::newRow("treeView") << QStringLiteral("treeView") << QFileDialog::Detail;
+}
+
void tst_QFileDialog2::task235069_hideOnEscape()
{
+ QFETCH(QString, childName);
+ QFETCH(QFileDialog::ViewMode, viewMode);
QDir current = QDir::currentPath();
+
QNonNativeFileDialog fd;
- fd.setViewMode(QFileDialog::List);
+ QSignalSpy spyFinished(&fd, &QDialog::finished);
+ QVERIFY(spyFinished.isValid());
+ QSignalSpy spyRejected(&fd, &QDialog::rejected);
+ QVERIFY(spyRejected.isValid());
+ fd.setViewMode(viewMode);
fd.setDirectory(current.absolutePath());
- fd.setAcceptMode( QFileDialog::AcceptSave);
+ fd.setAcceptMode(QFileDialog::AcceptSave);
fd.show();
- QListView *list = fd.findChild<QListView*>("listView");
- list->setFocus();
+ QWidget *child = fd.findChild<QWidget *>(childName);
+ QVERIFY(child);
+ child->setFocus();
QTest::qWait(200);
- QTest::keyClick(list, Qt::Key_Escape);
+ QTest::keyClick(child, Qt::Key_Escape);
QCOMPARE(fd.isVisible(), false);
- QNonNativeFileDialog fd2;
- fd2.setDirectory(current.absolutePath());
- fd2.setAcceptMode( QFileDialog::AcceptSave);
- fd2.show();
- QLineEdit *edit = fd2.findChild<QLineEdit*>("fileNameEdit");
- QTest::keyClick(edit, Qt::Key_Escape);
- QCOMPARE(fd2.isVisible(), false);
+ QCOMPARE(spyFinished.count(), 1); // QTBUG-7690
+ QCOMPARE(spyRejected.count(), 1); // reject(), don't hide()
}
#ifdef QT_BUILD_INTERNAL
diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp
index 260aa25512..b0bf395f6b 100644
--- a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp
+++ b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp
@@ -123,6 +123,9 @@ private slots:
void permissions_data();
void permissions();
+ void doNotUnwatchOnFailedRmdir();
+ void specialFiles();
+
protected:
bool createFiles(const QString &test_path, const QStringList &initial_files, int existingFileCount = 0, const QStringList &intial_dirs = QStringList());
@@ -821,18 +824,21 @@ void tst_QFileSystemModel::sort()
QModelIndex parent = myModel->index(dirPath, 0);
QList<QString> expectedOrder;
expectedOrder << tempFile2.fileName() << tempFile.fileName() << dirPath + QChar('/') + ".." << dirPath + QChar('/') + ".";
- //File dialog Mode means sub trees are not sorted, only the current root
+
if (fileDialogMode) {
- // FIXME: we were only able to disableRecursiveSort in developer builds, so we can only
- // stably perform this test for developer builds
-#ifdef QT_BUILD_INTERNAL
- QList<QString> actualRows;
+ // File dialog Mode means sub trees are not sorted, only the current root.
+ // There's no way we can check that the sub tree is "not sorted"; just check if it
+ // has the same contents of the expected list
+ QList<QString> actualRows;
for(int i = 0; i < myModel->rowCount(parent); ++i)
{
actualRows << dirPath + QChar('/') + myModel->index(i, 1, parent).data(QFileSystemModel::FileNameRole).toString();
}
- QVERIFY(actualRows != expectedOrder);
-#endif
+
+ std::sort(expectedOrder.begin(), expectedOrder.end());
+ std::sort(actualRows.begin(), actualRows.end());
+
+ QCOMPARE(actualRows, expectedOrder);
} else {
for(int i = 0; i < myModel->rowCount(parent); ++i)
{
@@ -1044,6 +1050,78 @@ void tst_QFileSystemModel::permissions() // checks QTBUG-20503
QCOMPARE(fileInfoPermissions, modelPermissions);
}
+void tst_QFileSystemModel::doNotUnwatchOnFailedRmdir()
+{
+ const QString tmp = flatDirTestPath;
+
+ QFileSystemModel model;
+
+ const QTemporaryDir tempDir(tmp + '/' + QStringLiteral("doNotUnwatchOnFailedRmdir-XXXXXX"));
+ QVERIFY(tempDir.isValid());
+
+ const QModelIndex rootIndex = model.setRootPath(tempDir.path());
+
+ // create a file in the directory so to prevent it from deletion
+ {
+ QFile file(tempDir.path() + '/' + QStringLiteral("file1"));
+ QVERIFY(file.open(QIODevice::WriteOnly));
+ }
+
+ QCOMPARE(model.rmdir(rootIndex), false);
+
+ // create another file
+ {
+ QFile file(tempDir.path() + '/' + QStringLiteral("file2"));
+ QVERIFY(file.open(QIODevice::WriteOnly));
+ }
+
+ // the model must now detect this second file
+ QTRY_COMPARE(model.rowCount(rootIndex), 2);
+}
+
+static QSet<QString> fileListUnderIndex(const QFileSystemModel *model, const QModelIndex &parent)
+{
+ QSet<QString> fileNames;
+ const int rowCount = model->rowCount(parent);
+ for (int i = 0; i < rowCount; ++i)
+ fileNames.insert(model->index(i, 0, parent).data(QFileSystemModel::FileNameRole).toString());
+ return fileNames;
+}
+
+void tst_QFileSystemModel::specialFiles()
+{
+ QFileSystemModel model;
+
+ model.setFilter(QDir::AllEntries | QDir::System | QDir::Hidden);
+
+ // Can't simply verify if the model returns a valid model index for a special file
+ // as it will always return a valid index for existing files,
+ // even if the file is not visible with the given filter.
+
+#if defined(Q_OS_UNIX)
+ const QModelIndex rootIndex = model.setRootPath(QStringLiteral("/dev/"));
+ const QString testFileName = QStringLiteral("null");
+#elif defined(Q_OS_WIN)
+ const QModelIndex rootIndex = model.setRootPath(flatDirTestPath);
+
+ const QString testFileName = QStringLiteral("linkSource.lnk");
+
+ QFile file(flatDirTestPath + QLatin1String("/linkTarget.txt"));
+ QVERIFY(file.open(QIODevice::WriteOnly));
+ file.close();
+ QVERIFY(file.link(flatDirTestPath + '/' + testFileName));
+#else
+ QSKIP("Not implemented");
+ QModelIndex rootIndex;
+ QString testFileName;
+#endif
+
+ QTRY_VERIFY(fileListUnderIndex(&model, rootIndex).contains(testFileName));
+
+ model.setFilter(QDir::AllEntries | QDir::Hidden);
+
+ QTRY_VERIFY(!fileListUnderIndex(&model, rootIndex).contains(testFileName));
+}
QTEST_MAIN(tst_QFileSystemModel)
#include "tst_qfilesystemmodel.moc"
diff --git a/tests/auto/widgets/kernel/qapplication/qapplication.pro b/tests/auto/widgets/kernel/qapplication/qapplication.pro
index 5154c915cd..21bfb50aee 100644
--- a/tests/auto/widgets/kernel/qapplication/qapplication.pro
+++ b/tests/auto/widgets/kernel/qapplication/qapplication.pro
@@ -1,6 +1,6 @@
TEMPLATE = subdirs
-SUBDIRS = desktopsettingsaware modal
+!winrt: SUBDIRS = desktopsettingsaware modal
test.depends += $$SUBDIRS
SUBDIRS += test
diff --git a/tests/auto/widgets/kernel/qapplication/test/test.pro b/tests/auto/widgets/kernel/qapplication/test/test.pro
index b617c228ac..908aa846c0 100644
--- a/tests/auto/widgets/kernel/qapplication/test/test.pro
+++ b/tests/auto/widgets/kernel/qapplication/test/test.pro
@@ -9,7 +9,10 @@ TARGET = ../tst_qapplication
TESTDATA = ../test/test.pro ../tmp/README
-SUBPROGRAMS = desktopsettingsaware modal
-win32:!wince: SUBPROGRAMS += wincmdline
+!winrt {
+ SUBPROGRAMS = desktopsettingsaware modal
+ win32:!wince: SUBPROGRAMS += wincmdline
+
+ for(file, SUBPROGRAMS): TEST_HELPER_INSTALLS += "../$${file}/$${file}"
+}
-for(file, SUBPROGRAMS): TEST_HELPER_INSTALLS += "../$${file}/$${file}"
diff --git a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp
index 4819f621ea..7d84f43131 100644
--- a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp
+++ b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp
@@ -761,6 +761,9 @@ void tst_QDockWidget::restoreDockWidget()
{
QByteArray geometry;
QByteArray state;
+
+ const bool isXcb = !QGuiApplication::platformName().compare("xcb", Qt::CaseInsensitive);
+
const QString name = QStringLiteral("main");
const QRect availableGeometry = QApplication::desktop()->availableGeometry();
const QSize size = availableGeometry.size() / 5;
@@ -785,11 +788,22 @@ void tst_QDockWidget::restoreDockWidget()
QVERIFY(dock->isFloating());
state = saveWindow.saveState();
geometry = saveWindow.saveGeometry();
+
+ // QTBUG-49832: Delete and recreate the dock; it should be restored to the same position.
+ delete dock;
+ dock = createTestDock(saveWindow);
+ QVERIFY(saveWindow.restoreDockWidget(dock));
+ dock->show();
+ QVERIFY(QTest::qWaitForWindowExposed(dock));
+ QTRY_VERIFY(dock->isFloating());
+ if (!isXcb) // Avoid Window manager positioning issues
+ QTRY_COMPARE(dock->pos(), dockPos);
}
QVERIFY(!geometry.isEmpty());
QVERIFY(!state.isEmpty());
+ // QTBUG-45780: Completely recreate the dock widget from the saved state.
{
QMainWindow restoreWindow;
restoreWindow.setObjectName(name);
@@ -804,7 +818,7 @@ void tst_QDockWidget::restoreDockWidget()
restoreWindow.show();
QVERIFY(QTest::qWaitForWindowExposed(&restoreWindow));
QTRY_VERIFY(dock->isFloating());
- if (!QGuiApplication::platformName().compare("xcb", Qt::CaseInsensitive))
+ if (isXcb)
QSKIP("Skip due to Window manager positioning issues", Abort);
QTRY_COMPARE(dock->pos(), dockPos);
}
diff --git a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
index c919d4ca79..db42ed3119 100644
--- a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
+++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
@@ -229,6 +229,7 @@ private slots:
void isModified();
void edited();
+ void fixupDoesNotModify_QTBUG_49295();
void insert();
void setSelection_data();
@@ -2845,6 +2846,29 @@ void tst_QLineEdit::edited()
QVERIFY(testWidget->isModified());
}
+void tst_QLineEdit::fixupDoesNotModify_QTBUG_49295()
+{
+ QLineEdit *testWidget = ensureTestWidget();
+
+ ValidatorWithFixup val;
+ testWidget->setValidator(&val);
+ testWidget->setText("foo");
+ QVERIFY(!testWidget->isModified());
+ QVERIFY(!testWidget->hasAcceptableInput());
+
+ QTest::keyClicks(testWidget, QStringLiteral("bar"));
+ QVERIFY(testWidget->isModified());
+ QVERIFY(!testWidget->hasAcceptableInput());
+
+ // trigger a fixup, which should not reset the modified flag
+ QFocusEvent lostFocus(QEvent::FocusOut);
+ qApp->sendEvent(testWidget, &lostFocus);
+
+ QVERIFY(testWidget->hasAcceptableInput());
+ QEXPECT_FAIL("", "QTBUG-49295: a fixup of a line edit should keep it modified", Continue);
+ QVERIFY(testWidget->isModified());
+}
+
void tst_QLineEdit::insert()
{
QLineEdit *testWidget = ensureTestWidget();
diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp
index 0e06197414..3bd95498e1 100644
--- a/tools/configure/configureapp.cpp
+++ b/tools/configure/configureapp.cpp
@@ -1823,8 +1823,8 @@ bool Configure::displayHelp()
desc("BUILDDEV", "yes", "-developer-build", "Compile and link Qt with Qt developer options (including auto-tests exporting)\n");
- desc("RELEASE_TOOLS", "yes", "-optimized-tools", "Do not build optimized host tools even in debug build.");
- desc("RELEASE_TOOLS", "no", "-no-optimized-tools", "Build optimized host tools even in debug build.\n");
+ desc("RELEASE_TOOLS", "yes", "-optimized-tools", "Build optimized host tools even in debug build.");
+ desc("RELEASE_TOOLS", "no", "-no-optimized-tools", "Do not build optimized host tools even in debug build.\n");
desc("OPENSOURCE", "opensource", "-opensource", "Compile and link the Open-Source Edition of Qt.");
desc("COMMERCIAL", "commercial", "-commercial", "Compile and link the Commercial Edition of Qt.\n");
@@ -1927,9 +1927,6 @@ bool Configure::displayHelp()
desc("LARGE_FILE", "yes", "-largefile", "Enables Qt to access files larger than 4 GB.\n");
- desc("FONT_CONFIG", "yes", "-fontconfig", "Build with FontConfig support.");
- desc("FONT_CONFIG", "no", "-no-fontconfig", "Do not build with FontConfig support.\n");
-
desc("POSIX_IPC", "yes", "-posix-ipc", "Enable POSIX IPC.\n");
desc("QT_GLIB", "yes", "-glib", "Compile Glib support.\n");
@@ -1979,7 +1976,10 @@ bool Configure::displayHelp()
desc("FREETYPE", "no", "-no-freetype", "Do not compile in Freetype2 support.");
desc("FREETYPE", "yes", "-qt-freetype", "Use the libfreetype bundled with Qt.");
- desc("FREETYPE", "system","-system-freetype", "Use the libfreetype provided by the system.");
+ desc("FREETYPE", "system","-system-freetype", "Use the libfreetype provided by the system.\n");
+
+ desc("FONT_CONFIG", "yes", "-fontconfig", "Build with FontConfig support.");
+ desc("FONT_CONFIG", "no", "-no-fontconfig", "Do not build with FontConfig support.\n");
desc("HARFBUZZ", "no", "-no-harfbuzz", "Do not compile in HarfBuzz-NG support.");
desc("HARFBUZZ", "qt", "-qt-harfbuzz", "Use HarfBuzz-NG bundled with Qt to do text shaping.\n"
diff --git a/tools/configure/environment.cpp b/tools/configure/environment.cpp
index af4c5e2247..a01f792f74 100644
--- a/tools/configure/environment.cpp
+++ b/tools/configure/environment.cpp
@@ -69,11 +69,8 @@ struct CompilerInfo{
{CC_MINGW, "MinGW (Minimalist GNU for Windows)", 0, "g++.exe"},
{CC_INTEL, "Intel(R) C++ Compiler for 32-bit applications", 0, "icl.exe"}, // xilink.exe, xilink5.exe, xilink6.exe, xilib.exe
{CC_MSVC2012, "Microsoft (R) Visual Studio 2012 C/C++ Compiler (11.0)", "Software\\Microsoft\\VisualStudio\\SxS\\VC7\\11.0", "cl.exe"}, // link.exe, lib.exe
- {CC_MSVC2012, "Microsoft (R) Visual Studio 2012 C/C++ Compiler (11.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7\\11.0", "cl.exe"}, // link.exe, lib.exe
{CC_MSVC2013, "Microsoft (R) Visual Studio 2013 C/C++ Compiler (12.0)", "Software\\Microsoft\\VisualStudio\\SxS\\VC7\\12.0", "cl.exe"}, // link.exe, lib.exe
- {CC_MSVC2013, "Microsoft (R) Visual Studio 2013 C/C++ Compiler (12.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7\\12.0", "cl.exe"}, // link.exe, lib.exe
// Microsoft skipped version 13
- {CC_MSVC2015, "Microsoft (R) Visual Studio 2015 C/C++ Compiler (14.0)", "Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VS7\\14.0", "cl.exe"}, // link.exe, lib.exe
{CC_MSVC2015, "Microsoft (R) Visual Studio 2015 C/C++ Compiler (14.0)", "Software\\Microsoft\\VisualStudio\\SxS\\VS7\\14.0", "cl.exe"}, // link.exe, lib.exe
{CC_UNKNOWN, "Unknown", 0, 0},
};
@@ -175,7 +172,8 @@ Compiler Environment::detectCompiler()
QString paths = qgetenv("PATH");
QStringList pathlist = paths.toLower().split(";");
for(int i = 0; compiler_info[i].compiler; ++i) {
- QString productPath = qt_readRegistryKey(HKEY_LOCAL_MACHINE, compiler_info[i].regKey).toLower();
+ QString productPath = qt_readRegistryKey(HKEY_LOCAL_MACHINE, compiler_info[i].regKey,
+ KEY_WOW64_32KEY).toLower();
if (productPath.length()) {
QStringList::iterator it;
for(it = pathlist.begin(); it != pathlist.end(); ++it) {
diff --git a/tools/shared/windows/registry.cpp b/tools/shared/windows/registry.cpp
index c989ae279b..432c707e28 100644
--- a/tools/shared/windows/registry.cpp
+++ b/tools/shared/windows/registry.cpp
@@ -74,7 +74,7 @@ static QString keyName(const QString &rKey)
}
#endif
-QString qt_readRegistryKey(HKEY parentHandle, const QString &rSubkey)
+QString qt_readRegistryKey(HKEY parentHandle, const QString &rSubkey, unsigned long options)
{
QString result;
@@ -83,7 +83,8 @@ QString qt_readRegistryKey(HKEY parentHandle, const QString &rSubkey)
QString rSubkeyPath = keyPath(rSubkey);
HKEY handle = 0;
- LONG res = RegOpenKeyEx(parentHandle, (wchar_t*)rSubkeyPath.utf16(), 0, KEY_READ, &handle);
+ LONG res = RegOpenKeyEx(parentHandle, (wchar_t*)rSubkeyPath.utf16(), 0,
+ KEY_READ | options, &handle);
if (res != ERROR_SUCCESS)
return QString();
@@ -152,6 +153,7 @@ QString qt_readRegistryKey(HKEY parentHandle, const QString &rSubkey)
#else
Q_UNUSED(parentHandle);
Q_UNUSED(rSubkey)
+ Q_UNUSED(options);
#endif
return result;
diff --git a/tools/shared/windows/registry_p.h b/tools/shared/windows/registry_p.h
index e13f9e6f46..4fa2d6aa9f 100644
--- a/tools/shared/windows/registry_p.h
+++ b/tools/shared/windows/registry_p.h
@@ -63,8 +63,14 @@ QT_BEGIN_NAMESPACE
* If the key is not found, or the registry cannot be accessed (for example
* if this code is compiled for a platform other than Windows), a null
* string is returned.
+ *
+ * 32-bit code reads from the registry's 32 bit view (Wow6432Node),
+ * 64 bit code reads from the 64 bit view.
+ * Pass KEY_WOW64_32KEY to access the 32 bit view regardless of the
+ * application's architecture, KEY_WOW64_64KEY respectively.
*/
-QString qt_readRegistryKey(HKEY parentHandle, const QString &rSubkey);
+QString qt_readRegistryKey(HKEY parentHandle, const QString &rSubkey,
+ unsigned long options = 0);
QT_END_NAMESPACE