summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrederik Gladhorn <frederik.gladhorn@digia.com>2014-05-09 00:44:24 +0200
committerFrederik Gladhorn <frederik.gladhorn@digia.com>2014-05-13 14:21:22 +0200
commitb5552bab40f2e165cf7196993ffc83785f4d8264 (patch)
tree5ca863fc90caacebd7bd5ebd2464d4b18efdd0dc
parent9cfdd66b6452704349b5f986f31b7f1f03748cb5 (diff)
parent01ce104a3ee3c8af68f6694840931661666984ab (diff)
Merge remote-tracking branch 'origin/stable' into dev
Manually changed enum to LibGL in src/plugins/platforms/xcb/qglxintegration.cpp Change-Id: If34ee6cce3d1d51fb4bb1fdfa59c30389ea0d207
-rw-r--r--dist/changes-5.3.09
-rw-r--r--mkspecs/features/qt_helper_lib.prf27
-rw-r--r--mkspecs/features/simd.prf2
-rw-r--r--mkspecs/macx-ios-clang/features/qt.prf2
-rw-r--r--qmake/generators/mac/pbuilder_pbx.cpp2
-rw-r--r--qmake/library/qmakebuiltins.cpp6
-rw-r--r--src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro9
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-coretext.cc6
-rw-r--r--src/angle/src/common/common.pri1
-rw-r--r--src/angle/src/compiler/preprocessor/preprocessor.pro3
-rw-r--r--src/angle/src/compiler/translator.pro3
-rw-r--r--src/angle/src/config.pri9
-rw-r--r--src/angle/src/d3dcompiler/d3dcompiler.pro9
-rw-r--r--src/angle/src/libEGL/libEGL.pro6
-rw-r--r--src/angle/src/libGLESv2/libGLESv2.pro11
-rw-r--r--src/corelib/doc/qtcore.qdocconf3
-rw-r--r--src/corelib/io/qfileselector.cpp5
-rw-r--r--src/corelib/io/qloggingcategory.cpp6
-rw-r--r--src/corelib/kernel/qcoreevent.h1
-rw-r--r--src/corelib/kernel/qmetatype.h1
-rw-r--r--src/corelib/kernel/qsharedmemory.cpp8
-rw-r--r--src/corelib/tools/qtimezoneprivate_mac.mm8
-rw-r--r--src/gui/image/qpixmap_blitter.cpp4
-rw-r--r--src/gui/kernel/qopenglcontext.h8
-rw-r--r--src/gui/kernel/qwindow.h2
-rw-r--r--src/gui/opengl/qopenglframebufferobject.cpp3
-rw-r--r--src/gui/painting/qdrawhelper.cpp157
-rw-r--r--src/gui/painting/qpainter.cpp18
-rw-r--r--src/gui/text/qfontengine.cpp9
-rw-r--r--src/gui/text/qfontengine_ft.cpp36
-rw-r--r--src/gui/text/qfontengine_p.h2
-rw-r--r--src/gui/text/qtextcursor.cpp2
-rw-r--r--src/gui/text/qtextengine.cpp2
-rw-r--r--src/network/socket/qabstractsocket.cpp2
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcursor.cpp27
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcursor_p.h19
-rw-r--r--src/plugins/platforms/android/androidjniaccessibility.cpp10
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp1
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.cpp55
-rw-r--r--src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm16
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuitem.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaprintdevice.mm4
-rw-r--r--src/plugins/platforms/direct2d/direct2d.pro2
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp42
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h9
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dcontext.cpp2
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp135
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp110
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h3
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp38
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h5
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp92
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h7
-rw-r--r--src/plugins/platforms/ios/qiosapplicationstate.mm1
-rw-r--r--src/plugins/platforms/ios/qioswindow.h1
-rw-r--r--src/plugins/platforms/ios/qioswindow.mm68
-rw-r--r--src/plugins/platforms/kms/qkmsdevice.cpp5
-rw-r--r--src/plugins/platforms/kms/qkmsscreen.cpp23
-rw-r--r--src/plugins/platforms/kms/qkmsscreen.h4
-rw-r--r--src/plugins/platforms/windows/qwindowsbackingstore.cpp5
-rw-r--r--src/plugins/platforms/windows/qwindowsfontengine.cpp21
-rw-r--r--src/plugins/platforms/windows/qwindowsfontengine.h5
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.cpp1
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.cpp2
-rw-r--r--src/plugins/platforms/xcb/xcb-static/xcb-static.pro5
-rw-r--r--src/plugins/printsupport/printsupport.pro2
-rw-r--r--src/sql/models/qsqltablemodel.cpp3
-rw-r--r--src/testlib/qtest.h10
-rw-r--r--src/testlib/qtestcase.cpp16
-rw-r--r--src/widgets/accessible/simplewidgets.cpp4
-rw-r--r--src/widgets/dialogs/qfiledialog.cpp11
-rw-r--r--src/widgets/graphicsview/qgraphicsview.cpp2
-rw-r--r--src/widgets/itemviews/qlistwidget.cpp2
-rw-r--r--src/widgets/itemviews/qtreeview.cpp13
-rw-r--r--src/widgets/kernel/qopenglwidget.cpp2
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp10
-rw-r--r--src/widgets/styles/qmacstyle_mac.mm4
-rw-r--r--src/widgets/widgets/qmdiarea.cpp3
-rw-r--r--src/widgets/widgets/qmenubar.cpp4
-rw-r--r--src/widgets/widgets/qwidgettextcontrol.cpp6
-rw-r--r--tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp47
-rw-r--r--tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp15
-rw-r--r--tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp71
-rw-r--r--tests/auto/other/qaccessibility/tst_qaccessibility.cpp4
-rw-r--r--tests/auto/sql/kernel/qsqlthread/tst_qsqlthread.cpp6
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp45
-rw-r--r--tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp29
-rw-r--r--tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp148
-rw-r--r--tests/auto/widgets/styles/styles.pro2
-rw-r--r--tests/auto/xml/sax/qxmlsimplereader/tst_qxmlsimplereader.cpp34
91 files changed, 1215 insertions, 384 deletions
diff --git a/dist/changes-5.3.0 b/dist/changes-5.3.0
index ae837fc023..f97e8699d2 100644
--- a/dist/changes-5.3.0
+++ b/dist/changes-5.3.0
@@ -446,6 +446,15 @@ Android
- Fonts:
* [QTBUG-36789] Fixed support for Arabic text.
+iOS
+---
+
+ - Support for input methods added.
+ - Support for word completion and spell checking added.
+ - Support for QClipboard added.
+ - "Hide keyboard" gesture added.
+ - Keyboard input is now sendt as input method events instead of key events.
+
Linux
-----
diff --git a/mkspecs/features/qt_helper_lib.prf b/mkspecs/features/qt_helper_lib.prf
new file mode 100644
index 0000000000..4af5bcaabb
--- /dev/null
+++ b/mkspecs/features/qt_helper_lib.prf
@@ -0,0 +1,27 @@
+#
+# W A R N I N G
+# -------------
+#
+# This file is not part of the Qt API. It exists purely as an
+# implementation detail. It may change from version to version
+# without notice, or even be removed.
+#
+# We mean it.
+#
+
+load(qt_build_paths)
+
+TEMPLATE = lib
+CONFIG -= qt
+
+contains(QT_CONFIG, debug_and_release): CONFIG += debug_and_release
+contains(QT_CONFIG, build_all): CONFIG += build_all
+
+DESTDIR = $$MODULE_BASE_OUTDIR/lib
+DLLDESTDIR = $$MODULE_BASE_OUTDIR/bin
+
+# Static builds always need to be installed, as the convenience libraries
+# are not linked to the final library in this case.
+installed|static: load(qt_installs)
+
+TARGET = $$qtLibraryTarget($$TARGET)
diff --git a/mkspecs/features/simd.prf b/mkspecs/features/simd.prf
index 4f86f60700..62a63f90ca 100644
--- a/mkspecs/features/simd.prf
+++ b/mkspecs/features/simd.prf
@@ -18,7 +18,7 @@ QT_CPU_FEATURES = $$eval(QT_CPU_FEATURES.$$QT_ARCH)
#
# Set up compilers for SIMD (SSE/AVX, NEON etc)
#
-*-g++*|intel_icc|*-clang*|*-qcc* {
+gcc { # includes intel_icc and clang variants
sse2 {
HEADERS += $$SSE2_HEADERS
diff --git a/mkspecs/macx-ios-clang/features/qt.prf b/mkspecs/macx-ios-clang/features/qt.prf
index 04ebb1208a..a5b00377ee 100644
--- a/mkspecs/macx-ios-clang/features/qt.prf
+++ b/mkspecs/macx-ios-clang/features/qt.prf
@@ -15,7 +15,7 @@ equals(TEMPLATE, app):contains(QT, gui(-private)?) {
# We do link and dependency resolution for the platform plugin
# manually, since we know we always need the plugin, so we don't
# need to generate an import for it.
- CONFIG -= import_qpa_plugin
+ QTPLUGIN.platforms = -
!no_main_wrapper {
# We use ld to rename the _main symbol to _qt_main, so that we don't get a symbol clash
diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp
index da64c33cf2..d44c2ca73f 100644
--- a/qmake/generators/mac/pbuilder_pbx.cpp
+++ b/qmake/generators/mac/pbuilder_pbx.cpp
@@ -1116,7 +1116,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
//all files
const ProStringList &files = project->values(ProKey(bundle_data[i] + ".files"));
for(int file = 0; file < files.count(); file++) {
- QString fn = files[file].toQString();
+ QString fn = fileFixify(files[file].toQString(), Option::output_dir, input_dir);
QString file_ref_key = keyFor("QMAKE_PBX_BUNDLE_DATA_FILE_REF." + bundle_data[i] + "-" + fn);
bundle_file_refs += file_ref_key;
t << "\t\t" << file_ref_key << " = {\n"
diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp
index 7896688e54..46934c83e9 100644
--- a/qmake/library/qmakebuiltins.cpp
+++ b/qmake/library/qmakebuiltins.cpp
@@ -1745,14 +1745,14 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
if (target == TargetSuper) {
if (m_superfile.isEmpty()) {
m_superfile = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.super"));
- printf("Info: creating super cache file %s\n", qPrintable(m_superfile));
+ printf("Info: creating super cache file %s\n", qPrintable(QDir::toNativeSeparators(m_superfile)));
valuesRef(ProKey("_QMAKE_SUPER_CACHE_")) << ProString(m_superfile);
}
fn = m_superfile;
} else if (target == TargetCache) {
if (m_cachefile.isEmpty()) {
m_cachefile = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.cache"));
- printf("Info: creating cache file %s\n", qPrintable(m_cachefile));
+ printf("Info: creating cache file %s\n", qPrintable(QDir::toNativeSeparators(m_cachefile)));
valuesRef(ProKey("_QMAKE_CACHE_")) << ProString(m_cachefile);
// We could update m_{source,build}Root and m_featureRoots here, or even
// "re-home" our rootEnv, but this doesn't sound too useful - if somebody
@@ -1766,7 +1766,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
if (fn.isEmpty())
fn = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.stash"));
if (!m_vfs->exists(fn)) {
- printf("Info: creating stash file %s\n", qPrintable(fn));
+ printf("Info: creating stash file %s\n", qPrintable(QDir::toNativeSeparators(fn)));
valuesRef(ProKey("_QMAKE_STASH_")) << ProString(fn);
}
}
diff --git a/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro b/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
index d505c30aa6..bd0475fc05 100644
--- a/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
+++ b/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
@@ -1,16 +1,11 @@
TARGET = qtharfbuzzng
-TEMPLATE = lib
CONFIG += \
static \
hide_symbols \
exceptions_off rtti_off
-CONFIG -= qt
-contains(QT_CONFIG, debug_and_release):CONFIG += debug_and_release
-contains(QT_CONFIG, build_all):CONFIG += build_all
-
-DESTDIR = $$QT_BUILD_TREE/lib
+load(qt_helper_lib)
DEFINES += HAVE_CONFIG_H
HEADERS += $$PWD/src/config.h
@@ -133,5 +128,3 @@ mac {
# even in 10.8 where they were also made available stand-alone.
LIBS_PRIVATE += -framework ApplicationServices
}
-
-TARGET = $$TARGET$$qtPlatformTargetSuffix()
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc b/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc
index 4a905ee189..4fef861acc 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc
@@ -690,13 +690,10 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
*/
CFDictionaryRef attributes = CTRunGetAttributes (run);
CTFontRef run_ct_font = static_cast<CTFontRef>(CFDictionaryGetValue (attributes, kCTFontAttributeName));
- CGFontRef run_cg_font = CTFontCopyGraphicsFont (run_ct_font, 0);
CFRange range = CTRunGetStringRange (run);
- if (!CFEqual (run_cg_font, face_data->cg_font))
+ if (!CFEqual (run_ct_font, font_data->ct_font))
{
- CFRelease (run_cg_font);
-
buffer->ensure (buffer->len + range.length);
if (buffer->in_error)
FAIL ("Buffer resize failed");
@@ -731,7 +728,6 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
}
continue;
}
- CFRelease (run_cg_font);
/* CoreText throws away the PDF token, while the OpenType backend will add a zero-advance
* glyph for this. We need to make sure the two produce the same output. */
diff --git a/src/angle/src/common/common.pri b/src/angle/src/common/common.pri
index 58ad88673a..0943b3f299 100644
--- a/src/angle/src/common/common.pri
+++ b/src/angle/src/common/common.pri
@@ -1,3 +1,4 @@
+CONFIG += installed
include (../config.pri)
INCLUDEPATH += \
diff --git a/src/angle/src/compiler/preprocessor/preprocessor.pro b/src/angle/src/compiler/preprocessor/preprocessor.pro
index 74cd97c5a4..420cb90b36 100644
--- a/src/angle/src/compiler/preprocessor/preprocessor.pro
+++ b/src/angle/src/compiler/preprocessor/preprocessor.pro
@@ -1,7 +1,4 @@
-TEMPLATE = lib
CONFIG += static
-TARGET = $$qtLibraryTarget(preprocessor)
-
include(../../config.pri)
INCLUDEPATH = $$ANGLE_DIR/src/compiler/preprocessor
diff --git a/src/angle/src/compiler/translator.pro b/src/angle/src/compiler/translator.pro
index 0051486f82..18c3978e0f 100644
--- a/src/angle/src/compiler/translator.pro
+++ b/src/angle/src/compiler/translator.pro
@@ -1,7 +1,4 @@
-TEMPLATE = lib
CONFIG += static
-TARGET = $$qtLibraryTarget(translator)
-
include(../config.pri)
# Mingw 4.7 chokes on implicit move semantics, so disable C++11 here
diff --git a/src/angle/src/config.pri b/src/angle/src/config.pri
index 8e0f6b7f42..aa777c356f 100644
--- a/src/angle/src/config.pri
+++ b/src/angle/src/config.pri
@@ -59,17 +59,10 @@ CONFIG(debug, debug|release) {
}
# c++11 is needed by MinGW to get support for unordered_map.
-CONFIG -= qt
CONFIG += stl exceptions c++11
-contains(QT_CONFIG, debug_and_release):CONFIG += debug_and_release
-contains(QT_CONFIG, build_all):CONFIG += build_all
-
INCLUDEPATH += . .. $$PWD/../include
-DESTDIR = $$QT_BUILD_TREE/lib
-DLLDESTDIR = $$QT_BUILD_TREE/bin
-
msvc {
# Disabled Warnings:
# 4100: 'identifier' : unreferenced formal parameter
@@ -107,3 +100,5 @@ gcc {
QMAKE_CXXFLAGS_DEBUG = $$QMAKE_CFLAGS_DEBUG
QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE
+
+load(qt_helper_lib)
diff --git a/src/angle/src/d3dcompiler/d3dcompiler.pro b/src/angle/src/d3dcompiler/d3dcompiler.pro
index 4d22080185..04b1de895d 100644
--- a/src/angle/src/d3dcompiler/d3dcompiler.pro
+++ b/src/angle/src/d3dcompiler/d3dcompiler.pro
@@ -1,9 +1,8 @@
-TEMPLATE = lib
-TARGET = $$qtLibraryTarget(d3dcompiler_qt)
-
+TARGET = d3dcompiler_qt
+CONFIG += installed
include(../config.pri)
-CONFIG += qt
+CONFIG += qt
QT = core
DEFINES += QT_NO_CAST_FROM_ASCII QT_NO_CAST_TO_ASCII
SOURCES += main.cpp
@@ -16,5 +15,3 @@ winrt:equals(WINSDK_VER, 8.1) {
# __stdcall exports get mangled, so use a def file
DEF_FILE += $${TARGET}.def
-
-load(qt_installs)
diff --git a/src/angle/src/libEGL/libEGL.pro b/src/angle/src/libEGL/libEGL.pro
index 4f10583fc0..dc286ca11d 100644
--- a/src/angle/src/libEGL/libEGL.pro
+++ b/src/angle/src/libEGL/libEGL.pro
@@ -1,6 +1,4 @@
-TEMPLATE = lib
-TARGET = $$qtLibraryTarget(libEGL)
-
+CONFIG += installed
include(../common/common.pri)
angle_d3d11: \
@@ -30,8 +28,6 @@ SOURCES += \
mingw:equals(QT_ARCH, i386): DEF_FILE = $$ANGLE_DIR/src/libEGL/$${TARGET}_mingw32.def
}
-load(qt_installs)
-
egl_headers.files = \
$$ANGLE_DIR/include/EGL/egl.h \
$$ANGLE_DIR/include/EGL/eglext.h \
diff --git a/src/angle/src/libGLESv2/libGLESv2.pro b/src/angle/src/libGLESv2/libGLESv2.pro
index 6176016f13..70c58dc5a4 100644
--- a/src/angle/src/libGLESv2/libGLESv2.pro
+++ b/src/angle/src/libGLESv2/libGLESv2.pro
@@ -1,7 +1,4 @@
-TEMPLATE = lib
-TARGET = $$qtLibraryTarget(libGLESv2)
-CONFIG += simd
-
+CONFIG += simd installed
include(../common/common.pri)
INCLUDEPATH += $$OUT_PWD/.. $$ANGLE_DIR/src/libGLESv2
@@ -13,8 +10,8 @@ angle_d3d11: \
LIBS_PRIVATE += -ld3d9
LIBS_PRIVATE += -ldxguid
-STATICLIBS = translator preprocessor
+STATICLIBS = translator preprocessor
for(libname, STATICLIBS) {
# Appends 'd' to the library for debug builds and builds up the fully
# qualified path to pass to the linker.
@@ -238,8 +235,6 @@ for (vs, VERTEX_SHADERS_CLEAR) {
angle_d3d11: QMAKE_EXTRA_COMPILERS += fxc_vs_$${vs}
}
-load(qt_installs)
-
khr_headers.files = $$ANGLE_DIR/include/KHR/khrplatform.h
khr_headers.path = $$[QT_INSTALL_HEADERS]/QtANGLE/KHR
gles2_headers.files = \
@@ -248,5 +243,3 @@ gles2_headers.files = \
$$ANGLE_DIR/include/GLES2/gl2platform.h
gles2_headers.path = $$[QT_INSTALL_HEADERS]/QtANGLE/GLES2
INSTALLS += khr_headers gles2_headers
-
-
diff --git a/src/corelib/doc/qtcore.qdocconf b/src/corelib/doc/qtcore.qdocconf
index c8eb15a7f7..c9c8f1da54 100644
--- a/src/corelib/doc/qtcore.qdocconf
+++ b/src/corelib/doc/qtcore.qdocconf
@@ -26,7 +26,8 @@ qhp.QtCore.subprojects.classes.sortPages = true
tagfile = ../../../doc/qtcore/qtcore.tags
-depends += activeqt qtdbus qtgui qtwidgets qtnetwork qtdoc qtmacextras qtqml qtquick qtlinguist qtdesigner qtconcurrent qtxml qmake
+depends += activeqt qtdbus qtgui qtwidgets qtnetwork qtdoc qtmacextras qtquick qtlinguist qtdesigner qtconcurrent qtxml qmake
+# depends += qtqml # Qt namespace collides with QtQml::Qt, see QTBUG-38630
headerdirs += ..
diff --git a/src/corelib/io/qfileselector.cpp b/src/corelib/io/qfileselector.cpp
index b4021c060f..0fa1f02f5c 100644
--- a/src/corelib/io/qfileselector.cpp
+++ b/src/corelib/io/qfileselector.cpp
@@ -365,6 +365,11 @@ QStringList QFileSelectorPrivate::platformSelectors()
ret << QStringLiteral("windows");
# if defined(Q_OS_WINCE)
ret << QStringLiteral("wince");
+# elif defined(Q_OS_WINRT)
+ ret << QStringLiteral("winrt");
+# if defined(Q_OS_WINPHONE)
+ ret << QStringLiteral("winphone");
+# endif
# endif
#elif defined(Q_OS_UNIX)
ret << QStringLiteral("unix");
diff --git a/src/corelib/io/qloggingcategory.cpp b/src/corelib/io/qloggingcategory.cpp
index 08ecd67dc8..518052e537 100644
--- a/src/corelib/io/qloggingcategory.cpp
+++ b/src/corelib/io/qloggingcategory.cpp
@@ -62,6 +62,12 @@ Q_GLOBAL_STATIC_WITH_ARGS(QLoggingCategory, qtDefaultCategory,
by a string - at runtime. Whether a category should be actually logged or
not can be checked with the \l isEnabled() methods.
+ All objects are meant to be configured by a common registry (see also
+ \l{Configuring Categories}). Different objects can also represent the same
+ category. It's therefore not recommended to export objects across module
+ boundaries, nor to manipulate the objects directly, nor to inherit from
+ QLoggingCategory.
+
\section1 Creating category objects
The Q_LOGGING_CATEGORY() and the Q_DECLARE_LOGGING_CATEGORY() macros
diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h
index 2e0f781822..d5aed60972 100644
--- a/src/corelib/kernel/qcoreevent.h
+++ b/src/corelib/kernel/qcoreevent.h
@@ -325,6 +325,7 @@ private:
friend class QGraphicsViewPrivate;
friend class QGraphicsScene;
friend class QGraphicsScenePrivate;
+ friend class QWidgetWindow;
#ifndef QT_NO_GESTURES
friend class QGestureManager;
#endif
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 3c9cc9ee28..9c61a67962 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -777,6 +777,7 @@ struct VariantData
const void *data;
const uint flags;
private:
+ // copy constructor allowed to be implicit to silence level 4 warning from MSVC
VariantData &operator=(const VariantData &) Q_DECL_EQ_DELETE;
};
diff --git a/src/corelib/kernel/qsharedmemory.cpp b/src/corelib/kernel/qsharedmemory.cpp
index 407a6a4e02..cde42c4f6e 100644
--- a/src/corelib/kernel/qsharedmemory.cpp
+++ b/src/corelib/kernel/qsharedmemory.cpp
@@ -125,11 +125,9 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key,
or writing to the shared memory, and remember to release the lock
with unlock() after you are done.
- Unlike QtSharedMemory, QSharedMemory automatically destroys the
- shared memory segment when the last instance of QSharedMemory is
- detached from the segment, and no references to the segment
- remain. Do not mix using QtSharedMemory and QSharedMemory. Port
- everything to QSharedMemory.
+ QSharedMemory automatically destroys the shared memory segment when
+ the last instance of QSharedMemory is detached from the segment, and
+ no references to the segment remain.
\warning QSharedMemory changes the key in a Qt-specific way, unless otherwise
specified. Interoperation with non-Qt applications is achieved by first creating
diff --git a/src/corelib/tools/qtimezoneprivate_mac.mm b/src/corelib/tools/qtimezoneprivate_mac.mm
index 49930490ff..7985b78712 100644
--- a/src/corelib/tools/qtimezoneprivate_mac.mm
+++ b/src/corelib/tools/qtimezoneprivate_mac.mm
@@ -89,7 +89,7 @@ QTimeZonePrivate *QMacTimeZonePrivate::clone()
void QMacTimeZonePrivate::init(const QByteArray &ianaId)
{
if (availableTimeZoneIds().contains(ianaId)) {
- m_nstz = [NSTimeZone timeZoneWithName:QCFString::toNSString(QString::fromUtf8(ianaId))];
+ m_nstz = [[NSTimeZone timeZoneWithName:QCFString::toNSString(QString::fromUtf8(ianaId))] retain];
if (m_nstz)
m_id = ianaId;
}
@@ -142,7 +142,6 @@ QString QMacTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
NSString *macLocaleCode = QCFString::toNSString(locale.name());
NSLocale *macLocale = [[NSLocale alloc] initWithLocaleIdentifier:macLocaleCode];
const QString result = QCFString::toQString([m_nstz localizedName:style locale:macLocale]);
- [macLocaleCode release];
[macLocale release];
return result;
}
@@ -192,7 +191,6 @@ QTimeZonePrivate::Data QMacTimeZonePrivate::data(qint64 forMSecsSinceEpoch) cons
data.daylightTimeOffset = [m_nstz daylightSavingTimeOffsetForDate:date];
data.standardTimeOffset = data.offsetFromUtc - data.daylightTimeOffset;
data.abbreviation = QCFString::toQString([m_nstz abbreviationForDate:date]);
- [date release];
return data;
}
@@ -203,8 +201,6 @@ bool QMacTimeZonePrivate::hasTransitions() const
NSDate *epoch = [NSDate dateWithTimeIntervalSince1970:0];
const NSDate *date = [m_nstz nextDaylightSavingTimeTransitionAfterDate:epoch];
const bool result = ([date timeIntervalSince1970] > [epoch timeIntervalSince1970]);
- [epoch release];
- [date release];
return result;
}
@@ -224,7 +220,6 @@ QTimeZonePrivate::Data QMacTimeZonePrivate::nextTransition(qint64 afterMSecsSinc
tran.daylightTimeOffset = [m_nstz daylightSavingTimeOffsetForDate:nextDate];
tran.standardTimeOffset = tran.offsetFromUtc - tran.daylightTimeOffset;
tran.abbreviation = QCFString::toQString([m_nstz abbreviationForDate:nextDate]);
- [nextDate release];
return tran;
}
@@ -246,7 +241,6 @@ QTimeZonePrivate::Data QMacTimeZonePrivate::previousTransition(qint64 beforeMSec
nextDate = [m_nstz nextDaylightSavingTimeTransitionAfterDate:nextDate];
nextSecs = [nextDate timeIntervalSince1970];
}
- [nextDate release];
}
if (secsList.size() >= 1)
return data(qint64(secsList.last()) * 1000);
diff --git a/src/gui/image/qpixmap_blitter.cpp b/src/gui/image/qpixmap_blitter.cpp
index 839a7a709f..2915cdda2d 100644
--- a/src/gui/image/qpixmap_blitter.cpp
+++ b/src/gui/image/qpixmap_blitter.cpp
@@ -59,6 +59,7 @@ static int global_ser_no = 0;
QBlittablePlatformPixmap::QBlittablePlatformPixmap()
: QPlatformPixmap(QPlatformPixmap::PixmapType,BlitterClass)
, m_alpha(false)
+ , m_devicePixelRatio(1.0)
#ifdef QT_BLITTER_RASTEROVERLAY
,m_rasterOverlay(0), m_unmergedCopy(0)
#endif //QT_BLITTER_RASTEROVERLAY
@@ -121,7 +122,7 @@ int QBlittablePlatformPixmap::metric(QPaintDevice::PaintDeviceMetric metric) con
case QPaintDevice::PdmPhysicalDpiY:
return qt_defaultDpiY();
case QPaintDevice::PdmDevicePixelRatio:
- return 1;
+ return devicePixelRatio();
default:
qWarning("QRasterPlatformPixmap::metric(): Unhandled metric type %d", metric);
break;
@@ -178,6 +179,7 @@ void QBlittablePlatformPixmap::fromImage(const QImage &image,
Qt::ImageConversionFlags flags)
{
m_alpha = image.hasAlphaChannel();
+ m_devicePixelRatio = image.devicePixelRatio();
resize(image.width(),image.height());
markRasterOverlay(QRect(0,0,w,h));
QImage *thisImg = buffer();
diff --git a/src/gui/kernel/qopenglcontext.h b/src/gui/kernel/qopenglcontext.h
index 402989b4d0..99f2fece51 100644
--- a/src/gui/kernel/qopenglcontext.h
+++ b/src/gui/kernel/qopenglcontext.h
@@ -199,19 +199,13 @@ public:
enum OpenGLModuleType {
LibGL,
- LibGLES,
-
- // ###
- DesktopGL = LibGL,
- GLES2 = LibGLES
+ LibGLES
};
static OpenGLModuleType openGLModuleType();
bool isOpenGLES() const;
- bool isES() const { return isOpenGLES(); } // ###
-
Q_SIGNALS:
void aboutToBeDestroyed();
diff --git a/src/gui/kernel/qwindow.h b/src/gui/kernel/qwindow.h
index 3278b7233c..0d13cfa648 100644
--- a/src/gui/kernel/qwindow.h
+++ b/src/gui/kernel/qwindow.h
@@ -297,7 +297,7 @@ Q_SIGNALS:
void screenChanged(QScreen *screen);
void modalityChanged(Qt::WindowModality modality);
void windowStateChanged(Qt::WindowState windowState);
- void windowTitleChanged(const QString &title);
+ Q_REVISION(2) void windowTitleChanged(const QString &title);
void xChanged(int arg);
void yChanged(int arg);
diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp
index cc829df950..7fb6815120 100644
--- a/src/gui/opengl/qopenglframebufferobject.cpp
+++ b/src/gui/opengl/qopenglframebufferobject.cpp
@@ -1112,6 +1112,9 @@ Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format,
\fn QImage QOpenGLFramebufferObject::toImage() const
Returns the contents of this framebuffer object as a QImage.
+
+ Will try to return a premultiplied ARBG32 or RGB32 image. Since 5.2 it will fall back to
+ a premultiplied RGBA8888 or RGBx8888 image when reading to ARGB32 is not supported.
*/
QImage QOpenGLFramebufferObject::toImage() const
{
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 7a5c5dc660..b5ccafdf9a 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -1709,6 +1709,163 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c
}
} else {
//we are zooming less than 8x, use 4bit precision
+
+ if (blendType != BlendTransformedBilinearTiled) {
+#define BILINEAR_ROTATE_BOUNDS_PROLOG \
+ while (b < end) { \
+ int x1 = (fx >> 16); \
+ int x2; \
+ int y1 = (fy >> 16); \
+ int y2; \
+ fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); \
+ fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); \
+ if (x1 != x2 && y1 != y2) \
+ break; \
+ const uint *s1 = (const uint *)data->texture.scanLine(y1); \
+ const uint *s2 = (const uint *)data->texture.scanLine(y2); \
+ uint tl = s1[x1]; \
+ uint tr = s1[x2]; \
+ uint bl = s2[x1]; \
+ uint br = s2[x2]; \
+ int distx = (fx & 0x0000ffff) >> 12; \
+ int disty = (fy & 0x0000ffff) >> 12; \
+ *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty); \
+ fx += fdx; \
+ fy += fdy; \
+ ++b; \
+ } \
+ uint *boundedEnd = end - 3; \
+ boundedEnd -= 3;
+
+#if defined(__SSE2__)
+ BILINEAR_ROTATE_BOUNDS_PROLOG
+
+ const __m128i colorMask = _mm_set1_epi32(0x00ff00ff);
+ const __m128i v_256 = _mm_set1_epi16(256);
+ __m128i v_fdx = _mm_set1_epi32(fdx*4);
+ __m128i v_fdy = _mm_set1_epi32(fdy*4);
+
+ const uchar *textureData = data->texture.imageData;
+ const int bytesPerLine = data->texture.bytesPerLine;
+
+ union Vect_buffer { __m128i vect; qint32 i[4]; };
+ Vect_buffer v_fx, v_fy;
+
+ for (int i = 0; i < 4; i++) {
+ v_fx.i[i] = fx;
+ v_fy.i[i] = fy;
+ fx += fdx;
+ fy += fdy;
+ }
+
+ while (b < boundedEnd) {
+ if (fdx > 0 && (v_fx.i[3] >> 16) >= image_x2)
+ break;
+ if (fdx < 0 && (v_fx.i[3] >> 16) < image_x1)
+ break;
+ if (fdy > 0 && (v_fy.i[3] >> 16) >= image_y2)
+ break;
+ if (fdy < 0 && (v_fy.i[3] >> 16) < image_y1)
+ break;
+
+ Vect_buffer tl, tr, bl, br;
+ Vect_buffer v_fx_shifted, v_fy_shifted;
+ v_fx_shifted.vect = _mm_srli_epi32(v_fx.vect, 16);
+ v_fy_shifted.vect = _mm_srli_epi32(v_fy.vect, 16);
+
+ for (int i = 0; i < 4; i++) {
+ const int x1 = v_fx_shifted.i[i];
+ const int y1 = v_fy_shifted.i[i];
+ const uchar *sl = textureData + bytesPerLine * y1;
+ const uint *s1 = (const uint *)sl;
+ const uint *s2 = (const uint *)(sl + bytesPerLine);
+ tl.i[i] = s1[x1];
+ tr.i[i] = s1[x1+1];
+ bl.i[i] = s2[x1];
+ br.i[i] = s2[x1+1];
+ }
+ __m128i v_distx = _mm_srli_epi16(v_fx.vect, 12);
+ __m128i v_disty = _mm_srli_epi16(v_fy.vect, 12);
+ v_distx = _mm_shufflehi_epi16(v_distx, _MM_SHUFFLE(2,2,0,0));
+ v_distx = _mm_shufflelo_epi16(v_distx, _MM_SHUFFLE(2,2,0,0));
+ v_disty = _mm_shufflehi_epi16(v_disty, _MM_SHUFFLE(2,2,0,0));
+ v_disty = _mm_shufflelo_epi16(v_disty, _MM_SHUFFLE(2,2,0,0));
+
+ interpolate_4_pixels_16_sse2(tl.vect, tr.vect, bl.vect, br.vect, v_distx, v_disty, colorMask, v_256, b);
+ b+=4;
+ v_fx.vect = _mm_add_epi32(v_fx.vect, v_fdx);
+ v_fy.vect = _mm_add_epi32(v_fy.vect, v_fdy);
+ }
+ fx = v_fx.i[0];
+ fy = v_fy.i[0];
+#elif defined(__ARM_NEON__)
+ BILINEAR_ROTATE_BOUNDS_PROLOG
+
+ const int16x8_t colorMask = vdupq_n_s16(0x00ff);
+ const int16x8_t invColorMask = vmvnq_s16(colorMask);
+ const int16x8_t v_256 = vdupq_n_s16(256);
+ int32x4_t v_fdx = vdupq_n_s32(fdx*4);
+ int32x4_t v_fdy = vdupq_n_s32(fdy*4);
+
+ const uchar *textureData = data->texture.imageData;
+ const int bytesPerLine = data->texture.bytesPerLine;
+
+ union Vect_buffer { int32x4_t vect; quint32 i[4]; };
+ Vect_buffer v_fx, v_fy;
+
+ for (int i = 0; i < 4; i++) {
+ v_fx.i[i] = fx;
+ v_fy.i[i] = fy;
+ fx += fdx;
+ fy += fdy;
+ }
+
+ const int32x4_t v_ffff_mask = vdupq_n_s32(0x0000ffff);
+
+ while (b < boundedEnd) {
+ if (fdx > 0 && (v_fx.i[3] >> 16) >= image_x2)
+ break;
+ if (fdx < 0 && (v_fx.i[3] >> 16) < image_x1)
+ break;
+ if (fdy > 0 && (v_fy.i[3] >> 16) >= image_y2)
+ break;
+ if (fdy < 0 && (v_fy.i[3] >> 16) < image_y1)
+ break;
+
+ Vect_buffer tl, tr, bl, br;
+
+ Vect_buffer v_fx_shifted, v_fy_shifted;
+ v_fx_shifted.vect = vshrq_n_s32(v_fx.vect, 16);
+ v_fy_shifted.vect = vshrq_n_s32(v_fy.vect, 16);
+
+ for (int i = 0; i < 4; i++) {
+ const int x1 = v_fx_shifted.i[i];
+ const int y1 = v_fy_shifted.i[i];
+ const uchar *sl = textureData + bytesPerLine * y1;
+ const uint *s1 = (const uint *)sl;
+ const uint *s2 = (const uint *)(sl + bytesPerLine);
+ tl.i[i] = s1[x1];
+ tr.i[i] = s1[x1+1];
+ bl.i[i] = s2[x1];
+ br.i[i] = s2[x1+1];
+ }
+
+ int32x4_t v_distx = vshrq_n_s32(vandq_s32(v_fx.vect, v_ffff_mask), 12);
+ int32x4_t v_disty = vshrq_n_s32(vandq_s32(v_fy.vect, v_ffff_mask), 12);
+ v_distx = vorrq_s32(v_distx, vshlq_n_s32(v_distx, 16));
+ v_disty = vorrq_s32(v_disty, vshlq_n_s32(v_disty, 16));
+ int16x8_t v_disty_ = vshlq_n_s16(v_disty, 4);
+
+ interpolate_4_pixels_16_neon(vreinterpretq_s16_s32(tl.vect), vreinterpretq_s16_s32(tr.vect), vreinterpretq_s16_s32(bl.vect), vreinterpretq_s16_s32(br.vect), vreinterpretq_s16_s32(v_distx), v_disty, v_disty_, colorMask, invColorMask, v_256, b);
+ b+=4;
+ v_fx.vect = vaddq_s32(v_fx.vect, v_fdx);
+ v_fy.vect = vaddq_s32(v_fy.vect, v_fdy);
+ }
+ fx = v_fx.i[0];
+ fy = v_fy.i[0];
+#endif
+ }
+
while (b < end) {
int x1 = (fx >> 16);
int x2;
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index a3b1f07c69..7c691c9670 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -147,8 +147,9 @@ static inline uint line_emulation(uint emulation)
}
#ifndef QT_NO_DEBUG
-static bool qt_painter_thread_test(int devType, const char *what)
+static bool qt_painter_thread_test(int devType, int engineType, const char *what)
{
+ const QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
switch (devType) {
case QInternal::Image:
case QInternal::Printer:
@@ -157,8 +158,13 @@ static bool qt_painter_thread_test(int devType, const char *what)
break;
default:
if (QThread::currentThread() != qApp->thread()
- && (devType!=QInternal::Pixmap || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedPixmaps))
- && (devType!=QInternal::OpenGL || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedOpenGL))) {
+ // pixmaps cannot be targets unless threaded pixmaps are supported
+ && (devType != QInternal::Pixmap || !platformIntegration->hasCapability(QPlatformIntegration::ThreadedPixmaps))
+ // framebuffer objects and such cannot be targets unless threaded GL is supported
+ && (devType != QInternal::OpenGL || !platformIntegration->hasCapability(QPlatformIntegration::ThreadedOpenGL))
+ // widgets cannot be targets except for QGLWidget
+ && (devType != QInternal::Widget || !platformIntegration->hasCapability(QPlatformIntegration::ThreadedOpenGL)
+ || (engineType != QPaintEngine::OpenGL && engineType != QPaintEngine::OpenGL2))) {
qWarning("QPainter: It is not safe to use %s outside the GUI thread", what);
return false;
}
@@ -5054,7 +5060,7 @@ void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm)
return;
#ifndef QT_NO_DEBUG
- qt_painter_thread_test(d->device->devType(), "drawPixmap()");
+ qt_painter_thread_test(d->device->devType(), d->engine->type(), "drawPixmap()");
#endif
if (d->extended) {
@@ -5125,7 +5131,7 @@ void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
if (!d->engine || pm.isNull())
return;
#ifndef QT_NO_DEBUG
- qt_painter_thread_test(d->device->devType(), "drawPixmap()");
+ qt_painter_thread_test(d->device->devType(), d->engine->type(), "drawPixmap()");
#endif
qreal x = r.x();
@@ -6612,7 +6618,7 @@ void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPo
return;
#ifndef QT_NO_DEBUG
- qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()");
+ qt_painter_thread_test(d->device->devType(), d->engine->type(), "drawTiledPixmap()");
#endif
qreal sw = pixmap.width();
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index b2254c4826..078e16574f 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -1335,6 +1335,15 @@ QByteArray QFontEngine::convertToPostscriptFontFamilyName(const QByteArray &fami
return f;
}
+/**
+ * Some font engines like the windows font engine
+ * can not reliable create outline paths
+ */
+bool QFontEngine::hasUnreliableGlyphOutline() const
+{
+ return false;
+}
+
QFixed QFontEngine::lastRightBearing(const QGlyphLayout &glyphs, bool round)
{
if (glyphs.numGlyphs >= 1) {
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index fe38755ffd..f5ca559d62 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -450,6 +450,7 @@ static void scaleOutline(FT_Face face, FT_GlyphSlot g, FT_Fixed x_scale, FT_Fixe
}
}
+#define GLYPH2PATH_DEBUG QT_NO_QDEBUG_MACRO // qDebug
void QFreetypeFace::addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoint &point, QPainterPath *path, FT_Fixed x_scale, FT_Fixed y_scale)
{
const qreal factor = 1/64.;
@@ -461,22 +462,32 @@ void QFreetypeFace::addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoi
int i = 0;
for (int j = 0; j < g->outline.n_contours; ++j) {
int last_point = g->outline.contours[j];
- QPointF start = cp + QPointF(g->outline.points[i].x*factor, -g->outline.points[i].y*factor);
- if(!(g->outline.tags[i] & 1)) {
- start += cp + QPointF(g->outline.points[last_point].x*factor, -g->outline.points[last_point].y*factor);
- start /= 2;
+ GLYPH2PATH_DEBUG() << "contour:" << i << "to" << last_point;
+ QPointF start = QPointF(g->outline.points[i].x*factor, -g->outline.points[i].y*factor);
+ if (!(g->outline.tags[i] & 1)) { // start point is not on curve:
+ if (!(g->outline.tags[last_point] & 1)) { // end point is not on curve:
+ GLYPH2PATH_DEBUG() << " start and end point are not on curve";
+ start = (QPointF(g->outline.points[last_point].x*factor,
+ -g->outline.points[last_point].y*factor) + start) / 2.0;
+ } else {
+ GLYPH2PATH_DEBUG() << " end point is on curve, start is not";
+ start = QPointF(g->outline.points[last_point].x*factor,
+ -g->outline.points[last_point].y*factor);
+ }
+ --i; // to use original start point as control point below
}
-// qDebug("contour: %d -- %d", i, g->outline.contours[j]);
-// qDebug("first point at %f %f", start.x(), start.y());
- path->moveTo(start);
+ start += cp;
+ GLYPH2PATH_DEBUG() << " start at" << start;
+ path->moveTo(start);
QPointF c[4];
c[0] = start;
int n = 1;
while (i < last_point) {
++i;
c[n] = cp + QPointF(g->outline.points[i].x*factor, -g->outline.points[i].y*factor);
-// qDebug() << " i=" << i << " flag=" << (int)g->outline.tags[i] << "point=" << c[n];
+ GLYPH2PATH_DEBUG() << " " << i << c[n] << "tag =" << (int)g->outline.tags[i]
+ << ": on curve =" << (bool)(g->outline.tags[i] & 1);
++n;
switch (g->outline.tags[i] & 3) {
case 2:
@@ -498,7 +509,7 @@ void QFreetypeFace::addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoi
case 1:
case 3:
if (n == 2) {
-// qDebug() << "lineTo" << c[1];
+ GLYPH2PATH_DEBUG() << " lineTo" << c[1];
path->lineTo(c[1]);
c[0] = c[1];
n = 1;
@@ -510,13 +521,14 @@ void QFreetypeFace::addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoi
}
break;
}
-// qDebug() << "cubicTo" << c[1] << c[2] << c[3];
+ GLYPH2PATH_DEBUG() << " cubicTo" << c[1] << c[2] << c[3];
path->cubicTo(c[1], c[2], c[3]);
c[0] = c[3];
n = 1;
}
+
if (n == 1) {
-// qDebug() << "closeSubpath";
+ GLYPH2PATH_DEBUG() << " closeSubpath";
path->closeSubpath();
} else {
c[3] = start;
@@ -524,7 +536,7 @@ void QFreetypeFace::addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoi
c[2] = (2*c[1] + c[3])/3;
c[1] = (2*c[1] + c[0])/3;
}
-// qDebug() << "cubicTo" << c[1] << c[2] << c[3];
+ GLYPH2PATH_DEBUG() << " close cubicTo" << c[1] << c[2] << c[3];
path->cubicTo(c[1], c[2], c[3]);
}
++i;
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index 5e40abbda6..fc849d788f 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -251,6 +251,8 @@ public:
static QByteArray convertToPostscriptFontFamilyName(const QByteArray &fontFamily);
+ virtual bool hasUnreliableGlyphOutline() const;
+
enum HintStyle {
HintNone,
HintLight,
diff --git a/src/gui/text/qtextcursor.cpp b/src/gui/text/qtextcursor.cpp
index ac9762b183..731b6adde8 100644
--- a/src/gui/text/qtextcursor.cpp
+++ b/src/gui/text/qtextcursor.cpp
@@ -132,7 +132,7 @@ QTextCursorPrivate::AdjustResult QTextCursorPrivate::adjustPosition(int position
void QTextCursorPrivate::setX()
{
- if (priv->isInEditBlock()) {
+ if (priv->isInEditBlock() || priv->inContentsChange) {
x = -1; // mark dirty
return;
}
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 34788dc4dc..67dedca760 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -2057,7 +2057,7 @@ void QTextEngine::justify(const QScriptLine &line)
// subtract one char more, as we can't justfy after the last character
--line_length;
- if (!line_length)
+ if (line_length <= 0)
return;
int firstItem = findItem(line.from);
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index b8f76f8d4f..bead45ab83 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -509,7 +509,7 @@ static QByteArray qt_prettyDebug(const char *data, int len, int maxLength)
{
if (!data) return "(null)";
QByteArray out;
- for (int i = 0; i < len; ++i) {
+ for (int i = 0; i < qMin(len, maxLength); ++i) {
char c = data[i];
if (isprint(int(uchar(c)))) {
out += c;
diff --git a/src/platformsupport/eglconvenience/qeglplatformcursor.cpp b/src/platformsupport/eglconvenience/qeglplatformcursor.cpp
index 70e7c4e4db..e99581183e 100644
--- a/src/platformsupport/eglconvenience/qeglplatformcursor.cpp
+++ b/src/platformsupport/eglconvenience/qeglplatformcursor.cpp
@@ -69,7 +69,8 @@ QEGLPlatformCursor::QEGLPlatformCursor(QPlatformScreen *screen)
m_vertexCoordEntry(0),
m_textureCoordEntry(0),
m_textureEntry(0),
- m_deviceListener(0)
+ m_deviceListener(0),
+ m_updater(screen)
{
QByteArray hideCursorVal = qgetenv("QT_QPA_EGLFS_HIDECURSOR");
if (!hideCursorVal.isEmpty())
@@ -270,12 +271,32 @@ bool QEGLPlatformCursor::setCurrentCursor(QCursor *cursor)
}
#endif
-void QEGLPlatformCursor::update(const QRegion &rgn)
+void QEGLPlatformCursorUpdater::update(const QPoint &pos, const QRegion &rgn)
{
- QWindowSystemInterface::handleExposeEvent(m_screen->topLevelAt(m_cursor.pos), rgn);
+ m_active = false;
+ QWindowSystemInterface::handleExposeEvent(m_screen->topLevelAt(pos), rgn);
QWindowSystemInterface::flushWindowSystemEvents();
}
+void QEGLPlatformCursorUpdater::scheduleUpdate(const QPoint &pos, const QRegion &rgn)
+{
+ if (m_active)
+ return;
+
+ m_active = true;
+
+ // Must not flush the window system events directly from here since we are likely to
+ // be a called directly from QGuiApplication's processMouseEvents. Flushing events
+ // could cause reentering by dispatching more queued mouse events.
+ QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection,
+ Q_ARG(QPoint, pos), Q_ARG(QRegion, rgn));
+}
+
+void QEGLPlatformCursor::update(const QRegion &rgn)
+{
+ m_updater.scheduleUpdate(m_cursor.pos, rgn);
+}
+
QRect QEGLPlatformCursor::cursorRect() const
{
return QRect(m_cursor.pos - m_cursor.hotSpot, m_cursor.size);
diff --git a/src/platformsupport/eglconvenience/qeglplatformcursor_p.h b/src/platformsupport/eglconvenience/qeglplatformcursor_p.h
index c9ff9a1198..6f4216874a 100644
--- a/src/platformsupport/eglconvenience/qeglplatformcursor_p.h
+++ b/src/platformsupport/eglconvenience/qeglplatformcursor_p.h
@@ -68,6 +68,24 @@ private:
int m_mouseCount;
};
+class QEGLPlatformCursorUpdater : public QObject
+{
+ Q_OBJECT
+
+public:
+ QEGLPlatformCursorUpdater(QPlatformScreen *screen)
+ : m_screen(screen), m_active(false) { }
+
+ void scheduleUpdate(const QPoint &pos, const QRegion &rgn);
+
+private slots:
+ void update(const QPoint &pos, const QRegion &rgn);
+
+private:
+ QPlatformScreen *m_screen;
+ bool m_active;
+};
+
class QEGLPlatformCursor : public QPlatformCursor
{
public:
@@ -130,6 +148,7 @@ private:
int m_textureCoordEntry;
int m_textureEntry;
QEGLPlatformCursorDeviceListener *m_deviceListener;
+ QEGLPlatformCursorUpdater m_updater;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp
index b987c49c9c..a38741cc91 100644
--- a/src/plugins/platforms/android/androidjniaccessibility.cpp
+++ b/src/plugins/platforms/android/androidjniaccessibility.cpp
@@ -50,7 +50,7 @@
#include "qdebug.h"
-static const char m_qtTag[] = "QtA11y";
+static const char m_qtTag[] = "Qt A11Y";
static const char m_classErrorMsg[] = "Can't find class \"%s\"";
static const char m_methodErrorMsg[] = "Can't find method \"%s%s\"";
@@ -184,8 +184,6 @@ if (!clazz) { \
desc = iface->text(QAccessible::Name);
if (desc.isEmpty())
desc = iface->text(QAccessible::Description);
-
- desc += QChar(' ') + QString::fromUtf8(qAccessibleRoleString(iface->role()));
}
jstring jdesc = env->NewString((jchar*) desc.constData(), (jsize) desc.size());
@@ -216,12 +214,6 @@ if (!clazz) { \
}
}
- if ((iface->role() != QAccessible::NoRole) &&
- (iface->role() != QAccessible::Client) &&
- (iface->role() != QAccessible::Pane)) {
- desc += QChar(' ') + QString::fromUtf8(qAccessibleRoleString(iface->role()));
- }
-
CALL_METHOD(node, "setEnabled", "(Z)V", !state.disabled)
//CALL_METHOD(node, "setFocusable", "(Z)V", state.focusable)
CALL_METHOD(node, "setFocusable", "(Z)V", true)
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp
index ff1a40bfc5..2998762cc3 100644
--- a/src/plugins/platforms/android/androidjnimain.cpp
+++ b/src/plugins/platforms/android/androidjnimain.cpp
@@ -769,7 +769,6 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/)
|| !QtAndroidInput::registerNatives(env)
|| !QtAndroidClipboard::registerNatives(env)
|| !QtAndroidMenu::registerNatives(env)
- || !QtAndroidAccessibility::registerNatives(env)
|| !QtAndroidDialogHelpers::registerNatives(env)) {
__android_log_print(ANDROID_LOG_FATAL, "Qt", "registerNatives failed");
return -1;
diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp
index e255a49ac7..c2e5f83639 100644
--- a/src/plugins/platforms/android/qandroidinputcontext.cpp
+++ b/src/plugins/platforms/android/qandroidinputcontext.cpp
@@ -591,19 +591,37 @@ jboolean QAndroidInputContext::endBatchEdit()
return JNI_TRUE;
}
-jboolean QAndroidInputContext::commitText(const QString &text, jint /*newCursorPosition*/)
+/*
+ Android docs say: If composing, replace compose text with \a text.
+ Otherwise insert \a text at current cursor position.
+
+ The cursor should then be moved to newCursorPosition. If > 0, this is
+ relative to the end of the text - 1; if <= 0, this is relative to the start
+ of the text. updateSelection() needs to be called.
+*/
+jboolean QAndroidInputContext::commitText(const QString &text, jint newCursorPosition)
{
- QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
- if (query.isNull())
- return JNI_FALSE;
+ QInputMethodEvent event;
+ event.setCommitString(text);
+ sendInputMethodEvent(&event);
+ clear();
+ // Qt has now put the cursor at the end of the text, corresponding to newCursorPosition == 1
+ if (newCursorPosition != 1) {
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
+ if (!query.isNull()) {
+ QList<QInputMethodEvent::Attribute> attributes;
+ const int localPos = query->value(Qt::ImCursorPosition).toInt();
+ const int newLocalPos = newCursorPosition > 0
+ ? localPos + newCursorPosition - 1
+ : localPos - text.length() + newCursorPosition;
+ //move the cursor
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection,
+ newLocalPos, 0, QVariant()));
+ }
+ }
- const int cursorPos = getAbsoluteCursorPosition(query);
- m_composingText = text;
- m_composingTextStart = cursorPos;
- m_composingCursor = cursorPos + text.length();
- finishComposingText();
- //### move cursor to newCursorPosition and call updateCursorPosition()
+ updateCursorPosition();
return JNI_TRUE;
}
@@ -624,9 +642,24 @@ jboolean QAndroidInputContext::deleteSurroundingText(jint leftLength, jint right
return JNI_TRUE;
}
+// Android docs say the cursor must not move
jboolean QAndroidInputContext::finishComposingText()
{
- QInputMethodEvent event;
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
+ if (query.isNull())
+ return JNI_FALSE;
+
+ if (m_composingText.isEmpty())
+ return JNI_TRUE; // not composing
+
+ const int blockPos = getBlockPosition(query);
+ const int localCursorPos = m_composingCursor - blockPos;
+
+ // Moving Qt's cursor to where the preedit cursor used to be
+ QList<QInputMethodEvent::Attribute> attributes;
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection, localCursorPos, 0, QVariant()));
+
+ QInputMethodEvent event(QString(), attributes);
event.setCommitString(m_composingText);
sendInputMethodEvent(&event);
clear();
diff --git a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm
index dc22da0983..a18f721e04 100644
--- a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm
@@ -92,16 +92,20 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont)
QFont newFont;
if (cocoaFont) {
int pSize = qRound([cocoaFont pointSize]);
- CTFontDescriptorRef font = CTFontCopyFontDescriptor((CTFontRef)cocoaFont);
- // QCoreTextFontDatabase::populateFontDatabase() is using localized names
- QString family = QCFString::toQString((CFStringRef) CTFontDescriptorCopyLocalizedAttribute(font, kCTFontFamilyNameAttribute, NULL));
- QString style = QCFString::toQString((CFStringRef) CTFontDescriptorCopyLocalizedAttribute(font, kCTFontStyleNameAttribute, NULL));
+ QString family(QCFString::toQString([cocoaFont familyName]));
+ QString typeface(QCFString::toQString([cocoaFont fontName]));
+
+ int hyphenPos = typeface.indexOf(QLatin1Char('-'));
+ if (hyphenPos != -1) {
+ typeface.remove(0, hyphenPos + 1);
+ } else {
+ typeface = QLatin1String("Normal");
+ }
- newFont = QFontDatabase().font(family, style, pSize);
+ newFont = QFontDatabase().font(family, typeface, pSize);
newFont.setUnderline(resolveFont.underline());
newFont.setStrikeOut(resolveFont.strikeOut());
- CFRelease(font);
}
return newFont;
}
diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm
index 44bc3b8f69..a89979a8ea 100644
--- a/src/plugins/platforms/cocoa/qcocoamenu.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenu.mm
@@ -234,6 +234,10 @@ QCocoaMenu::QCocoaMenu() :
QCocoaMenu::~QCocoaMenu()
{
+ foreach (QCocoaMenuItem *item, m_menuItems) {
+ if (COCOA_MENU_ANCESTOR(item) == this)
+ SET_COCOA_MENU_ANCESTOR(item, 0);
+ }
QCocoaAutoReleasePool pool;
[m_nativeItem setSubmenu:nil];
[m_nativeMenu release];
diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
index 99d26034bf..9e748bff72 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
@@ -106,6 +106,8 @@ QCocoaMenuItem::QCocoaMenuItem() :
QCocoaMenuItem::~QCocoaMenuItem()
{
+ if (m_menu && COCOA_MENU_ANCESTOR(m_menu) == this)
+ SET_COCOA_MENU_ANCESTOR(m_menu, 0);
if (m_merged) {
[m_native setHidden:YES];
} else {
diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm
index 57d5c800e0..7322025df6 100644
--- a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm
+++ b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm
@@ -463,7 +463,11 @@ bool QCocoaPrintDevice::openPpdFile()
ppdClose(m_ppd);
m_ppd = 0;
CFURLRef ppdURL = NULL;
+#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
+ char ppdPath[PATH_MAX];
+#else
char ppdPath[MAXPATHLEN];
+#endif
if (PMPrinterCopyDescriptionURL(m_printer, kPMPPDDescriptionType, &ppdURL) == noErr
&& ppdURL != NULL
&& CFURLGetFileSystemRepresentation(ppdURL, true, (UInt8*)ppdPath, sizeof(ppdPath))) {
diff --git a/src/plugins/platforms/direct2d/direct2d.pro b/src/plugins/platforms/direct2d/direct2d.pro
index 439d31fb56..03997f2737 100644
--- a/src/plugins/platforms/direct2d/direct2d.pro
+++ b/src/plugins/platforms/direct2d/direct2d.pro
@@ -9,7 +9,7 @@ QT *= core-private
QT *= gui-private
QT *= platformsupport-private
-LIBS *= -ld2d1 -ld3d11 -ldwrite
+LIBS *= -ld2d1 -ld3d11 -ldwrite -lVersion
include(../windows/windows.pri)
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp
index e4ce81bd24..be013f027b 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -66,6 +66,16 @@ static inline QWindowsDirect2DPlatformPixmap *platformPixmap(QPixmap *p)
return static_cast<QWindowsDirect2DPlatformPixmap *>(p->handle());
}
+static inline QWindowsDirect2DBitmap *bitmap(QPixmap *p)
+{
+ return platformPixmap(p)->bitmap();
+}
+
+static inline QWindowsDirect2DWindow *nativeWindow(QWindow *window)
+{
+ return static_cast<QWindowsDirect2DWindow *>(window->handle());
+}
+
QWindowsDirect2DBackingStore::QWindowsDirect2DBackingStore(QWindow *window)
: QPlatformBackingStore(window)
{
@@ -77,36 +87,40 @@ QWindowsDirect2DBackingStore::~QWindowsDirect2DBackingStore()
void QWindowsDirect2DBackingStore::beginPaint(const QRegion &)
{
- platformPixmap(m_pixmap.data())->bitmap()->deviceContext()->begin();
+ bitmap(nativeWindow(window())->pixmap())->deviceContext()->begin();
}
void QWindowsDirect2DBackingStore::endPaint()
{
- platformPixmap(m_pixmap.data())->bitmap()->deviceContext()->end();
+ bitmap(nativeWindow(window())->pixmap())->deviceContext()->end();
}
QPaintDevice *QWindowsDirect2DBackingStore::paintDevice()
{
- return m_pixmap.data();
+ return nativeWindow(window())->pixmap();
}
-void QWindowsDirect2DBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
+void QWindowsDirect2DBackingStore::flush(QWindow *targetWindow, const QRegion &region, const QPoint &offset)
{
- QPlatformWindow *pw = window->handle();
- if (pw && m_pixmap)
- static_cast<QWindowsDirect2DWindow *>(pw)->flush(platformPixmap(m_pixmap.data())->bitmap(), region, offset);
+ if (targetWindow != window()) {
+ QSharedPointer<QWindowsDirect2DBitmap> copy(nativeWindow(window())->copyBackBuffer());
+ nativeWindow(targetWindow)->flush(copy.data(), region, offset);
+ }
+
+ nativeWindow(targetWindow)->present();
}
void QWindowsDirect2DBackingStore::resize(const QSize &size, const QRegion &region)
{
- Q_UNUSED(region);
+ QPixmap old = nativeWindow(window())->pixmap()->copy();
- QScopedPointer<QPixmap> oldPixmap(m_pixmap.take());
- m_pixmap.reset(new QPixmap(size.width(), size.height()));
+ nativeWindow(window())->resizeSwapChain(size);
+ QPixmap *newPixmap = nativeWindow(window())->pixmap();
- if (oldPixmap) {
- foreach (const QRect &rect, region.rects())
- platformPixmap(m_pixmap.data())->copy(oldPixmap->handle(), rect);
+ if (!old.isNull()) {
+ foreach (const QRect &rect, region.rects()) {
+ platformPixmap(newPixmap)->copy(old.handle(), rect);
+ }
}
}
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h
index fc6802aaa2..71e9437274 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -50,6 +50,8 @@
QT_BEGIN_NAMESPACE
+class QWindowsDirect2DWindow;
+
class QWindowsDirect2DBackingStore : public QPlatformBackingStore
{
Q_DISABLE_COPY(QWindowsDirect2DBackingStore)
@@ -62,11 +64,8 @@ public:
void endPaint();
QPaintDevice *paintDevice() Q_DECL_OVERRIDE;
- void flush(QWindow *window, const QRegion &region, const QPoint &offset) Q_DECL_OVERRIDE;
+ void flush(QWindow *targetWindow, const QRegion &region, const QPoint &offset) Q_DECL_OVERRIDE;
void resize(const QSize &size, const QRegion &staticContents) Q_DECL_OVERRIDE;
-
-private:
- QScopedPointer<QPixmap> m_pixmap;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dcontext.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dcontext.cpp
index 58002fb0dd..80688a1da7 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dcontext.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dcontext.cpp
@@ -99,7 +99,7 @@ public:
return false;
}
- hr = dxgiDevice->GetParent(IID_PPV_ARGS(&dxgiAdapter));
+ hr = dxgiDevice->GetAdapter(&dxgiAdapter);
if (FAILED(hr)) {
qWarning("%s: Failed to probe DXGI Device for parent DXGI Adapter: %#x", __FUNCTION__, hr);
return false;
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp
index 1a26d7029e..44fc7aa927 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp
@@ -48,7 +48,8 @@
#include "qwindowscontext.h"
-#include <QtCore/QDebug>
+#include <qplatformdefs.h>
+#include <QtCore/QCoreApplication>
#include <QtGui/private/qpixmap_raster_p.h>
#include <QtGui/qpa/qwindowsysteminterface.h>
@@ -61,8 +62,140 @@ public:
QWindowsDirect2DContext m_d2dContext;
};
+class Direct2DVersion
+{
+private:
+ Direct2DVersion()
+ : partOne(0)
+ , partTwo(0)
+ , partThree(0)
+ , partFour(0)
+ {}
+
+ Direct2DVersion(int one, int two, int three, int four)
+ : partOne(one)
+ , partTwo(two)
+ , partThree(three)
+ , partFour(four)
+ {}
+
+public:
+ // 6.2.9200.16765 corresponds to Direct2D 1.1 on Windows 7 SP1 with Platform Update
+ enum {
+ D2DMinVersionPart1 = 6,
+ D2DMinVersionPart2 = 2,
+ D2DMinVersionPart3 = 9200,
+ D2DMinVersionPart4 = 16765
+ };
+
+ static Direct2DVersion systemVersion() {
+ static const int bufSize = 512;
+ TCHAR filename[bufSize];
+
+ UINT i = GetSystemDirectory(filename, bufSize);
+ if (i > 0 && i < MAX_PATH) {
+ if (_tcscat_s(filename, MAX_PATH, __TEXT("\\d2d1.dll")) == 0) {
+ DWORD versionInfoSize = GetFileVersionInfoSize(filename, NULL);
+ if (versionInfoSize) {
+ QVector<BYTE> info(versionInfoSize);
+ if (GetFileVersionInfo(filename, NULL, versionInfoSize, info.data())) {
+ UINT size;
+ DWORD *fi;
+
+ if (VerQueryValue(info.constData(), __TEXT("\\"), (LPVOID *) &fi, &size) && size) {
+ VS_FIXEDFILEINFO *verInfo = (VS_FIXEDFILEINFO *) fi;
+ return Direct2DVersion(HIWORD(verInfo->dwFileVersionMS),
+ LOWORD(verInfo->dwFileVersionMS),
+ HIWORD(verInfo->dwFileVersionLS),
+ LOWORD(verInfo->dwFileVersionLS));
+ }
+ }
+ }
+ }
+ }
+
+ return Direct2DVersion();
+ }
+
+ static Direct2DVersion minimumVersion() {
+ return Direct2DVersion(D2DMinVersionPart1,
+ D2DMinVersionPart2,
+ D2DMinVersionPart3,
+ D2DMinVersionPart4);
+ }
+
+ bool isValid() const {
+ return partOne || partTwo || partThree || partFour;
+ }
+
+ bool operator<(const Direct2DVersion &other) {
+ int c = cmp(partOne, other.partOne);
+ if (c > 0)
+ return false;
+ if (c < 0)
+ return true;
+
+ c = cmp(partTwo, other.partTwo);
+ if (c > 0)
+ return false;
+ if (c < 0)
+ return true;
+
+ c = cmp(partThree, other.partThree);
+ if (c > 0)
+ return false;
+ if (c < 0)
+ return true;
+
+ c = cmp(partFour, other.partFour);
+ if (c > 0)
+ return false;
+ if (c < 0)
+ return true;
+
+ return false;
+ }
+
+ static Q_DECL_CONSTEXPR int cmp(int a, int b) {
+ return a - b;
+ }
+
+ int partOne, partTwo, partThree, partFour;
+};
+
QWindowsDirect2DIntegration *QWindowsDirect2DIntegration::create(const QStringList &paramList)
{
+ Direct2DVersion systemVersion = Direct2DVersion::systemVersion();
+
+ if (systemVersion.isValid() && systemVersion < Direct2DVersion::minimumVersion()) {
+ QString msg = QCoreApplication::translate("QWindowsDirect2DIntegration",
+ "Qt cannot load the direct2d platform plugin because " \
+ "the Direct2D version on this system is too old. The " \
+ "minimum system requirement for this platform plugin " \
+ "is Windows 7 SP1 with Platform Update.\n\n" \
+ "The minimum Direct2D version required is %1.%2.%3.%4. " \
+ "The Direct2D version on this system is %5.%6.%7.%8.");
+
+ msg = msg.arg(Direct2DVersion::D2DMinVersionPart1)
+ .arg(Direct2DVersion::D2DMinVersionPart2)
+ .arg(Direct2DVersion::D2DMinVersionPart3)
+ .arg(Direct2DVersion::D2DMinVersionPart4)
+ .arg(systemVersion.partOne)
+ .arg(systemVersion.partTwo)
+ .arg(systemVersion.partThree)
+ .arg(systemVersion.partFour);
+
+ QString caption = QCoreApplication::translate("QWindowsDirect2DIntegration",
+ "Cannot load direct2d platform plugin");
+
+ MessageBoxW(NULL,
+ msg.toStdWString().c_str(),
+ caption.toStdWString().c_str(),
+ MB_OK | MB_ICONERROR);
+
+ return Q_NULLPTR;
+ }
+
QWindowsDirect2DIntegration *integration = new QWindowsDirect2DIntegration(paramList);
if (!integration->init()) {
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
index 58c30b6eeb..6e8d9b0baf 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
@@ -58,7 +58,6 @@
#include <QtGui/private/qfontengine_p.h>
#include <QtGui/private/qstatictext_p.h>
-#include <wrl.h>
using Microsoft::WRL::ComPtr;
QT_BEGIN_NAMESPACE
@@ -346,6 +345,8 @@ public:
QPointF currentBrushOrigin;
+ QHash< QFont, ComPtr<IDWriteFontFace> > fontCache;
+
struct {
bool emulate;
QPen qpen;
@@ -1291,44 +1292,6 @@ void QWindowsDirect2DPaintEngine::drawPixmap(const QRectF &r,
}
}
-static ComPtr<IDWriteFontFace> fontFaceFromFontEngine(QFontEngine *fe)
-{
- ComPtr<IDWriteFontFace> fontFace;
-
- switch (fe->type()) {
- case QFontEngine::Win:
- {
- QWindowsFontEngine *wfe = static_cast<QWindowsFontEngine *>(fe);
- QSharedPointer<QWindowsFontEngineData> wfed = wfe->fontEngineData();
-
- HGDIOBJ oldfont = wfe->selectDesignFont();
- HRESULT hr = QWindowsDirect2DContext::instance()->dwriteGdiInterop()->CreateFontFaceFromHdc(wfed->hdc, &fontFace);
- DeleteObject(SelectObject(wfed->hdc, oldfont));
- if (FAILED(hr))
- qWarning("%s: Could not create DirectWrite fontface from HDC: %#x", __FUNCTION__, hr);
-
- }
- break;
-
-#ifndef QT_NO_DIRECTWRITE
-
- case QFontEngine::DirectWrite:
- {
- QWindowsFontEngineDirectWrite *wfedw = static_cast<QWindowsFontEngineDirectWrite *>(fe);
- fontFace = wfedw->directWriteFontFace();
- }
- break;
-
-#endif // QT_NO_DIRECTWRITE
-
- default:
- qWarning("%s: Unknown font engine!", __FUNCTION__);
- break;
- }
-
- return fontFace;
-}
-
void QWindowsDirect2DPaintEngine::drawStaticTextItem(QStaticTextItem *staticTextItem)
{
Q_D(QWindowsDirect2DPaintEngine);
@@ -1340,24 +1303,22 @@ void QWindowsDirect2DPaintEngine::drawStaticTextItem(QStaticTextItem *staticText
ensurePen();
// If we can't support the current configuration with Direct2D, fall back to slow path
- // Most common cases are perspective transform and gradient brush as pen
- if ((state()->transform().isAffine() == false) || d->pen.emulate) {
+ if (emulationRequired(PenEmulation)) {
QPaintEngineEx::drawStaticTextItem(staticTextItem);
return;
}
- ComPtr<IDWriteFontFace> fontFace = fontFaceFromFontEngine(staticTextItem->fontEngine());
+ ComPtr<IDWriteFontFace> fontFace = fontFaceFromFontEngine(staticTextItem->font, staticTextItem->fontEngine());
if (!fontFace) {
qWarning("%s: Could not find font - falling back to slow text rendering path.", __FUNCTION__);
QPaintEngineEx::drawStaticTextItem(staticTextItem);
return;
}
- QVector<UINT16> glyphIndices(staticTextItem->numGlyphs);
- QVector<FLOAT> glyphAdvances(staticTextItem->numGlyphs);
- QVector<DWRITE_GLYPH_OFFSET> glyphOffsets(staticTextItem->numGlyphs);
+ QVarLengthArray<UINT16> glyphIndices(staticTextItem->numGlyphs);
+ QVarLengthArray<FLOAT> glyphAdvances(staticTextItem->numGlyphs);
+ QVarLengthArray<DWRITE_GLYPH_OFFSET> glyphOffsets(staticTextItem->numGlyphs);
- // XXX Are we generating a lot of cache misses here?
for (int i = 0; i < staticTextItem->numGlyphs; i++) {
glyphIndices[i] = UINT16(staticTextItem->glyphs[i]); // Imperfect conversion here
@@ -1390,24 +1351,22 @@ void QWindowsDirect2DPaintEngine::drawTextItem(const QPointF &p, const QTextItem
ensurePen();
// If we can't support the current configuration with Direct2D, fall back to slow path
- // Most common cases are perspective transform and gradient brush as pen
- if ((state()->transform().isAffine() == false) || d->pen.emulate) {
+ if (emulationRequired(PenEmulation)) {
QPaintEngine::drawTextItem(p, textItem);
return;
}
- ComPtr<IDWriteFontFace> fontFace = fontFaceFromFontEngine(ti.fontEngine);
+ ComPtr<IDWriteFontFace> fontFace = fontFaceFromFontEngine(*ti.f, ti.fontEngine);
if (!fontFace) {
qWarning("%s: Could not find font - falling back to slow text rendering path.", __FUNCTION__);
QPaintEngine::drawTextItem(p, textItem);
return;
}
- QVector<UINT16> glyphIndices(ti.glyphs.numGlyphs);
- QVector<FLOAT> glyphAdvances(ti.glyphs.numGlyphs);
- QVector<DWRITE_GLYPH_OFFSET> glyphOffsets(ti.glyphs.numGlyphs);
+ QVarLengthArray<UINT16> glyphIndices(ti.glyphs.numGlyphs);
+ QVarLengthArray<FLOAT> glyphAdvances(ti.glyphs.numGlyphs);
+ QVarLengthArray<DWRITE_GLYPH_OFFSET> glyphOffsets(ti.glyphs.numGlyphs);
- // XXX Are we generating a lot of cache misses here?
for (int i = 0; i < ti.glyphs.numGlyphs; i++) {
glyphIndices[i] = UINT16(ti.glyphs.glyphs[i]); // Imperfect conversion here
glyphAdvances[i] = ti.glyphs.effectiveAdvance(i).toReal();
@@ -1618,4 +1577,49 @@ void QWindowsDirect2DPaintEngine::adjustForAliasing(QPointF *point)
(*point) += adjustment;
}
+Microsoft::WRL::ComPtr<IDWriteFontFace> QWindowsDirect2DPaintEngine::fontFaceFromFontEngine(const QFont &font, QFontEngine *fe)
+{
+ Q_D(QWindowsDirect2DPaintEngine);
+
+ ComPtr<IDWriteFontFace> fontFace = d->fontCache.value(font);
+ if (fontFace)
+ return fontFace;
+
+ switch (fe->type()) {
+ case QFontEngine::Win:
+ {
+ QWindowsFontEngine *wfe = static_cast<QWindowsFontEngine *>(fe);
+ QSharedPointer<QWindowsFontEngineData> wfed = wfe->fontEngineData();
+
+ HGDIOBJ oldfont = wfe->selectDesignFont();
+ HRESULT hr = QWindowsDirect2DContext::instance()->dwriteGdiInterop()->CreateFontFaceFromHdc(wfed->hdc, &fontFace);
+ DeleteObject(SelectObject(wfed->hdc, oldfont));
+ if (FAILED(hr))
+ qWarning("%s: Could not create DirectWrite fontface from HDC: %#x", __FUNCTION__, hr);
+
+ }
+ break;
+
+#ifndef QT_NO_DIRECTWRITE
+
+ case QFontEngine::DirectWrite:
+ {
+ QWindowsFontEngineDirectWrite *wfedw = static_cast<QWindowsFontEngineDirectWrite *>(fe);
+ fontFace = wfedw->directWriteFontFace();
+ }
+ break;
+
+#endif // QT_NO_DIRECTWRITE
+
+ default:
+ qWarning("%s: Unknown font engine!", __FUNCTION__);
+ break;
+ }
+
+ if (fontFace)
+ d->fontCache.insert(font, fontFace);
+
+ return fontFace;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h
index badd7a7688..fb9b7acec3 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h
@@ -47,6 +47,7 @@
#include <d2d1_1.h>
#include <dwrite_1.h>
+#include <wrl.h>
QT_BEGIN_NAMESPACE
@@ -114,6 +115,8 @@ private:
bool antiAliasingEnabled() const;
void adjustForAliasing(QRectF *rect);
void adjustForAliasing(QPointF *point);
+
+ Microsoft::WRL::ComPtr<IDWriteFontFace> fontFaceFromFontEngine(const QFont &font, QFontEngine *fe);
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp
index 072c4b3c0e..d9f7c595ca 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -56,12 +56,27 @@ class QWindowsDirect2DPlatformPixmapPrivate
{
public:
QWindowsDirect2DPlatformPixmapPrivate()
- : bitmap(new QWindowsDirect2DBitmap)
- , device(new QWindowsDirect2DPaintDevice(bitmap.data(), QInternal::Pixmap))
+ : owns_bitmap(true)
+ , bitmap(new QWindowsDirect2DBitmap)
+ , device(new QWindowsDirect2DPaintDevice(bitmap, QInternal::Pixmap))
, devicePixelRatio(1.0)
{}
- QScopedPointer<QWindowsDirect2DBitmap> bitmap;
+ QWindowsDirect2DPlatformPixmapPrivate(QWindowsDirect2DBitmap *bitmap)
+ : owns_bitmap(false)
+ , bitmap(bitmap)
+ , device(new QWindowsDirect2DPaintDevice(bitmap, QInternal::Pixmap))
+ , devicePixelRatio(1.0)
+ {}
+
+ ~QWindowsDirect2DPlatformPixmapPrivate()
+ {
+ if (owns_bitmap)
+ delete bitmap;
+ }
+
+ bool owns_bitmap;
+ QWindowsDirect2DBitmap *bitmap;
QScopedPointer<QWindowsDirect2DPaintDevice> device;
qreal devicePixelRatio;
};
@@ -75,6 +90,19 @@ QWindowsDirect2DPlatformPixmap::QWindowsDirect2DPlatformPixmap(PixelType pixelTy
setSerialNumber(qt_d2dpixmap_serno++);
}
+QWindowsDirect2DPlatformPixmap::QWindowsDirect2DPlatformPixmap(QPlatformPixmap::PixelType pixelType,
+ QWindowsDirect2DBitmap *bitmap)
+ : QPlatformPixmap(pixelType, Direct2DClass)
+ , d_ptr(new QWindowsDirect2DPlatformPixmapPrivate(bitmap))
+{
+ setSerialNumber(qt_d2dpixmap_serno++);
+
+ is_null = false;
+ w = bitmap->size().width();
+ h = bitmap->size().height();
+ this->d = 32;
+}
+
QWindowsDirect2DPlatformPixmap::~QWindowsDirect2DPlatformPixmap()
{
@@ -173,7 +201,7 @@ void QWindowsDirect2DPlatformPixmap::setDevicePixelRatio(qreal scaleFactor)
QWindowsDirect2DBitmap *QWindowsDirect2DPlatformPixmap::bitmap() const
{
Q_D(const QWindowsDirect2DPlatformPixmap);
- return d->bitmap.data();
+ return d->bitmap;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h
index e6684ea423..1936ef0622 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -55,6 +55,9 @@ class QWindowsDirect2DPlatformPixmap : public QPlatformPixmap
Q_DECLARE_PRIVATE(QWindowsDirect2DPlatformPixmap)
public:
QWindowsDirect2DPlatformPixmap(PixelType pixelType);
+
+ // We do NOT take ownership of the bitmap through this constructor!
+ QWindowsDirect2DPlatformPixmap(PixelType pixelType, QWindowsDirect2DBitmap *bitmap);
~QWindowsDirect2DPlatformPixmap();
virtual void resize(int width, int height);
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
index 50d0cb81f5..15ec0c3526 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
@@ -43,6 +43,7 @@
#include "qwindowsdirect2dwindow.h"
#include "qwindowsdirect2ddevicecontext.h"
#include "qwindowsdirect2dhelpers.h"
+#include "qwindowsdirect2dplatformpixmap.h"
#include <d3d11.h>
#include <d2d1_1.h>
@@ -87,6 +88,13 @@ QWindowsDirect2DWindow::~QWindowsDirect2DWindow()
{
}
+QPixmap *QWindowsDirect2DWindow::pixmap()
+{
+ setupBitmap();
+
+ return m_pixmap.data();
+}
+
void QWindowsDirect2DWindow::flush(QWindowsDirect2DBitmap *bitmap, const QRegion &region, const QPoint &offset)
{
DXGI_SWAP_CHAIN_DESC1 desc;
@@ -102,32 +110,38 @@ void QWindowsDirect2DWindow::flush(QWindowsDirect2DBitmap *bitmap, const QRegion
if (!m_bitmap)
return;
- m_bitmap->deviceContext()->begin();
-
- ID2D1DeviceContext *dc = m_bitmap->deviceContext()->get();
- if (!m_needsFullFlush) {
- QRegion clipped = region;
- clipped &= QRect(0, 0, desc.Width, desc.Height);
-
- foreach (const QRect &rect, clipped.rects()) {
- QRectF rectF(rect);
+ if (bitmap != m_bitmap.data()) {
+ m_bitmap->deviceContext()->begin();
+
+ ID2D1DeviceContext *dc = m_bitmap->deviceContext()->get();
+ if (!m_needsFullFlush) {
+ QRegion clipped = region;
+ clipped &= QRect(0, 0, desc.Width, desc.Height);
+
+ foreach (const QRect &rect, clipped.rects()) {
+ QRectF rectF(rect);
+ dc->DrawBitmap(bitmap->bitmap(),
+ to_d2d_rect_f(rectF),
+ 1.0,
+ D2D1_INTERPOLATION_MODE_LINEAR,
+ to_d2d_rect_f(rectF.translated(offset.x(), offset.y())));
+ }
+ } else {
+ QRectF rectF(0, 0, desc.Width, desc.Height);
dc->DrawBitmap(bitmap->bitmap(),
to_d2d_rect_f(rectF),
1.0,
D2D1_INTERPOLATION_MODE_LINEAR,
to_d2d_rect_f(rectF.translated(offset.x(), offset.y())));
+ m_needsFullFlush = false;
}
- } else {
- QRectF rectF(0, 0, desc.Width, desc.Height);
- dc->DrawBitmap(bitmap->bitmap(),
- to_d2d_rect_f(rectF),
- 1.0,
- D2D1_INTERPOLATION_MODE_LINEAR,
- to_d2d_rect_f(rectF.translated(offset.x(), offset.y())));
- m_needsFullFlush = false;
+
+ m_bitmap->deviceContext()->end();
}
+}
- m_bitmap->deviceContext()->end();
+void QWindowsDirect2DWindow::present()
+{
m_swapChain->Present(0, 0);
}
@@ -136,6 +150,7 @@ void QWindowsDirect2DWindow::resizeSwapChain(const QSize &size)
if (!m_swapChain)
return;
+ m_pixmap.reset();
m_bitmap.reset();
m_deviceContext->SetTarget(Q_NULLPTR);
@@ -149,6 +164,43 @@ void QWindowsDirect2DWindow::resizeSwapChain(const QSize &size)
m_needsFullFlush = true;
}
+QSharedPointer<QWindowsDirect2DBitmap> QWindowsDirect2DWindow::copyBackBuffer() const
+{
+ const QSharedPointer<QWindowsDirect2DBitmap> null_result;
+
+ if (!m_bitmap)
+ return null_result;
+
+ D2D1_PIXEL_FORMAT format = m_bitmap->bitmap()->GetPixelFormat();
+ D2D1_SIZE_U size = m_bitmap->bitmap()->GetPixelSize();
+
+ FLOAT dpiX, dpiY;
+ m_bitmap->bitmap()->GetDpi(&dpiX, &dpiY);
+
+ D2D1_BITMAP_PROPERTIES1 properties = {
+ format, // D2D1_PIXEL_FORMAT pixelFormat;
+ dpiX, // FLOAT dpiX;
+ dpiY, // FLOAT dpiY;
+ D2D1_BITMAP_OPTIONS_TARGET, // D2D1_BITMAP_OPTIONS bitmapOptions;
+ Q_NULLPTR // _Field_size_opt_(1) ID2D1ColorContext *colorContext;
+ };
+ ComPtr<ID2D1Bitmap1> copy;
+ HRESULT hr = m_deviceContext.Get()->CreateBitmap(size, NULL, 0, properties, &copy);
+
+ if (FAILED(hr)) {
+ qWarning("%s: Could not create staging bitmap: %#x", __FUNCTION__, hr);
+ return null_result;
+ }
+
+ hr = copy.Get()->CopyFromBitmap(NULL, m_bitmap->bitmap(), NULL);
+ if (FAILED(hr)) {
+ qWarning("%s: Could not copy from bitmap! %#x", __FUNCTION__, hr);
+ return null_result;
+ }
+
+ return QSharedPointer<QWindowsDirect2DBitmap>(new QWindowsDirect2DBitmap(copy.Get(), Q_NULLPTR));
+}
+
void QWindowsDirect2DWindow::setupBitmap()
{
if (m_bitmap)
@@ -175,6 +227,10 @@ void QWindowsDirect2DWindow::setupBitmap()
}
m_bitmap.reset(new QWindowsDirect2DBitmap(backBufferBitmap.Get(), m_deviceContext.Get()));
+
+ QWindowsDirect2DPlatformPixmap *pp = new QWindowsDirect2DPlatformPixmap(QPlatformPixmap::PixmapType,
+ m_bitmap.data());
+ m_pixmap.reset(new QPixmap(pp));
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h
index 7996904639..47c790da5d 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h
@@ -56,16 +56,21 @@ public:
QWindowsDirect2DWindow(QWindow *window, const QWindowsWindowData &data);
~QWindowsDirect2DWindow();
+ QPixmap *pixmap();
void flush(QWindowsDirect2DBitmap *bitmap, const QRegion &region, const QPoint &offset);
+ void present();
+ void resizeSwapChain(const QSize &size);
+
+ QSharedPointer<QWindowsDirect2DBitmap> copyBackBuffer() const;
private:
- void resizeSwapChain(const QSize &size);
void setupBitmap();
private:
Microsoft::WRL::ComPtr<IDXGISwapChain1> m_swapChain;
Microsoft::WRL::ComPtr<ID2D1DeviceContext> m_deviceContext;
QScopedPointer<QWindowsDirect2DBitmap> m_bitmap;
+ QScopedPointer<QPixmap> m_pixmap;
bool m_needsFullFlush;
};
diff --git a/src/plugins/platforms/ios/qiosapplicationstate.mm b/src/plugins/platforms/ios/qiosapplicationstate.mm
index 8d77e608e5..afa3ecb21f 100644
--- a/src/plugins/platforms/ios/qiosapplicationstate.mm
+++ b/src/plugins/platforms/ios/qiosapplicationstate.mm
@@ -150,6 +150,7 @@
break;
}
QWindowSystemInterface::handleApplicationStateChanged(state);
+ QWindowSystemInterface::flushWindowSystemEvents();
}
@end
diff --git a/src/plugins/platforms/ios/qioswindow.h b/src/plugins/platforms/ios/qioswindow.h
index fc99543aa6..6b6892e6e4 100644
--- a/src/plugins/platforms/ios/qioswindow.h
+++ b/src/plugins/platforms/ios/qioswindow.h
@@ -88,6 +88,7 @@ public:
WId winId() const { return WId(m_view); };
private:
+ void applicationStateChanged(Qt::ApplicationState state);
void applyGeometry(const QRect &rect);
QUIView *m_view;
diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm
index 7d5c507972..6f5c96cfc1 100644
--- a/src/plugins/platforms/ios/qioswindow.mm
+++ b/src/plugins/platforms/ios/qioswindow.mm
@@ -192,12 +192,25 @@
- (void)displayLayer:(CALayer *)layer
{
- QSize bounds = fromCGRect(layer.bounds).toRect().size();
+ Q_UNUSED(layer);
+ Q_ASSERT(layer == self.layer);
- Q_ASSERT(m_qioswindow->geometry().size() == bounds);
- Q_ASSERT(self.hidden == !m_qioswindow->window()->isVisible());
+ [self sendUpdatedExposeEvent];
+}
+
+- (void)sendUpdatedExposeEvent
+{
+ QRegion region;
+
+ if (m_qioswindow->isExposed()) {
+ QSize bounds = fromCGRect(self.layer.bounds).toRect().size();
+
+ Q_ASSERT(m_qioswindow->geometry().size() == bounds);
+ Q_ASSERT(self.hidden == !m_qioswindow->window()->isVisible());
+
+ region = QRect(QPoint(), bounds);
+ }
- QRegion region = self.hidden ? QRegion() : QRect(QPoint(), bounds);
QWindowSystemInterface::handleExposeEvent(m_qioswindow->window(), region);
QWindowSystemInterface::flushWindowSystemEvents();
}
@@ -279,19 +292,33 @@
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
- if (!touches && m_activeTouches.isEmpty())
+ if (m_activeTouches.isEmpty())
return;
- if (!touches) {
- m_activeTouches.clear();
- } else {
- for (UITouch *touch in touches)
- m_activeTouches.remove(touch);
-
- Q_ASSERT_X(m_activeTouches.isEmpty(), Q_FUNC_INFO,
- "Subset of active touches cancelled by UIKit");
- }
-
+ // When four-finger swiping, we get a touchesCancelled callback
+ // which includes all four touch points. The swipe gesture is
+ // then active until all four touches have been released, and
+ // we start getting touchesBegan events again.
+
+ // When five-finger pinching, we also get a touchesCancelled
+ // callback with all five touch points, but the pinch gesture
+ // ends when the second to last finger is released from the
+ // screen. The last finger will not emit any more touch
+ // events, _but_, will contribute to starting another pinch
+ // gesture. That second pinch gesture will _not_ trigger a
+ // touchesCancelled event when starting, but as each finger
+ // is released, and we may get touchesMoved events for the
+ // remaining fingers. [event allTouches] also contains one
+ // less touch point than it should, so this behavior is
+ // likely a bug in the iOS system gesture recognizer, but we
+ // have to take it into account when maintaining the Qt state.
+ // We do this by assuming that there are no cases where a
+ // sub-set of the active touch events are intentionally cancelled.
+
+ if (touches && (static_cast<NSInteger>([touches count]) != m_activeTouches.count()))
+ qWarning("Subset of active touches cancelled by UIKit");
+
+ m_activeTouches.clear();
m_nextTouchId = 0;
NSTimeInterval timestamp = event ? event.timestamp : [[NSProcessInfo processInfo] systemUptime];
@@ -334,6 +361,8 @@ QIOSWindow::QIOSWindow(QWindow *window)
, m_view([[QUIView alloc] initWithQIOSWindow:this])
, m_windowLevel(0)
{
+ connect(qGuiApp, &QGuiApplication::applicationStateChanged, this, &QIOSWindow::applicationStateChanged);
+
setParent(QPlatformWindow::parent());
// Resolve default window geometry in case it was not set before creating the
@@ -471,7 +500,8 @@ void QIOSWindow::applyGeometry(const QRect &rect)
bool QIOSWindow::isExposed() const
{
- return window()->isVisible() && !window()->geometry().isEmpty();
+ return qApp->applicationState() > Qt::ApplicationHidden
+ && window()->isVisible() && !window()->geometry().isEmpty();
}
void QIOSWindow::setWindowState(Qt::WindowState state)
@@ -593,6 +623,12 @@ void QIOSWindow::handleContentOrientationChange(Qt::ScreenOrientation orientatio
[[UIApplication sharedApplication] setStatusBarOrientation:uiOrientation animated:NO];
}
+void QIOSWindow::applicationStateChanged(Qt::ApplicationState)
+{
+ if (window()->isExposed() != isExposed())
+ [m_view sendUpdatedExposeEvent];
+}
+
qreal QIOSWindow::devicePixelRatio() const
{
return m_view.contentScaleFactor;
diff --git a/src/plugins/platforms/kms/qkmsdevice.cpp b/src/plugins/platforms/kms/qkmsdevice.cpp
index 1e08c6f301..8e669fe7d5 100644
--- a/src/plugins/platforms/kms/qkmsdevice.cpp
+++ b/src/plugins/platforms/kms/qkmsdevice.cpp
@@ -85,8 +85,7 @@ QKmsDevice::~QKmsDevice()
void QKmsDevice::createScreens()
{
- drmModeRes *resources = 0;
- resources = drmModeGetResources(m_fd);
+ drmModeRes *resources = drmModeGetResources(m_fd);
if (!resources)
qFatal("drmModeGetResources failed");
@@ -95,7 +94,7 @@ void QKmsDevice::createScreens()
drmModeConnector *connector = 0;
connector = drmModeGetConnector(m_fd, resources->connectors[i]);
if (connector && connector->connection == DRM_MODE_CONNECTED) {
- m_integration->addScreen(new QKmsScreen(this, connector->connector_id));
+ m_integration->addScreen(new QKmsScreen(this, resources, connector));
}
drmModeFreeConnector(connector);
}
diff --git a/src/plugins/platforms/kms/qkmsscreen.cpp b/src/plugins/platforms/kms/qkmsscreen.cpp
index ad1a45b459..a930aa6545 100644
--- a/src/plugins/platforms/kms/qkmsscreen.cpp
+++ b/src/plugins/platforms/kms/qkmsscreen.cpp
@@ -63,18 +63,18 @@ static drmModeModeInfo builtin_1024x768 = {
"1024x768"
};
-QKmsScreen::QKmsScreen(QKmsDevice *device, int connectorId)
+QKmsScreen::QKmsScreen(QKmsDevice *device, const drmModeRes *resources, const drmModeConnector *connector)
: m_device(device),
m_current_bo(0),
m_next_bo(0),
- m_connectorId(connectorId),
+ m_connectorId(connector->connector_id),
m_depth(32),
m_format(QImage::Format_Invalid),
m_eglWindowSurface(EGL_NO_SURFACE),
m_modeSet(false)
{
m_cursor = new QKmsCursor(this);
- initializeScreenMode();
+ initializeScreenMode(resources, connector);
}
QKmsScreen::~QKmsScreen()
@@ -114,14 +114,9 @@ QPlatformCursor *QKmsScreen::cursor() const
return m_cursor;
}
-void QKmsScreen::initializeScreenMode()
+void QKmsScreen::initializeScreenMode(const drmModeRes *resources, const drmModeConnector *connector)
{
//Determine optimal mode for screen
- drmModeRes *resources = drmModeGetResources(m_device->fd());
- if (!resources)
- qFatal("drmModeGetResources failed");
-
- drmModeConnector *connector = drmModeGetConnector(m_device->fd(), m_connectorId);
drmModeModeInfo *mode = 0;
for (int i = 0; i < connector->count_modes; ++i) {
if (connector->modes[i].type & DRM_MODE_TYPE_PREFERRED) {
@@ -129,8 +124,12 @@ void QKmsScreen::initializeScreenMode()
break;
}
}
- if (!mode)
- mode = &builtin_1024x768;
+ if (!mode) {
+ if (connector->count_modes > 0)
+ mode = &connector->modes[0];
+ else
+ mode = &builtin_1024x768;
+ }
drmModeEncoder *encoder = drmModeGetEncoder(m_device->fd(), connector->encoders[0]);
if (encoder == 0)
@@ -162,8 +161,6 @@ void QKmsScreen::initializeScreenMode()
qDebug() << "created gbm surface" << m_gbmSurface << m_mode.hdisplay << m_mode.vdisplay;
//Cleanup
drmModeFreeEncoder(encoder);
- drmModeFreeConnector(connector);
- drmModeFreeResources(resources);
}
QSurfaceFormat QKmsScreen::tweakFormat(const QSurfaceFormat &format)
diff --git a/src/plugins/platforms/kms/qkmsscreen.h b/src/plugins/platforms/kms/qkmsscreen.h
index 5ae5a1062b..1fa8dbb763 100644
--- a/src/plugins/platforms/kms/qkmsscreen.h
+++ b/src/plugins/platforms/kms/qkmsscreen.h
@@ -68,7 +68,7 @@ class QKmsContext;
class QKmsScreen : public QPlatformScreen
{
public:
- QKmsScreen(QKmsDevice *device, int connectorId);
+ QKmsScreen(QKmsDevice *device, const drmModeRes *resources, const drmModeConnector *connector);
~QKmsScreen();
QRect geometry() const;
@@ -94,7 +94,7 @@ public:
private:
void performPageFlip();
- void initializeScreenMode();
+ void initializeScreenMode(const drmModeRes *resources, const drmModeConnector *connector);
QKmsDevice *m_device;
gbm_bo *m_current_bo;
diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp
index 1abf447709..34a9c1df5f 100644
--- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp
+++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp
@@ -145,9 +145,8 @@ void QWindowsBackingStore::resize(const QSize &size, const QRegion &region)
<< " from: " << (m_image.isNull() ? QSize() : m_image->image().size());
}
#endif
- QImage::Format format = QWindowsNativeImage::systemFormat();
- if (format == QImage::Format_RGB32 && window()->format().hasAlpha())
- format = QImage::Format_ARGB32_Premultiplied;
+ const QImage::Format format = window()->format().hasAlpha() ?
+ QImage::Format_ARGB32_Premultiplied : QWindowsNativeImage::systemFormat();
QWindowsNativeImage *oldwni = m_image.data();
QWindowsNativeImage *newwni = new QWindowsNativeImage(size.width(), size.height(), format);
diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp
index 29c43fc7a5..6f97c8584b 100644
--- a/src/plugins/platforms/windows/qwindowsfontengine.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp
@@ -169,6 +169,20 @@ bool QWindowsFontEngine::hasCMapTable() const
return GetFontData(hdc, MAKE_TAG('c', 'm', 'a', 'p'), 0, 0, 0) != GDI_ERROR;
}
+bool QWindowsFontEngine::hasGlyfTable() const
+{
+ HDC hdc = m_fontEngineData->hdc;
+ SelectObject(hdc, hfont);
+ return GetFontData(hdc, MAKE_TAG('g', 'l', 'y', 'f'), 0, 0, 0) != GDI_ERROR;
+}
+
+bool QWindowsFontEngine::hasEbdtTable() const
+{
+ HDC hdc = m_fontEngineData->hdc;
+ SelectObject(hdc, hfont);
+ return GetFontData(hdc, MAKE_TAG('E', 'B', 'D', 'T'), 0, 0, 0) != GDI_ERROR;
+}
+
void QWindowsFontEngine::getCMap()
{
ttf = (bool)(tm.tmPitchAndFamily & TMPF_TRUETYPE) || hasCMapTable();
@@ -308,6 +322,8 @@ QWindowsFontEngine::QWindowsFontEngine(const QString &name,
userData.insert(QStringLiteral("hFont"), QVariant::fromValue(hfont));
userData.insert(QStringLiteral("trueType"), QVariant(bool(ttf)));
setUserData(userData);
+
+ hasUnreliableOutline = hasGlyfTable() && hasEbdtTable();
}
QWindowsFontEngine::~QWindowsFontEngine()
@@ -662,6 +678,11 @@ void QWindowsFontEngine::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qre
}
#endif // Q_CC_MINGW
+bool QWindowsFontEngine::hasUnreliableGlyphOutline() const
+{
+ return hasUnreliableOutline;
+}
+
qreal QWindowsFontEngine::minLeftBearing() const
{
if (lbearing == SHRT_MIN)
diff --git a/src/plugins/platforms/windows/qwindowsfontengine.h b/src/plugins/platforms/windows/qwindowsfontengine.h
index 7a0803830c..0ddf778fa0 100644
--- a/src/plugins/platforms/windows/qwindowsfontengine.h
+++ b/src/plugins/platforms/windows/qwindowsfontengine.h
@@ -122,6 +122,8 @@ public:
virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0);
#endif
+ bool hasUnreliableGlyphOutline() const Q_DECL_OVERRIDE;
+
int getGlyphIndexes(const QChar *ch, int numChars, QGlyphLayout *glyphs) const;
void getCMap();
@@ -136,6 +138,8 @@ private:
QImage::Format mask_format);
bool hasCFFTable() const;
bool hasCMapTable() const;
+ bool hasGlyfTable() const;
+ bool hasEbdtTable() const;
const QSharedPointer<QWindowsFontEngineData> m_fontEngineData;
@@ -146,6 +150,7 @@ private:
uint stockFont : 1;
uint ttf : 1;
uint hasOutline : 1;
+ uint hasUnreliableOutline : 1;
uint cffTable : 1;
TEXTMETRIC tm;
int lw;
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp
index 583441f396..773220660a 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.cpp
+++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp
@@ -496,6 +496,7 @@ QWinRTScreen::QWinRTScreen(ICoreWindow *window)
// Set initial orientation
onOrientationChanged(0);
+ setOrientationUpdateMask(m_nativeOrientation);
m_displayProperties->add_OrientationChanged(Callback<IDisplayPropertiesEventHandler>(this, &QWinRTScreen::onOrientationChanged).Get(),
&m_tokens[QEvent::OrientationChange]);
diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp
index 30d5c911e7..7304930b8b 100644
--- a/src/plugins/platforms/xcb/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/qglxintegration.cpp
@@ -419,7 +419,7 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share, const
return;
}
m_format = QSurfaceFormat();
- m_format.setRenderableType(QOpenGLContext::openGLModuleType() == QOpenGLContext::DesktopGL
+ m_format.setRenderableType(QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL
? QSurfaceFormat::OpenGL : QSurfaceFormat::OpenGLES);
updateFormatFromContext(m_format);
if (vinfo)
diff --git a/src/plugins/platforms/xcb/xcb-static/xcb-static.pro b/src/plugins/platforms/xcb/xcb-static/xcb-static.pro
index 19852b74b1..dfdcb2e83a 100644
--- a/src/plugins/platforms/xcb/xcb-static/xcb-static.pro
+++ b/src/plugins/platforms/xcb/xcb-static/xcb-static.pro
@@ -3,9 +3,8 @@
# libxcb-fixes, libxcb-randr, libxcb-shm, libxcb-sync, libxcb-image,
# libxcb-keysyms, libxcb-icccm, libxcb-renderutil, libxcb-xkb
#
-TEMPLATE = lib
-TARGET = xcb-static
-CONFIG += staticlib
+CONFIG += static
+load(qt_helper_lib)
XCB_DIR = ../../../../3rdparty/xcb
diff --git a/src/plugins/printsupport/printsupport.pro b/src/plugins/printsupport/printsupport.pro
index 93f3d65bc5..ed201f0744 100644
--- a/src/plugins/printsupport/printsupport.pro
+++ b/src/plugins/printsupport/printsupport.pro
@@ -1,5 +1,5 @@
TEMPLATE = subdirs
-mac: SUBDIRS += cocoa
+osx: SUBDIRS += cocoa
win32: SUBDIRS += windows
unix:!mac:contains(QT_CONFIG, cups): SUBDIRS += cups
diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp
index 5c73705d4c..0eed6ea4d3 100644
--- a/src/sql/models/qsqltablemodel.cpp
+++ b/src/sql/models/qsqltablemodel.cpp
@@ -448,9 +448,10 @@ bool QSqlTableModel::selectRow(int row)
// Look for changed values. Primary key fields are customarily first
// and probably change less often than other fields, so start at the end.
for (int f = curValues.count() - 1; f >= 0; --f) {
- if (curValues.value(f) != newValues.value(f))
+ if (curValues.value(f) != newValues.value(f)) {
needsAddingToCache = true;
break;
+ }
}
}
}
diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h
index 7c9a7b2b3f..7d2f3cea72 100644
--- a/src/testlib/qtest.h
+++ b/src/testlib/qtest.h
@@ -201,11 +201,17 @@ inline bool qCompare(QList<T> const &t1, QList<T> const &t2, const char *actual,
}
for (int i = 0; isOk && i < actualSize; ++i) {
if (!(t1.at(i) == t2.at(i))) {
+ char *val1 = toString(t1.at(i));
+ char *val2 = toString(t2.at(i));
+
qsnprintf(msg, sizeof(msg), "Compared lists differ at index %d.\n"
" Actual (%s): %s\n"
- " Expected (%s): %s", i, actual, toString(t1.at(i)),
- expected, toString(t2.at(i)));
+ " Expected (%s): %s", i, actual, val1 ? val1 : "<null>",
+ expected, val2 ? val2 : "<null>");
isOk = false;
+
+ delete [] val1;
+ delete [] val2;
}
}
return compare_helper(isOk, msg, 0, 0, actual, expected, file, line);
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index cbf479f1d2..cc58b51743 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -2863,8 +2863,6 @@ bool QTest::currentTestFailed()
void QTest::qSleep(int ms)
{
QTEST_ASSERT(ms > 0);
- QElapsedTimer timer;
- timer.start();
#if defined(Q_OS_WINRT)
WaitForSingleObjectEx(GetCurrentThread(), ms, true);
@@ -2874,20 +2872,6 @@ void QTest::qSleep(int ms)
struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
nanosleep(&ts, NULL);
#endif
- // Warn if the elapsed time was more than 50% longer or more than 10% shorter than the
- // requested time.
- qint64 requested = 1000000 * (qint64)ms;
- qint64 diff = timer.nsecsElapsed() - requested;
-#ifndef Q_OS_WIN
- const qint64 factor = 2; // more than 50% longer
-#else
- const qint64 factor = 1; // Windows: 50% is quite common, warn about 100%
-#endif
- if (diff * factor > requested || diff * 10 < -requested) {
- QTestLog::warn(qPrintable(
- QString::fromLatin1("QTest::qSleep() should have taken %1ns, but actually took %2ns!")
- .arg(requested).arg(diff + requested)), __FILE__, __LINE__);
- }
}
/*! \internal
diff --git a/src/widgets/accessible/simplewidgets.cpp b/src/widgets/accessible/simplewidgets.cpp
index b3170278ee..6e1428323f 100644
--- a/src/widgets/accessible/simplewidgets.cpp
+++ b/src/widgets/accessible/simplewidgets.cpp
@@ -647,10 +647,6 @@ QAccessible::State QAccessibleLineEdit::state() const
if (l->hasSelectedText())
state.selected = true;
- if (l->contextMenuPolicy() != Qt::NoContextMenu
- && l->contextMenuPolicy() != Qt::PreventContextMenu)
- state.hasPopup = true;
-
return state;
}
diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp
index bb8cdec896..6349bdc301 100644
--- a/src/widgets/dialogs/qfiledialog.cpp
+++ b/src/widgets/dialogs/qfiledialog.cpp
@@ -2128,6 +2128,11 @@ QString QFileDialog::getOpenFileName(QWidget *parent,
return QString();
}
+static inline QUrl dialogResultToUrl(const QString &file)
+{
+ return file.isEmpty() ? QUrl() : QUrl::fromLocalFile(file);
+}
+
/*!
This is a convenience static function that returns an existing file
selected by the user. If the user presses Cancel, it returns an
@@ -2166,7 +2171,7 @@ QUrl QFileDialog::getOpenFileUrl(QWidget *parent,
Q_UNUSED(supportedSchemes);
// Falls back to local file
- return QUrl::fromLocalFile(getOpenFileName(parent, caption, dir.toLocalFile(), filter, selectedFilter, options));
+ return dialogResultToUrl(getOpenFileName(parent, caption, dir.toLocalFile(), filter, selectedFilter, options));
}
/*!
@@ -2424,7 +2429,7 @@ QUrl QFileDialog::getSaveFileUrl(QWidget *parent,
Q_UNUSED(supportedSchemes);
// Falls back to local file
- return QUrl::fromLocalFile(getSaveFileName(parent, caption, dir.toLocalFile(), filter, selectedFilter, options));
+ return dialogResultToUrl(getSaveFileName(parent, caption, dir.toLocalFile(), filter, selectedFilter, options));
}
/*!
@@ -2532,7 +2537,7 @@ QUrl QFileDialog::getExistingDirectoryUrl(QWidget *parent,
Q_UNUSED(supportedSchemes);
// Falls back to local file
- return QUrl::fromLocalFile(getExistingDirectory(parent, caption, dir.toLocalFile(), options));
+ return dialogResultToUrl(getExistingDirectory(parent, caption, dir.toLocalFile(), options));
}
inline static QString _qt_get_directory(const QString &path)
diff --git a/src/widgets/graphicsview/qgraphicsview.cpp b/src/widgets/graphicsview/qgraphicsview.cpp
index 86648c4f26..5bcf52b6a3 100644
--- a/src/widgets/graphicsview/qgraphicsview.cpp
+++ b/src/widgets/graphicsview/qgraphicsview.cpp
@@ -1655,7 +1655,7 @@ void QGraphicsView::invalidateScene(const QRectF &rect, QGraphicsScene::SceneLay
/*!
\property QGraphicsView::interactive
- \brief whether the view allowed scene interaction.
+ \brief whether the view allows scene interaction.
If enabled, this view is set to allow scene interaction. Otherwise, this
view will not allow interaction, and any mouse or key events are ignored
diff --git a/src/widgets/itemviews/qlistwidget.cpp b/src/widgets/itemviews/qlistwidget.cpp
index 5040192f31..1f954d67dd 100644
--- a/src/widgets/itemviews/qlistwidget.cpp
+++ b/src/widgets/itemviews/qlistwidget.cpp
@@ -1631,7 +1631,7 @@ QWidget *QListWidget::itemWidget(QListWidgetItem *item) const
/*!
\since 4.1
- Sets the \a widget to be displayed in the give \a item.
+ Sets the \a widget to be displayed in the given \a item.
This function should only be used to display static content in the place of
a list widget item. If you want to display custom dynamic content or
diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp
index 781dd345bd..3f952ff768 100644
--- a/src/widgets/itemviews/qtreeview.cpp
+++ b/src/widgets/itemviews/qtreeview.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -1421,15 +1421,8 @@ void QTreeViewPrivate::adjustViewOptionsForIndex(QStyleOptionViewItem *option, c
const int right = (spanning ? header->visualIndex(0) : header->count() - 1 );
calcLogicalIndices(&logicalIndices, &viewItemPosList, left, right);
- int columnIndex = 0;
- for (int visualIndex = 0; visualIndex < current.column(); ++visualIndex) {
- int logicalIndex = header->logicalIndex(visualIndex);
- if (!header->isSectionHidden(logicalIndex)) {
- ++columnIndex;
- }
- }
-
- option->viewItemPosition = viewItemPosList.at(columnIndex);
+ const int visualIndex = logicalIndices.indexOf(current.column());
+ option->viewItemPosition = viewItemPosList.at(visualIndex);
}
diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp
index 10be5aef16..cbefb8a6bf 100644
--- a/src/widgets/kernel/qopenglwidget.cpp
+++ b/src/widgets/kernel/qopenglwidget.cpp
@@ -147,7 +147,7 @@ void QOpenGLWidget::paintGL()
void QOpenGLWidget::updateGL()
{
Q_D(QOpenGLWidget);
- if (d->uninitialized)
+ if (d->uninitialized || !d->surface())
return;
makeCurrent();
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index 0031d8e965..fc328e7af0 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -440,11 +440,13 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
if (!win)
win = w->nativeParentWidget()->windowHandle();
if (win && win->geometry().contains(event->globalPos())) {
+ // Use postEvent() to ensure the local QEventLoop terminates when called from QMenu::exec()
const QPoint localPos = win->mapFromGlobal(event->globalPos());
- QMouseEvent e(QEvent::MouseButtonPress, localPos, localPos, event->globalPos(), event->button(), event->buttons(), event->modifiers());
- QGuiApplicationPrivate::setMouseEventSource(&e, QGuiApplicationPrivate::mouseEventSource(event));
- e.setTimestamp(event->timestamp());
- QApplication::sendSpontaneousEvent(win, &e);
+ QMouseEvent *e = new QMouseEvent(QEvent::MouseButtonPress, localPos, localPos, event->globalPos(), event->button(), event->buttons(), event->modifiers());
+ e->spont = 1;
+ QGuiApplicationPrivate::setMouseEventSource(e, QGuiApplicationPrivate::mouseEventSource(event));
+ e->setTimestamp(event->timestamp());
+ QCoreApplication::postEvent(win, e);
}
}
}
diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm
index f3bbe11563..bedd9c74b6 100644
--- a/src/widgets/styles/qmacstyle_mac.mm
+++ b/src/widgets/styles/qmacstyle_mac.mm
@@ -1677,7 +1677,7 @@ QMacStylePrivate::QMacStylePrivate()
if (ptrHIShapeGetBounds == 0) {
QLibrary library(QLatin1String("/System/Library/Frameworks/Carbon.framework/Carbon"));
library.setLoadHints(QLibrary::ExportExternalSymbolsHint);
- ptrHIShapeGetBounds = reinterpret_cast<PtrHIShapeGetBounds>(library.resolve("HIShapeGetBounds"));
+ ptrHIShapeGetBounds = reinterpret_cast<PtrHIShapeGetBounds>(library.resolve("HIShapeGetBounds"));
}
}
@@ -5300,7 +5300,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(opt)){
HIThemeButtonDrawInfo bdi;
d->initComboboxBdi(combo, &bdi, widget, d->getDrawState(opt->state));
- if (!tds == kThemeStateInactive)
+ if (tds != kThemeStateInactive)
QMacStylePrivate::drawCombobox(qt_hirectForQRect(combo->rect), bdi, p);
else
d->drawColorlessButton(qt_hirectForQRect(combo->rect), &bdi, p, opt);
diff --git a/src/widgets/widgets/qmdiarea.cpp b/src/widgets/widgets/qmdiarea.cpp
index d0488d5955..beabaa87da 100644
--- a/src/widgets/widgets/qmdiarea.cpp
+++ b/src/widgets/widgets/qmdiarea.cpp
@@ -2606,6 +2606,9 @@ bool QMdiArea::eventFilter(QObject *object, QEvent *event)
return QAbstractScrollArea::eventFilter(object, event);
}
+ if (subWindow->mdiArea() != this)
+ return QAbstractScrollArea::eventFilter(object, event);
+
// QMdiSubWindow events:
switch (event->type()) {
case QEvent::Move:
diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp
index 729e08c7a5..f523ac2777 100644
--- a/src/widgets/widgets/qmenubar.cpp
+++ b/src/widgets/widgets/qmenubar.cpp
@@ -384,7 +384,7 @@ void QMenuBarPrivate::setCurrentAction(QAction *action, bool popup, bool activat
QAction *previousAction = currentAction;
#endif
currentAction = action;
- if (action) {
+ if (action && action->isEnabled()) {
activateAction(action, QAction::Hover);
if(popup)
popupAction(action, activateFirst);
@@ -1038,7 +1038,7 @@ void QMenuBar::mousePressEvent(QMouseEvent *e)
d->mouseDown = true;
QAction *action = d->actionAt(e->pos());
- if (!action || !d->isVisible(action)) {
+ if (!action || !d->isVisible(action) || !action->isEnabled()) {
d->setCurrentAction(0);
#ifndef QT_NO_WHATSTHIS
if (QWhatsThis::inWhatsThisMode())
diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp
index 9cc62fd10a..54b20e36f5 100644
--- a/src/widgets/widgets/qwidgettextcontrol.cpp
+++ b/src/widgets/widgets/qwidgettextcontrol.cpp
@@ -438,7 +438,6 @@ void QWidgetTextControlPrivate::setContent(Qt::TextFormat format, const QString
QObject::connect(doc, SIGNAL(contentsChanged()), q, SLOT(_q_updateCurrentCharFormatAndSelection()));
QObject::connect(doc, SIGNAL(cursorPositionChanged(QTextCursor)), q, SLOT(_q_emitCursorPosChanged(QTextCursor)));
- QObject::connect(doc, SIGNAL(contentsChange(int,int,int)), q, SLOT(_q_contentsChanged(int,int,int)));
QObject::connect(doc, SIGNAL(documentLayoutChanged()), q, SLOT(_q_documentLayoutChanged()));
// convenience signal forwards
@@ -501,6 +500,8 @@ void QWidgetTextControlPrivate::setContent(Qt::TextFormat format, const QString
q->ensureCursorVisible();
emit q->cursorPositionChanged();
+
+ QObject::connect(doc, SIGNAL(contentsChange(int,int,int)), q, SLOT(_q_contentsChanged(int,int,int)), Qt::UniqueConnection);
}
void QWidgetTextControlPrivate::startDrag()
@@ -646,7 +647,8 @@ void QWidgetTextControlPrivate::_q_contentsChanged(int from, int charsRemoved, i
{
Q_Q(QWidgetTextControl);
#ifndef QT_NO_ACCESSIBILITY
- if (QAccessible::isActive()) {
+
+ if (QAccessible::isActive() && q->parent() && q->parent()->isWidgetType()) {
QTextCursor tmp(doc);
tmp.setPosition(from);
tmp.setPosition(from + charsAdded, QTextCursor::KeepAnchor);
diff --git a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
index 53aef40df0..59c951332e 100644
--- a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
+++ b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
@@ -192,6 +192,8 @@ private slots:
void QTBUG28998_linkColor();
+ void textCursorUsageWithinContentsChange();
+
private:
void backgroundImage_checkExpectedHtml(const QTextDocument &doc);
@@ -3021,5 +3023,50 @@ void tst_QTextDocument::QTBUG28998_linkColor()
QCOMPARE(format.foreground(), pal.link());
}
+class ContentsChangeHandler : public QObject
+{
+ Q_OBJECT
+public:
+ ContentsChangeHandler(QTextDocument *doc)
+ : verticalMovementX(-1)
+ , doc(doc)
+ {
+ connect(doc, SIGNAL(contentsChange(int,int,int)),
+ this, SLOT(saveModifiedText(int, int, int)));
+ }
+
+private slots:
+ void saveModifiedText(int from, int /*charsRemoved*/, int charsAdded)
+ {
+ QTextCursor tmp(doc);
+ tmp.setPosition(from);
+ tmp.setPosition(from + charsAdded, QTextCursor::KeepAnchor);
+ text = tmp.selectedText();
+ verticalMovementX = tmp.verticalMovementX();
+ }
+
+public:
+ QString text;
+ int verticalMovementX;
+private:
+ QTextDocument *doc;
+};
+
+void tst_QTextDocument::textCursorUsageWithinContentsChange()
+{
+ // force creation of layout
+ doc->documentLayout();
+
+ QTextCursor cursor(doc);
+ cursor.insertText("initial text");
+
+ ContentsChangeHandler handler(doc);
+
+ cursor.insertText("new text");
+
+ QCOMPARE(handler.text, QString("new text"));
+ QCOMPARE(handler.verticalMovementX, -1);
+}
+
QTEST_MAIN(tst_QTextDocument)
#include "tst_qtextdocument.moc"
diff --git a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
index d0482d77e2..26eaec0470 100644
--- a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
+++ b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
@@ -122,6 +122,7 @@ private slots:
void boundingRectForUnsetLineWidth();
void boundingRectForSetLineWidth();
void glyphLessItems();
+ void justifyTrailingSpaces();
// QTextLine stuff
void setNumColumnsWrapAtWordBoundaryOrAnywhere();
@@ -1996,5 +1997,19 @@ void tst_QTextLayout::cursorInNonStopChars()
QVERIFY(line.cursorToX(2) == line.cursorToX(3));
}
+void tst_QTextLayout::justifyTrailingSpaces()
+{
+ QTextLayout layout(QStringLiteral(" t"), testFont);
+ layout.setTextOption(QTextOption(Qt::AlignJustify));
+ layout.beginLayout();
+
+ QTextLine line = layout.createLine();
+ line.setLineWidth(5);
+
+ layout.endLayout();
+
+ QVERIFY(qFuzzyIsNull(layout.lineAt(0).cursorToX(0)));
+}
+
QTEST_MAIN(tst_QTextLayout)
#include "tst_qtextlayout.moc"
diff --git a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp
index e3151ba862..f98cde51f9 100644
--- a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp
+++ b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp
@@ -81,6 +81,7 @@ private slots:
void emptyConstructor();
void constructor_data();
void constructor();
+ void constructor_device();
void constructingGarbage();
void copyAndAssign_data();
void copyAndAssign();
@@ -111,6 +112,8 @@ private slots:
void verify();
void extensions();
void threadSafeConstMethods();
+ void version_data();
+ void version();
// helper for verbose test failure messages
QString toString(const QList<QSslError>&);
@@ -226,6 +229,47 @@ void tst_QSslCertificate::constructor()
QVERIFY(!certificate.isNull());
}
+void tst_QSslCertificate::constructor_device()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QFile f(testDataDir + "/verify-certs/test-ocsp-good-cert.pem");
+ bool ok = f.open(QIODevice::ReadOnly);
+ QVERIFY(ok);
+
+ QSslCertificate cert(&f);
+ QVERIFY(!cert.isNull());
+ f.close();
+
+ // Check opening a DER as a PEM fails
+ QFile f2(testDataDir + "/certificates/cert.der");
+ ok = f2.open(QIODevice::ReadOnly);
+ QVERIFY(ok);
+
+ QSslCertificate cert2(&f2);
+ QVERIFY(cert2.isNull());
+ f2.close();
+
+ // Check opening a DER as a DER works
+ QFile f3(testDataDir + "/certificates/cert.der");
+ ok = f3.open(QIODevice::ReadOnly);
+ QVERIFY(ok);
+
+ QSslCertificate cert3(&f3, QSsl::Der);
+ QVERIFY(!cert3.isNull());
+ f3.close();
+
+ // Check opening a PEM as a DER fails
+ QFile f4(testDataDir + "/verify-certs/test-ocsp-good-cert.pem");
+ ok = f4.open(QIODevice::ReadOnly);
+ QVERIFY(ok);
+
+ QSslCertificate cert4(&f4, QSsl::Der);
+ QVERIFY(cert4.isNull());
+ f4.close();
+}
+
void tst_QSslCertificate::constructingGarbage()
{
if (!QSslSocket::supportsSsl())
@@ -1158,6 +1202,33 @@ void tst_QSslCertificate::threadSafeConstMethods()
}
+void tst_QSslCertificate::version_data()
+{
+ QTest::addColumn<QSslCertificate>("certificate");
+ QTest::addColumn<QByteArray>("result");
+
+ QTest::newRow("null certificate") << QSslCertificate() << QByteArray();
+
+ QList<QSslCertificate> certs;
+ certs << QSslCertificate::fromPath(testDataDir + "/verify-certs/test-ocsp-good-cert.pem");
+
+ QTest::newRow("v3 certificate") << certs.first() << QByteArrayLiteral("3");
+
+ certs.clear();
+ certs << QSslCertificate::fromPath(testDataDir + "/certificates/cert.pem");
+ QTest::newRow("v1 certificate") << certs.first() << QByteArrayLiteral("1");
+}
+
+void tst_QSslCertificate::version()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QFETCH(QSslCertificate, certificate);
+ QFETCH(QByteArray, result);
+ QCOMPARE(certificate.version(), result);
+}
+
#endif // QT_NO_SSL
QTEST_MAIN(tst_QSslCertificate)
diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
index 10ccebfec2..9715375e95 100644
--- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
+++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
@@ -1935,7 +1935,7 @@ void tst_QAccessibility::lineEditTest()
QVERIFY(iface->state().movable);
QVERIFY(iface->state().focusable);
QVERIFY(iface->state().selectable);
- QVERIFY(iface->state().hasPopup);
+ QVERIFY(!iface->state().hasPopup);
QCOMPARE(bool(iface->state().focused), le->hasFocus());
QString secret(QLatin1String("secret"));
@@ -1963,7 +1963,7 @@ void tst_QAccessibility::lineEditTest()
QVERIFY(!(iface->state().movable));
QVERIFY(iface->state().focusable);
QVERIFY(iface->state().selectable);
- QVERIFY(iface->state().hasPopup);
+ QVERIFY(!iface->state().hasPopup);
QCOMPARE(bool(iface->state().focused), le->hasFocus());
QLineEdit *le2 = new QLineEdit(toplevel);
diff --git a/tests/auto/sql/kernel/qsqlthread/tst_qsqlthread.cpp b/tests/auto/sql/kernel/qsqlthread/tst_qsqlthread.cpp
index e85c64db8e..881f2b5c7c 100644
--- a/tests/auto/sql/kernel/qsqlthread/tst_qsqlthread.cpp
+++ b/tests/auto/sql/kernel/qsqlthread/tst_qsqlthread.cpp
@@ -50,7 +50,7 @@
#include "qdebug.h"
#ifdef Q_OS_LINUX
-#include <pthread.h>
+#include <sched.h>
#endif
const QString qtest(qTableName("qtest", __FILE__, QSqlDatabase()));
@@ -159,7 +159,7 @@ public:
q.bindValue(2, 10);
QVERIFY_SQL(q, exec());
#ifdef Q_OS_LINUX
- pthread_yield();
+ sched_yield();
#endif
}
}
@@ -197,7 +197,7 @@ public:
q1.clear();
QVERIFY_SQL(q2, exec());
#ifdef Q_OS_LINUX
- pthread_yield();
+ sched_yield();
#endif
}
}
diff --git a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
index 047df0d3f2..096658ae02 100644
--- a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
+++ b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
@@ -171,6 +171,7 @@ private slots:
void tildeExpansion();
#endif // QT_BUILD_INTERNAL
#endif
+ void getFileUrl();
private:
QByteArray userSettings;
@@ -1429,5 +1430,49 @@ void tst_QFiledialog::tildeExpansion()
#endif // QT_BUILD_INTERNAL
#endif
+class DialogRejecter : public QObject
+{
+ Q_OBJECT
+public:
+ DialogRejecter()
+ {
+ QTimer *timer = new QTimer(this);
+ timer->setInterval(1000);
+ connect(timer, &QTimer::timeout, this, &DialogRejecter::rejectFileDialog);
+ timer->start();
+ }
+
+public slots:
+ void rejectFileDialog()
+ {
+ if (QWidget *w = QApplication::activeModalWidget())
+ if (QDialog *d = qobject_cast<QDialog *>(w))
+ d->reject();
+ }
+};
+
+void tst_QFiledialog::getFileUrl()
+{
+ // QTBUG-38672 , static functions should return empty Urls
+ const QFileDialog::Options options = QFileDialog::DontUseNativeDialog;
+ DialogRejecter dr;
+
+ QUrl url = QFileDialog::getOpenFileUrl(0, QStringLiteral("getOpenFileUrl"),
+ QUrl(), QString(), Q_NULLPTR, options);
+ QVERIFY(url.isEmpty());
+ QVERIFY(!url.isValid());
+
+ url = QFileDialog::getExistingDirectoryUrl(0, QStringLiteral("getExistingDirectoryUrl"),
+ QUrl(), options | QFileDialog::ShowDirsOnly);
+ QVERIFY(url.isEmpty());
+ QVERIFY(!url.isValid());
+
+ url = QFileDialog::getSaveFileUrl(0, QStringLiteral("getSaveFileUrl"),
+ QUrl(), QString(), Q_NULLPTR, options);
+ QVERIFY(url.isEmpty());
+ QVERIFY(!url.isValid());
+
+}
+
QTEST_MAIN(tst_QFiledialog)
#include "tst_qfiledialog.moc"
diff --git a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
index 77690cc27a..d12fb06daa 100644
--- a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
+++ b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the test suite of the Qt Toolkit.
@@ -261,6 +261,7 @@ private slots:
void taskQTBUG_18539_emitLayoutChanged();
void taskQTBUG_8176_emitOnExpandAll();
void taskQTBUG_34717_collapseAtBottom();
+ void taskQTBUG_37813_crash();
void testInitialFocus();
};
@@ -4327,5 +4328,31 @@ void tst_QTreeView::quickExpandCollapse()
}
#endif
+void tst_QTreeView::taskQTBUG_37813_crash()
+{
+ // QTBUG_37813: Crash in visual / logical index mapping in QTreeViewPrivate::adjustViewOptionsForIndex()
+ // when hiding/moving columns. It is reproduceable with a QTreeWidget only.
+#ifdef QT_BUILD_INTERNAL
+ QTreeWidget treeWidget;
+ treeWidget.setDragEnabled(true);
+ treeWidget.setColumnCount(2);
+ QList<QTreeWidgetItem *> items;
+ for (int r = 0; r < 2; ++r) {
+ QTreeWidgetItem *item = new QTreeWidgetItem();
+ for (int c = 0; c < treeWidget.columnCount(); ++c)
+ item->setText(c, QString::fromLatin1("Row %1 Column %2").arg(r).arg(c));
+ items.append(item);
+ }
+ treeWidget.addTopLevelItems(items);
+ treeWidget.setColumnHidden(0, true);
+ treeWidget.header()->moveSection(0, 1);
+ QItemSelection sel(treeWidget.model()->index(0, 0), treeWidget.model()->index(0, 1));
+ QRect rect;
+ QAbstractItemViewPrivate *av = static_cast<QAbstractItemViewPrivate*>(qt_widget_private(&treeWidget));
+ const QPixmap pixmap = av->renderToPixmap(sel.indexes(), &rect);
+ QVERIFY(pixmap.size().isValid());
+#endif // QT_BUILD_INTERNAL
+}
+
QTEST_MAIN(tst_QTreeView)
#include "tst_qtreeview.moc"
diff --git a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
index 5a36ffc671..14d59d3630 100644
--- a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
+++ b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
@@ -49,6 +49,12 @@
#include "../../../qtest-config.h"
+static inline void centerOnScreen(QWidget *w)
+{
+ const QPoint offset = QPoint(w->width() / 2, w->height() / 2);
+ w->move(QGuiApplication::primaryScreen()->availableGeometry().center() - offset);
+}
+
class tst_QStyleSheetStyle : public QObject
{
Q_OBJECT
@@ -142,6 +148,8 @@ tst_QStyleSheetStyle::~tst_QStyleSheetStyle()
void tst_QStyleSheetStyle::numinstances()
{
QWidget w;
+ w.resize(200, 200);
+ centerOnScreen(&w);
QCommonStyle *style = new QCommonStyle;
style->setParent(&w);
QWidget c(&w);
@@ -531,7 +539,14 @@ void tst_QStyleSheetStyle::dynamicProperty()
qApp->setStyleSheet(QString());
QString appStyle = qApp->style()->metaObject()->className();
- QPushButton pb1, pb2;
+ QPushButton pb1(QStringLiteral("dynamicProperty_pb1"));
+ pb1.setMinimumWidth(160);
+ pb1.move(QGuiApplication::primaryScreen()->availableGeometry().topLeft() + QPoint(20, 100));
+
+ QPushButton pb2(QStringLiteral("dynamicProperty_pb2"));
+ pb2.setMinimumWidth(160);
+ pb2.move(QGuiApplication::primaryScreen()->availableGeometry().topLeft() + QPoint(20, 200));
+
pb1.setProperty("type", "critical");
qApp->setStyleSheet("*[class~=\"QPushButton\"] { color: red; } *[type=\"critical\"] { background: white; }");
QVERIFY(COLOR(pb1) == Qt::red);
@@ -675,6 +690,8 @@ void tst_QStyleSheetStyle::onWidgetDestroyed()
void tst_QStyleSheetStyle::fontPrecedence()
{
QLineEdit edit;
+ edit.setMinimumWidth(200);
+ centerOnScreen(&edit);
edit.show();
QFont font;
QVERIFY(FONTSIZE(edit) != 22); // Sanity check to make sure this test makes sense.
@@ -737,8 +754,9 @@ void tst_QStyleSheetStyle::focusColors()
// ten pixels of the right color requires quite a many characters, as the
// majority of the pixels will have slightly different colors due to the
// anti-aliasing effect.
-#if !defined(Q_OS_WIN32) && !defined(Q_OS_MAC) && !(defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(Q_CC_INTEL))
- QSKIP("This is a fragile test which fails on many esoteric platforms because of focus problems. "
+#if !defined(Q_OS_WIN32) && !(defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(Q_CC_INTEL))
+ QSKIP("This is a fragile test which fails on many esoteric platforms because of focus problems"
+ " (for example, QTBUG-33959)."
"That doesn't mean that the feature doesn't work in practice.");
#endif
QList<QWidget *> widgets;
@@ -768,6 +786,7 @@ void tst_QStyleSheetStyle::focusColors()
layout->addWidget(widget);
frame.setLayout(layout);
+ centerOnScreen(&frame);
frame.show();
QApplication::setActiveWindow(&frame);
QVERIFY(QTest::qWaitForWindowActive(&frame));
@@ -795,6 +814,9 @@ void tst_QStyleSheetStyle::focusColors()
#ifndef QTEST_NO_CURSOR
void tst_QStyleSheetStyle::hoverColors()
{
+#ifdef Q_OS_OSX
+ QSKIP("This test is fragile on Mac, most likely due to QTBUG-33959.");
+#endif
QList<QWidget *> widgets;
widgets << new QPushButton("TESTING TESTING");
widgets << new QLineEdit("TESTING TESTING");
@@ -822,31 +844,22 @@ void tst_QStyleSheetStyle::hoverColors()
layout->addWidget(widget);
frame.setLayout(layout);
+ centerOnScreen(&frame);
frame.show();
QApplication::setActiveWindow(&frame);
QVERIFY(QTest::qWaitForWindowActive(&frame));
//move the mouse inside the widget, it should be colored
QTest::mouseMove ( widget, QPoint(6,6));
- QTest::qWait(60);
-#ifdef Q_OS_MAC
- QEXPECT_FAIL("", "Numerous failures related to Qt::WA_UnderMouse, see QTBUGT-23685", Continue);
-#endif
- QVERIFY(widget->testAttribute(Qt::WA_UnderMouse));
+ QTRY_VERIFY(widget->testAttribute(Qt::WA_UnderMouse));
QImage image(frame.width(), frame.height(), QImage::Format_ARGB32);
frame.render(&image);
-#ifdef Q_OS_MAC
- QEXPECT_FAIL("", "Numerous failures related to Qt::WA_UnderMouse, see QTBUGT-23685", Continue);
-#endif
QVERIFY2(testForColors(image, QColor(0xe8, 0xff, 0x66)),
(QString::fromLatin1(widget->metaObject()->className())
+ " did not contain background color #e8ff66").toLocal8Bit().constData());
-#ifdef Q_OS_MAC
- QEXPECT_FAIL("", "Numerous failures related to Qt::WA_UnderMouse, see QTBUGT-23685", Continue);
-#endif
QVERIFY2(testForColors(image, QColor(0xff, 0x00, 0x84)),
(QString::fromLatin1(widget->metaObject()->className())
+ " did not contain text color #ff0084").toLocal8Bit().constData());
@@ -866,9 +879,7 @@ void tst_QStyleSheetStyle::hoverColors()
//move the mouse again inside the widget, it should be colored
QTest::mouseMove (widget, QPoint(5,5));
- QTest::qWait(60);
-
- QVERIFY(widget->testAttribute(Qt::WA_UnderMouse));
+ QTRY_VERIFY(widget->testAttribute(Qt::WA_UnderMouse));
frame.render(&image);
@@ -904,35 +915,47 @@ public:
void tst_QStyleSheetStyle::background()
{
- const int number = 4;
- QWidget* widgets[number];
+ typedef QSharedPointer<QWidget> WidgetPtr;
+
+ const QString styleSheet = QStringLiteral("* { background-color: #e8ff66; }");
+ QVector<WidgetPtr> widgets;
+ const QPoint topLeft = QGuiApplication::primaryScreen()->availableGeometry().topLeft();
// Testing inheritance styling of QDialog.
- widgets[0] = new SingleInheritanceDialog;
- widgets[0]->setStyleSheet("* { background-color: #e8ff66; }");
- widgets[1] = new DoubleInheritanceDialog;
- widgets[1]->setStyleSheet("* { background-color: #e8ff66; }");
+ WidgetPtr toplevel(new SingleInheritanceDialog);
+ toplevel->resize(200, 200);
+ toplevel->move(topLeft + QPoint(20, 20));
+ toplevel->setStyleSheet(styleSheet);
+ widgets.append(toplevel);
+
+ toplevel = WidgetPtr(new DoubleInheritanceDialog);
+ toplevel->resize(200, 200);
+ toplevel->move(topLeft + QPoint(20, 320));
+ toplevel->setStyleSheet(styleSheet);
+ widgets.append(toplevel);
// Testing gradients in QComboBox.
- QLayout* layout;
- QComboBox* cb;
// First color
- widgets[2] = new QDialog;
- layout = new QGridLayout;
- cb = new QComboBox;
+ toplevel = WidgetPtr(new QDialog);
+ toplevel->move(topLeft + QPoint(320, 20));
+ QGridLayout *layout = new QGridLayout(toplevel.data());
+ QComboBox* cb = new QComboBox;
+ cb->setMinimumWidth(160);
cb->setStyleSheet("* { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop:0 #e8ff66, stop:1 #000000); }");
- layout->addWidget(cb);
- widgets[2]->setLayout(layout);
+ layout->addWidget(cb, 0, 0);
+ widgets.append(toplevel);
// Second color
- widgets[3] = new QDialog;
- layout = new QGridLayout;
+ toplevel = WidgetPtr(new QDialog);
+ toplevel->move(topLeft + QPoint(320, 320));
+ layout = new QGridLayout(toplevel.data());
cb = new QComboBox;
+ cb->setMinimumWidth(160);
cb->setStyleSheet("* { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop:0 #e8ff66, stop:1 #000000); }");
- layout->addWidget(cb);
- widgets[3]->setLayout(layout);
-
- for (int c = 0; c < number; ++c) {
- QWidget* widget = widgets[c];
+ layout->addWidget(cb, 0, 0);
+ widgets.append(toplevel);
+ for (int c = 0; c < widgets.size(); ++c) {
+ QWidget *widget = widgets.at(c).data();
+ widget->setWindowTitle(QStringLiteral("background ") + QString::number(c));
widget->show();
QVERIFY(QTest::qWaitForWindowExposed(widget));
@@ -941,12 +964,15 @@ void tst_QStyleSheetStyle::background()
if (image.depth() < 24)
QSKIP("Test doesn't support color depth < 24");
+ if (c == 2 && !QApplication::style()->objectName().compare(QLatin1String("fusion"), Qt::CaseInsensitive))
+ QEXPECT_FAIL("", "QTBUG-21468", Abort);
+
QVERIFY2(testForColors(image, QColor(0xe8, 0xff, 0x66)),
- (QString::fromLatin1(widget->metaObject()->className())
+ (QString::number(c) + QLatin1Char(' ') + QString::fromLatin1(widget->metaObject()->className())
+ " did not contain background image with color #e8ff66")
.toLocal8Bit().constData());
- delete widget;
+ widget->hide();
}
}
@@ -956,6 +982,7 @@ void tst_QStyleSheetStyle::tabAlignement()
QTabWidget tabWidget(&topLevel);
tabWidget.addTab(new QLabel("tab1"),"tab1");
tabWidget.resize(QSize(400,400));
+ centerOnScreen(&topLevel);
topLevel.show();
QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
QTabBar *bar = tabWidget.findChild<QTabBar*>();
@@ -1023,6 +1050,7 @@ void tst_QStyleSheetStyle::minmaxSizes()
tabWidget.setStyleSheet("QTabBar::tab { min-width:100px; max-width:130px; }");
+ centerOnScreen(&tabWidget);
tabWidget.show();
QTest::qWait(50);
//i allow 4px additional border from the native style (hence the -2, <=2)
@@ -1050,6 +1078,7 @@ void tst_QStyleSheetStyle::task206238_twice()
tw->addTab(new QLabel("foo"), "test");
w.setCentralWidget(tw);
w.setStyleSheet("background: red;");
+ centerOnScreen(&w);
w.show();
QTest::qWait(20);
QCOMPARE(BACKGROUND(w) , QColor("red"));
@@ -1219,6 +1248,8 @@ void tst_QStyleSheetStyle::proxyStyle()
QString styleSheet("QPushButton {background-color: red; }");
QWidget *w = new QWidget;
+ w->setMinimumWidth(160);
+ centerOnScreen(w);
QVBoxLayout *layout = new QVBoxLayout(w);
QPushButton *pb1 = new QPushButton(qApp->style()->objectName(), w);
@@ -1294,6 +1325,7 @@ void tst_QStyleSheetStyle::emptyStyleSheet()
layout.addWidget(new QDateEdit(&w));
layout.addWidget(new QGroupBox("some text", &w));
+ centerOnScreen(&w);
w.show();
QVERIFY(QTest::qWaitForWindowExposed(&w));
//workaround the fact that the label sizehint is one pixel different the first time.
@@ -1315,13 +1347,30 @@ void tst_QStyleSheetStyle::emptyStyleSheet()
img2.save("emptyStyleSheet_img2.png");
}
+ QEXPECT_FAIL("", "QTBUG-21468", Abort);
QCOMPARE(img1,img2);
}
+class ApplicationStyleSetter
+{
+public:
+ explicit inline ApplicationStyleSetter(QStyle *s) : m_oldStyleName(QApplication::style()->objectName())
+ { QApplication::setStyle(s); }
+ inline ~ApplicationStyleSetter()
+ { QApplication::setStyle(QStyleFactory::create(m_oldStyleName)); }
+
+private:
+ const QString m_oldStyleName;
+};
+
void tst_QStyleSheetStyle::toolTip()
{
qApp->setStyleSheet(QString());
QWidget w;
+ // Use "Fusion" to prevent the Vista style from clobbering the tooltip palette in polish().
+ QStyle *fusionStyle = QStyleFactory::create(QLatin1String("Fusion"));
+ QVERIFY(fusionStyle);
+ ApplicationStyleSetter as(fusionStyle);
QHBoxLayout layout(&w);
w.setLayout(&layout);
@@ -1349,11 +1398,12 @@ void tst_QStyleSheetStyle::toolTip()
wid4->setToolTip("this is wid4");
wid4->setObjectName("wid4");
+ centerOnScreen(&w);
w.show();
qApp->setActiveWindow(&w);
QVERIFY(QTest::qWaitForWindowActive(&w));
- QColor normalToolTip = qApp->palette().toolTipBase().color();
+ const QColor normalToolTip = QToolTip::palette().color(QPalette::Inactive, QPalette::ToolTipBase);
QList<QWidget *> widgets;
QList<QColor> colors;
@@ -1372,12 +1422,13 @@ void tst_QStyleSheetStyle::toolTip()
QWidget *tooltip = 0;
foreach (QWidget *widget, QApplication::topLevelWidgets()) {
- if (widget->inherits("QTipLabel") && widget->isVisible()) {
+ if (widget->inherits("QTipLabel")) {
tooltip = widget;
break;
}
}
QVERIFY(tooltip);
+ QTRY_VERIFY(tooltip->isVisible()); // Wait until Roll-Effect is finished (Windows Vista)
QCOMPARE(tooltip->palette().color(tooltip->backgroundRole()), col);
}
@@ -1394,6 +1445,8 @@ void tst_QStyleSheetStyle::embeddedFonts()
{
//task 235622 and 210551
QSpinBox spin;
+ spin.setMinimumWidth(160);
+ spin.move(QGuiApplication::primaryScreen()->availableGeometry().topLeft() + QPoint(20, 20));
spin.show();
spin.setStyleSheet("QSpinBox { font-size: 32px; }");
QTest::qWait(20);
@@ -1411,6 +1464,8 @@ void tst_QStyleSheetStyle::embeddedFonts()
//task 242556
QComboBox box;
+ box.setMinimumWidth(160);
+ box.move(QGuiApplication::primaryScreen()->availableGeometry().topLeft() + QPoint(20, 120));
box.setEditable(true);
box.addItems(QStringList() << "First" << "Second" << "Third");
box.setStyleSheet("QComboBox { font-size: 32px; }");
@@ -1483,6 +1538,7 @@ void tst_QStyleSheetStyle::complexWidgetFocus()
layout->addWidget(widget);
frame.setLayout(layout);
+ centerOnScreen(&frame);
frame.show();
QApplication::setActiveWindow(&frame);
QVERIFY(QTest::qWaitForWindowActive(&frame));
@@ -1507,6 +1563,7 @@ void tst_QStyleSheetStyle::task188195_baseBackground()
{
QTreeView tree;
tree.setStyleSheet( "QTreeView:disabled { background-color:#ab1251; }" );
+ tree.move(QGuiApplication::primaryScreen()->availableGeometry().topLeft() + QPoint(20, 100));
tree.show();
QTest::qWait(20);
QImage image(tree.width(), tree.height(), QImage::Format_ARGB32);
@@ -1527,6 +1584,7 @@ void tst_QStyleSheetStyle::task188195_baseBackground()
QTableWidget table(12, 12);
table.setItem(0, 0, new QTableWidgetItem());
table.setStyleSheet( "QTableView {background-color: #ff0000}" );
+ table.move(QGuiApplication::primaryScreen()->availableGeometry().topLeft() + QPoint(300, 100));
table.show();
QTest::qWait(20);
image = QImage(table.width(), table.height(), QImage::Format_ARGB32);
@@ -1560,6 +1618,7 @@ void tst_QStyleSheetStyle::task232085_spinBoxLineEditBg()
layout->addWidget(spinbox);
frame.setLayout(layout);
+ centerOnScreen(&frame);
frame.show();
QApplication::setActiveWindow(&frame);
spinbox->setFocus();
@@ -1619,6 +1678,7 @@ void tst_QStyleSheetStyle::QTBUG11658_cachecrash()
Widget(QWidget *parent = 0)
: QWidget(parent)
{
+ setMinimumWidth(160);
QVBoxLayout* pLayout = new QVBoxLayout(this);
QCheckBox* pCheckBox = new QCheckBox(this);
pLayout->addWidget(pCheckBox);
@@ -1633,6 +1693,7 @@ void tst_QStyleSheetStyle::QTBUG11658_cachecrash()
Widget *w = new Widget();
delete w;
w = new Widget();
+ centerOnScreen(w);
w->show();
QVERIFY(QTest::qWaitForWindowExposed(w));
@@ -1653,6 +1714,8 @@ void tst_QStyleSheetStyle::QTBUG15910_crashNullWidget()
}
} w;
w.setStyleSheet("* { background-color: white; color:black; border 3px solid yellow }");
+ w.setMinimumWidth(160);
+ centerOnScreen(&w);
w.show();
QVERIFY(QTest::qWaitForWindowExposed(&w));
}
@@ -1675,6 +1738,7 @@ void tst_QStyleSheetStyle::QTBUG36933_brokenPseudoClassLookup()
// parsing of this stylesheet must not crash, and it must be correctly applied
widget.setStyleSheet(QStringLiteral("QHeaderView::section:vertical { background-color: #FF0000 }"));
+ centerOnScreen(&widget);
widget.show();
QVERIFY(QTest::qWaitForWindowExposed(&widget));
@@ -1685,6 +1749,8 @@ void tst_QStyleSheetStyle::QTBUG36933_brokenPseudoClassLookup()
QHeaderView *verticalHeader = widget.verticalHeader();
QImage image(verticalHeader->size(), QImage::Format_ARGB32);
verticalHeader->render(&image);
+ if (!QApplication::style()->objectName().compare(QLatin1String("fusion"), Qt::CaseInsensitive))
+ QEXPECT_FAIL("", "QTBUG-21468", Abort);
QVERIFY(testForColors(image, QColor(0xFF, 0x00, 0x00)));
}
diff --git a/tests/auto/widgets/styles/styles.pro b/tests/auto/widgets/styles/styles.pro
index 1791279b72..508b6ecd41 100644
--- a/tests/auto/widgets/styles/styles.pro
+++ b/tests/auto/widgets/styles/styles.pro
@@ -12,5 +12,5 @@ SUBDIRS=\
!mac:SUBDIRS -= \
qmacstyle \
-!contains( styles, motif ):SUBDIRS -= \
+ios|android|qnx|*wince*:SUBDIRS -= \
qstylesheetstyle \
diff --git a/tests/auto/xml/sax/qxmlsimplereader/tst_qxmlsimplereader.cpp b/tests/auto/xml/sax/qxmlsimplereader/tst_qxmlsimplereader.cpp
index 6a3bcc7a7d..fadfc0b48a 100644
--- a/tests/auto/xml/sax/qxmlsimplereader/tst_qxmlsimplereader.cpp
+++ b/tests/auto/xml/sax/qxmlsimplereader/tst_qxmlsimplereader.cpp
@@ -60,26 +60,26 @@ class XmlServer : public QThread
{
Q_OBJECT
public:
- XmlServer();
+ XmlServer(QObject *parent = 0) : QThread(parent), quit_soon(false), listening(false) {}
+
bool quit_soon;
+ bool listening;
protected:
virtual void run();
};
-XmlServer::XmlServer()
-{
- quit_soon = false;
-}
-
-#define CHUNK_SIZE 1
+#define CHUNK_SIZE 2048
void XmlServer::run()
{
QTcpServer srv;
- if (!srv.listen(QHostAddress::Any, TEST_PORT))
+ listening = srv.listen(QHostAddress::Any, TEST_PORT);
+ if (!listening) {
+ qWarning() << "Failed to listen on" << TEST_PORT << srv.errorString();
return;
+ }
for (;;) {
srv.waitForNewConnection(100);
@@ -168,12 +168,9 @@ class tst_QXmlSimpleReader : public QObject
QString prefix;
};
-tst_QXmlSimpleReader::tst_QXmlSimpleReader()
+tst_QXmlSimpleReader::tst_QXmlSimpleReader() : server(new XmlServer(this))
{
- server = new XmlServer();
- server->setParent(this);
server->start();
- QTest::qSleep(1000);
}
tst_QXmlSimpleReader::~tst_QXmlSimpleReader()
@@ -568,16 +565,13 @@ void tst_QXmlSimpleReader::inputFromSocket()
{
QFETCH(QString, file_name);
+ QTRY_VERIFY(server->listening);
+
QTcpSocket sock;
sock.connectToHost(QHostAddress::LocalHost, TEST_PORT);
-
- const bool connectionSuccess = sock.waitForConnected();
- if(!connectionSuccess) {
- QTextStream out(stderr);
- out << "QTcpSocket::errorString()" << sock.errorString();
- }
-
- QVERIFY(connectionSuccess);
+ QVERIFY2(sock.waitForConnected(),
+ qPrintable(QStringLiteral("Cannot connect on port ") + QString::number(TEST_PORT)
+ + QStringLiteral(": ") + sock.errorString()));
sock.write(file_name.toLocal8Bit() + "\n");
QVERIFY(sock.waitForBytesWritten());