diff options
author | Tomasz Olszak <olszak.tomasz@gmail.com> | 2014-04-26 22:46:27 +0200 |
---|---|---|
committer | Tomasz Olszak <olszak.tomasz@gmail.com> | 2014-04-26 22:46:39 +0200 |
commit | 278b908d7ac1f4179585198996b88e7de8bee3dd (patch) | |
tree | b28e8f2926540c83c8e857dbfcc6121bd3492647 | |
parent | 88eed403ea227721a5cea6f1e0ef347687aa6e4b (diff) | |
parent | a2ad5cf1aadd5a3bec09595be7e8611abab31bb6 (diff) | |
download | qtbase-278b908d7ac1f4179585198996b88e7de8bee3dd.tar.gz qtbase-278b908d7ac1f4179585198996b88e7de8bee3dd.tar.bz2 qtbase-278b908d7ac1f4179585198996b88e7de8bee3dd.zip |
Merge remote-tracking branch 'origin/stable' into wip/tizen
Change-Id: I871631ffa655b5b43753d2906b69fb36cdbc66c0
140 files changed, 2368 insertions, 1534 deletions
diff --git a/config.tests/unix/objcopy/objcopy.pro b/config.tests/unix/objcopy/objcopy.pro index d2f9c738f6..3c28b89ef3 100644 --- a/config.tests/unix/objcopy/objcopy.pro +++ b/config.tests/unix/objcopy/objcopy.pro @@ -1,10 +1,4 @@ SOURCES = objcopy.cpp CONFIG -= qt -all.depends += only_keep_debug strip_debug add_gnu_debuglink - -only_keep_debug.commands = $$QMAKE_OBJCOPY --only-keep-debug objcopy objcopy.debug -strip_debug.commands = $$QMAKE_OBJCOPY --strip-debug objcopy -add_gnu_debuglink.commands = $$QMAKE_OBJCOPY --add-gnu-debuglink=objcopy.debug objcopy - -QMAKE_EXTRA_TARGETS += all only_keep_debug strip_debug add_gnu_debuglink +QMAKE_POST_LINK += $$QMAKE_OBJCOPY --only-keep-debug objcopy objcopy.debug && $$QMAKE_OBJCOPY --strip-debug objcopy && $$QMAKE_OBJCOPY --add-gnu-debuglink=objcopy.debug objcopy @@ -616,7 +616,7 @@ CFG_EGL=auto CFG_EGL_X=auto CFG_FONTCONFIG=auto CFG_FREETYPE=auto -CFG_HARFBUZZ=no +CFG_HARFBUZZ=auto CFG_SQL_AVAILABLE= QT_ALL_BUILD_PARTS=" libs tools examples tests " QT_DEFAULT_BUILD_PARTS="libs tools examples" @@ -781,8 +781,6 @@ QT_LIBS_GLIB= # default qpa platform QT_QPA_DEFAULT_PLATFORM= -# default print support plugin -QT_PRINTSUPPORT_DEFAULT_PLUGIN= # Android vars CFG_DEFAULT_ANDROID_NDK_ROOT=$ANDROID_NDK_ROOT @@ -1805,6 +1803,20 @@ while [ "$#" -gt 0 ]; do UNKNOWN_OPT=yes fi ;; + pulseaudio) + if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then + CFG_PULSEAUDIO="$VAL" + else + UNKNOWN_OPT=yes + fi + ;; + alsa) + if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then + CFG_ALSA="$VAL" + else + UNKNOWN_OPT=yes + fi + ;; gtkstyle) if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then CFG_QGTKSTYLE="$VAL" @@ -2369,6 +2381,15 @@ Third Party Libraries: -no-glib ........... Do not compile Glib support. + -glib .............. Compile Glib support. + -no-pulseaudio ..... Do not compile PulseAudio support. + + -pulseaudio ........ Compile PulseAudio support. + + -no-alsa ........... Do not compile ALSA support. + + -alsa .............. Compile ALSA support. + + -no-gtkstyle ....... Do not compile GTK theme support. + + -gtkstyle .......... Compile GTK theme support. + Additional options: -make <part> ....... Add part to the list of parts to be built at make time. @@ -3103,7 +3124,7 @@ if [ "$XPLATFORM_IOS" = "yes" ]; then CFG_PKGCONFIG="no" CFG_NOBUILD_PARTS="$CFG_NOBUILD_PARTS examples" CFG_SHARED="no" # iOS builds should be static to be able to submit to the App Store - CFG_SKIP_MODULES="$CFG_SKIP_MODULES qtconnectivity qtdoc qtmacextras qtserialport qttools qtwebkit qtwebkit-examples" + CFG_SKIP_MODULES="$CFG_SKIP_MODULES qtconnectivity qtdoc qtmacextras qtserialport qtwebkit qtwebkit-examples" # If the user passes -sdk on the command line we build a SDK-specific Qt build. # Otherwise we build a joined simulator and device build, which is the default. @@ -4619,7 +4640,7 @@ if [ "$CFG_GLIB" = "yes" -a "$CFG_QGTKSTYLE" != "no" ]; then QMakeVar set QT_LIBS_QGTK2 "$QT_LIBS_QGTK2" else if [ "$CFG_QGTKSTYLE" = "yes" ] && [ "$CFG_CONFIGURE_EXIT_ON_ERROR" = "yes" ]; then - echo "Gtk theme support cannot be enabled due to functionality tests!" + echo "GTK theme support cannot be enabled due to functionality tests!" echo " Turn on verbose messaging (-v) to $0 to see the fin al report." echo " If you believe this message is in error you may use the continue" echo " switch (-continue) to $0 to continue." @@ -5183,15 +5204,6 @@ if [ -z "$QT_QPA_DEFAULT_PLATFORM" ]; then fi fi -# Determine print support plugin belonging to the default QPA platform -if [ "$QT_QPA_DEFAULT_PLATFORM" = "cocoa" ]; then - QT_PRINTSUPPORT_DEFAULT_PLUGIN=cocoaprintersupport -elif [ "$QT_QPA_DEFAULT_PLATFORM" = "windows" ]; then - QT_PRINTSUPPORT_DEFAULT_PLUGIN=windowsprintersupport -elif [ "$QT_QPA_DEFAULT_PLATFORM" = "xcb" ]; then - QT_PRINTSUPPORT_DEFAULT_PLUGIN=cupsprintersupport -fi - if [ -n "$QMAKE_CFLAGS_XCB" ] || [ -n "$QMAKE_LIBS_XCB" ]; then QMakeVar set QMAKE_CFLAGS_XCB "$QMAKE_CFLAGS_XCB" QMakeVar set QMAKE_LIBS_XCB "$QMAKE_LIBS_XCB" @@ -5235,8 +5247,8 @@ if [ "$CFG_FREETYPE" = "auto" ]; then fi # harfbuzz support -[ "$XPLATFORM_MINGW" = "yes" ] && [ "$CFG_HARFBUZZ" = "auto" ] && CFG_HARFBUZZ=no [ "$XPLATFORM_MAC" = "yes" ] && [ "$CFG_HARFBUZZ" = "auto" ] && CFG_HARFBUZZ=yes +[ "$CFG_HARFBUZZ" = "auto" ] && CFG_HARFBUZZ=no # disable auto-detection on non-Mac for now if [ "$CFG_HARFBUZZ" = "auto" ]; then if compileTest unix/harfbuzz "HarfBuzz"; then CFG_HARFBUZZ=system @@ -6151,7 +6163,6 @@ EOF fi echo "#define QT_QPA_DEFAULT_PLATFORM_NAME \"$QT_QPA_DEFAULT_PLATFORM\"" >>"$outpath/src/corelib/global/qconfig.h.new" -echo "#define QT_QPA_DEFAULT_PRINTSUPPORTPLUGIN_NAME \"QT_PRINTSUPPORT_DEFAULT_PLUGIN\"" >>"$outpath/src/corelib/global/qconfig.h.new" # avoid unecessary rebuilds by copying only if qconfig.h has changed if cmp -s "$outpath/src/corelib/global/qconfig.h" "$outpath/src/corelib/global/qconfig.h.new"; then @@ -6221,7 +6232,6 @@ EOF if [ "$CFG_SHARED" = "no" ]; then echo "QT_DEFAULT_QPA_PLUGIN = q$QT_QPA_DEFAULT_PLATFORM" >> "$QTCONFIG.tmp" - echo "QT_DEFAULT_PRINTSUPPORTPLUGIN = $QT_PRINTSUPPORT_DEFAULT_PLUGIN" >> "$QTCONFIG.tmp" echo >> "$QTCONFIG.tmp" fi diff --git a/doc/global/qt-cpp-defines.qdocconf b/doc/global/qt-cpp-defines.qdocconf index 3240ec4a20..1039c88e8d 100644 --- a/doc/global/qt-cpp-defines.qdocconf +++ b/doc/global/qt-cpp-defines.qdocconf @@ -19,6 +19,7 @@ defines += Q_QDOC \ Q_COMPILER_RVALUE_REFS Cpp.ignoretokens += \ + ENGINIOCLIENT_EXPORT \ PHONON_EXPORT \ Q_AUTOTEST_EXPORT \ Q_BLUETOOTH_EXPORT \ diff --git a/doc/src/snippets/qx11embedcontainer/main.cpp b/doc/src/snippets/qx11embedcontainer/main.cpp deleted file mode 100644 index 97d6f11385..0000000000 --- a/doc/src/snippets/qx11embedcontainer/main.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtGui> -#include <QX11EmbedContainer> - -//! [0] -int main(int argc, char *argv[]) -{ - QApplication app(argc, argv); - - if (app.arguments().count() != 2) { - qFatal("Error - expected executable path as argument"); - return 1; - } - - QX11EmbedContainer container; - container.show(); - - QProcess process(&container); - QString executable(app.arguments()[1]); - QStringList arguments; - arguments << QString::number(container.winId()); - process.start(executable, arguments); - - int status = app.exec(); - process.close(); - return status; -} -//! [0] diff --git a/doc/src/snippets/qx11embedwidget/main.cpp b/doc/src/snippets/qx11embedwidget/main.cpp deleted file mode 100644 index 77b45c1da3..0000000000 --- a/doc/src/snippets/qx11embedwidget/main.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QApplication> -#include "embedwidget.h" - -//! [0] -int main(int argc, char *argv[]) -{ - QApplication app(argc, argv); - - if (app.arguments().count() != 2) { - qFatal("Error - expected window id as argument"); - return 1; - } - - QString windowId(app.arguments()[1]); - EmbedWidget window; - window.embedInto(windowId.toULong()); - window.show(); - - return app.exec(); -} -//! [0] diff --git a/mkspecs/features/qml_plugin.prf b/mkspecs/features/qml_plugin.prf index f3739572c7..f161a71ef9 100644 --- a/mkspecs/features/qml_plugin.prf +++ b/mkspecs/features/qml_plugin.prf @@ -100,12 +100,3 @@ load(qt_common) } load(qml_module) - -unix|mingw { - !isEmpty(_QMAKE_SUPER_CACHE_): \ - lib_replace.match = $$dirname(_QMAKE_SUPER_CACHE_)/[^/][^/]*/lib - else: \ - lib_replace.match = $$MODULE_BASE_OUTDIR - lib_replace.replace = $$[QT_INSTALL_LIBS/raw] - QMAKE_PRL_INSTALL_REPLACE += lib_replace -} diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf index 5968a8a4ff..418b124a85 100644 --- a/mkspecs/features/qt.prf +++ b/mkspecs/features/qt.prf @@ -204,8 +204,6 @@ contains(QT_CONFIG, static) { else: \ QTPLUGIN += $$QT_DEFAULT_QPA_PLUGIN } - needs_printsupport_plugin: \ - QTPLUGIN += $$QT_DEFAULT_PRINTSUPPORTPLUGIN import_plugins:!isEmpty(QTPLUGIN) { IMPORT_FILE_CONT = \ "// This file is autogenerated by qmake. It imports static plugin classes for" \ diff --git a/mkspecs/features/qt_common.prf b/mkspecs/features/qt_common.prf index 6cd848b405..4dcabe9237 100644 --- a/mkspecs/features/qt_common.prf +++ b/mkspecs/features/qt_common.prf @@ -19,6 +19,24 @@ contains(TEMPLATE, .*lib) { unix:contains(QT_CONFIG, reduce_relocations): CONFIG += bsymbolic_functions contains(QT_CONFIG, largefile): CONFIG += largefile contains(QT_CONFIG, separate_debug_info): CONFIG += separate_debug_info + + !isEmpty(_QMAKE_SUPER_CACHE_): \ + rplbase = $$dirname(_QMAKE_SUPER_CACHE_)/[^/][^/]* + else: \ + rplbase = $$MODULE_BASE_OUTDIR + host_build: \ + qt_libdir = $$[QT_HOST_LIBS] + else: \ + qt_libdir = $$[QT_INSTALL_LIBS/raw] + contains(QMAKE_DEFAULT_LIBDIRS, $$qt_libdir) { + lib_replace.match = "[^ ']*$$rplbase/lib" + lib_replace.replace = + } else { + lib_replace.match = $$rplbase/lib + lib_replace.replace = $$qt_libdir + } + lib_replace.CONFIG = path + QMAKE_PRL_INSTALL_REPLACE += lib_replace } warnings_are_errors:warning_clean { diff --git a/mkspecs/features/qt_module.prf b/mkspecs/features/qt_module.prf index 2134077ed3..5dac0250ea 100644 --- a/mkspecs/features/qt_module.prf +++ b/mkspecs/features/qt_module.prf @@ -127,6 +127,8 @@ win32 { # keeps the code clean and helps in writing code that is # safe across all platforms. DEFINES *= _CRT_SECURE_NO_WARNINGS + + DEFINES += _USE_MATH_DEFINES } aix-g++* { @@ -166,43 +168,29 @@ android: CONFIG += qt_android_deps #install directives load(qt_installs) -!isEmpty(_QMAKE_SUPER_CACHE_): \ - rplbase = $$dirname(_QMAKE_SUPER_CACHE_)/[^/][^/]* -else: \ - rplbase = $$MODULE_BASE_OUTDIR -include_replace.match = $$rplbase/include -include_replace.replace = $$[QT_INSTALL_HEADERS/raw] -include_replace.CONFIG = path -lib_replace.match = $$rplbase/lib -host_build: \ - lib_replace.replace = $$[QT_HOST_LIBS] -else: \ - lib_replace.replace = $$[QT_INSTALL_LIBS/raw] -lib_replace.CONFIG = path -QMAKE_PRL_INSTALL_REPLACE += include_replace lib_replace - -unix|mingw { - CONFIG += create_pc - QMAKE_PKGCONFIG_LIBDIR = $$lib_replace.replace - QMAKE_PKGCONFIG_INCDIR = $$include_replace.replace - QMAKE_PKGCONFIG_CFLAGS = -I${includedir}/$$MODULE_INCNAME - QMAKE_PKGCONFIG_DESTDIR = pkgconfig - QMAKE_PKGCONFIG_INSTALL_REPLACE += include_replace lib_replace -} - -unix { - CONFIG += create_libtool explicitlib - QMAKE_LIBTOOL_LIBDIR = $$lib_replace.replace - QMAKE_LIBTOOL_INSTALL_REPLACE += include_replace lib_replace -} +load(qt_targets) +load(qt_common) +# this builds on top of qt_common unix|mingw { + CONFIG += create_pc + QMAKE_PKGCONFIG_DESTDIR = pkgconfig + QMAKE_PKGCONFIG_LIBDIR = $$qt_libdir + QMAKE_PKGCONFIG_INCDIR = $$[QT_INSTALL_HEADERS/raw] + QMAKE_PKGCONFIG_CFLAGS = -I${includedir}/$$MODULE_INCNAME QMAKE_PKGCONFIG_NAME = $$replace(TARGET, ^Qt, "Qt$$section(VERSION, ., 0, 0) ") QMAKE_PKGCONFIG_FILE = $$replace(TARGET, ^Qt, Qt$$section(VERSION, ., 0, 0)) for(i, MODULE_DEPENDS): \ QMAKE_PKGCONFIG_REQUIRES += $$replace(QT.$${i}.name, ^Qt, Qt$$eval(QT.$${i}.MAJOR_VERSION)) isEmpty(QMAKE_PKGCONFIG_DESCRIPTION): \ QMAKE_PKGCONFIG_DESCRIPTION = $$replace(TARGET, ^Qt, "Qt ") module + QMAKE_PKGCONFIG_INSTALL_REPLACE += lib_replace + + unix { + CONFIG += create_libtool explicitlib + QMAKE_LIBTOOL_LIBDIR = $$qt_libdir + QMAKE_LIBTOOL_INSTALL_REPLACE += lib_replace + } } contains(QT_PRODUCT, OpenSource.*):DEFINES *= QT_OPENSOURCE @@ -221,9 +209,3 @@ win32 { } TARGET = $$qtLibraryTarget($$TARGET$$QT_LIBINFIX) #do this towards the end - -load(qt_targets) -load(qt_common) - -win32:DEFINES+=_USE_MATH_DEFINES - diff --git a/mkspecs/features/qt_plugin.prf b/mkspecs/features/qt_plugin.prf index c020bd2767..52567eaff0 100644 --- a/mkspecs/features/qt_plugin.prf +++ b/mkspecs/features/qt_plugin.prf @@ -83,12 +83,3 @@ load(qt_common) wince*:LIBS += $$QMAKE_LIBS_GUI QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF - -!isEmpty(_QMAKE_SUPER_CACHE_): \ - rplbase = $$dirname(_QMAKE_SUPER_CACHE_)/[^/][^/]* -else: \ - rplbase = $$MODULE_BASE_OUTDIR -lib_replace.match = $$rplbase/lib -lib_replace.replace = $$[QT_INSTALL_LIBS/raw] -lib_replace.CONFIG = path -QMAKE_PRL_INSTALL_REPLACE += lib_replace diff --git a/mkspecs/features/winrt/font_deployment.prf b/mkspecs/features/winrt/font_deployment.prf index 36db5b7cac..c767d5bc1a 100644 --- a/mkspecs/features/winrt/font_deployment.prf +++ b/mkspecs/features/winrt/font_deployment.prf @@ -43,7 +43,7 @@ if(!build_pass:equals(TEMPLATE, "vcapp")) { !isEmpty(FONTS):equals(TEMPLATE, "app") { fonts.files = $$BUILD_DIR/fonts/* - isEmpty($$target.path) { + isEmpty(target.path) { fonts.path = $$OUT_PWD/fonts } else { fonts.path = $$target.path/fonts @@ -54,7 +54,9 @@ if(!build_pass:equals(TEMPLATE, "vcapp")) { } !isEmpty(FONTS):winphone:equals(TEMPLATE, "vcapp"):build_pass { - fonts.files = $$OUT_PWD/fonts/* + for (FONT, FONTS) { + fonts.files += $$OUT_PWD/fonts/$$basename(FONT) + } fonts.path = fonts DEPLOYMENT += fonts } diff --git a/mkspecs/macx-ios-clang/features/default_post.prf b/mkspecs/macx-ios-clang/features/default_post.prf index 496553f8c0..79024c588c 100644 --- a/mkspecs/macx-ios-clang/features/default_post.prf +++ b/mkspecs/macx-ios-clang/features/default_post.prf @@ -77,6 +77,9 @@ equals(TEMPLATE, app) { args += $$system_quote($$arg) system("cd $$system_quote($$OUT_PWD) && $$QMAKE_QMAKE $$args $$system_quote($$_PRO_FILE_) -spec macx-xcode") + check.commands = "$(MAKE) -f $(MAKEFILE).ReleaseSimulator xcode_build_check" + QMAKE_EXTRA_TARGETS += check + } else { load(resolve_config) @@ -113,6 +116,9 @@ equals(TEMPLATE, app) { QMAKE_EXTRA_TARGETS += xcode_build_dir_distclean distclean.depends = xcode_build_dir_distclean QMAKE_EXTRA_TARGETS += distclean + + xcode_build_check.commands = "$(TESTRUNNER) $$title($$cfg)-$${sdk}/$(TARGET).app $(TESTARGS)" + QMAKE_EXTRA_TARGETS += xcode_build_check } CONFIG = diff --git a/mkspecs/qnx-armle-v7-qcc/qplatformdefs.h b/mkspecs/qnx-armle-v7-qcc/qplatformdefs.h index 2f95f0d392..27e4a3aa41 100644 --- a/mkspecs/qnx-armle-v7-qcc/qplatformdefs.h +++ b/mkspecs/qnx-armle-v7-qcc/qplatformdefs.h @@ -83,7 +83,7 @@ #include <arpa/inet.h> #define QT_USE_XOPEN_LFS_EXTENSIONS -#if !defined(__EXT_QNX__READDIR64_R) +#if defined(__EXT_QNX__READDIR_R) && !defined(__EXT_QNX__READDIR64_R) #define QT_NO_READDIR64 #endif #include "../common/posix/qplatformdefs.h" diff --git a/mkspecs/qnx-x86-qcc/qplatformdefs.h b/mkspecs/qnx-x86-qcc/qplatformdefs.h index b47aecde0d..246f82e27f 100644 --- a/mkspecs/qnx-x86-qcc/qplatformdefs.h +++ b/mkspecs/qnx-x86-qcc/qplatformdefs.h @@ -83,7 +83,7 @@ #include <arpa/inet.h> #define QT_USE_XOPEN_LFS_EXTENSIONS -#if !defined(__EXT_QNX__READDIR64_R) +#if defined(__EXT_QNX__READDIR_R) && !defined(__EXT_QNX__READDIR64_R) #define QT_NO_READDIR64 #endif #include "../common/posix/qplatformdefs.h" diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index bad4eb5456..3870d1ef0d 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -3217,7 +3217,7 @@ MakefileGenerator::writePkgConfigFile() QString prefix = pkgConfigPrefix(); QString libDir = project->first("QMAKE_PKGCONFIG_LIBDIR").toQString(); if(libDir.isEmpty()) - libDir = prefix + Option::dir_sep + "lib" + Option::dir_sep; + libDir = prefix + "/lib"; QString includeDir = project->first("QMAKE_PKGCONFIG_INCDIR").toQString(); if(includeDir.isEmpty()) includeDir = prefix + "/include"; @@ -3284,10 +3284,12 @@ MakefileGenerator::writePkgConfigFile() // libs t << "Libs: "; - QString pkgConfiglibDir; QString pkgConfiglibName; if (target_mode == TARG_MAC_MODE && project->isActiveConfig("lib_bundle")) { - pkgConfiglibDir = "-F${libdir}"; + if (libDir != QLatin1String("/System/Library/Frameworks") + && libDir != QLatin1String("/Library/Frameworks")) { + t << "-F${libdir} "; + } ProString bundle; if (!project->isEmpty("QMAKE_FRAMEWORK_BUNDLE_NAME")) bundle = unescapeFilePath(project->first("QMAKE_FRAMEWORK_BUNDLE_NAME")); @@ -3298,12 +3300,13 @@ MakefileGenerator::writePkgConfigFile() bundle = bundle.left(suffix); pkgConfiglibName = "-framework " + bundle + " "; } else { - pkgConfiglibDir = "-L${libdir}"; + if (!project->values("QMAKE_DEFAULT_LIBDIRS").contains(libDir)) + t << "-L${libdir} "; pkgConfiglibName = "-l" + unescapeFilePath(project->first("QMAKE_ORIG_TARGET")); if (project->isActiveConfig("shared")) pkgConfiglibName += project->first("TARGET_VERSION_EXT").toQString(); } - t << pkgConfiglibDir << " " << pkgConfiglibName << " \n"; + t << pkgConfiglibName << " \n"; ProStringList libs; if(!project->isEmpty("QMAKE_INTERNAL_PRL_LIBS")) { @@ -3327,7 +3330,10 @@ MakefileGenerator::writePkgConfigFile() << varGlue("PRL_EXPORT_CXXFLAGS", "", " ", " ") << varGlue("QMAKE_PKGCONFIG_CFLAGS", "", " ", " ") // << varGlue("DEFINES","-D"," -D"," ") - << "-I${includedir}\n"; + ; + if (!project->values("QMAKE_DEFAULT_INCDIRS").contains(includeDir)) + t << "-I${includedir}"; + t << endl; // requires const QString requires = project->values("QMAKE_PKGCONFIG_REQUIRES").join(' '); diff --git a/qmake/option.cpp b/qmake/option.cpp index a2bd938666..677899950c 100644 --- a/qmake/option.cpp +++ b/qmake/option.cpp @@ -488,7 +488,7 @@ bool Option::postProcessProject(QMakeProject *project) Option::dir_sep = project->dirSep().toQString(); - if (Option::output_dir.startsWith(project->buildRoot())) + if (!project->buildRoot().isEmpty() && Option::output_dir.startsWith(project->buildRoot())) Option::mkfile::cachefile_depth = Option::output_dir.mid(project->buildRoot().length()).count('/'); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp index 2de477b3bc..e70727c65e 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp @@ -40,6 +40,13 @@ #include "libEGL/Display.h" +#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE) +# include <dxgi1_3.h> +# include <wrl.h> +# include <windows.applicationmodel.core.h> +typedef ABI::Windows::Foundation::IEventHandler<ABI::Windows::ApplicationModel::SuspendingEventArgs *> SuspendEventHandler; +#endif + #ifdef _DEBUG // this flag enables suppressing some spurious warnings that pop up in certain WebGL samples // and conformance tests. to enable all warnings, remove this define. @@ -426,9 +433,49 @@ EGLint Renderer11::initialize() } } +#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE) + // Monitor when the application suspends so that Trim() can be called + Microsoft::WRL::ComPtr<ABI::Windows::ApplicationModel::Core::ICoreApplication> application; + result = RoGetActivationFactory(Microsoft::WRL::Wrappers::HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(), + IID_PPV_ARGS(&application)); + if (FAILED(result)) + { + ERR("Error obtaining CoreApplication: 0x%08X", result); + return EGL_NOT_INITIALIZED; + } + + EventRegistrationToken cookie; + result = application->add_Suspending(Microsoft::WRL::Callback<SuspendEventHandler>(this, &Renderer11::onSuspend).Get(), &cookie); + if (FAILED(result)) + { + ERR("Error setting suspend callback: 0x%08X", result); + return EGL_NOT_INITIALIZED; + } +#endif + return EGL_SUCCESS; } +#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE) +HRESULT Renderer11::onSuspend(IInspectable *, ABI::Windows::ApplicationModel::ISuspendingEventArgs *) +{ + if (!mDevice) + return S_OK; + + Microsoft::WRL::ComPtr<IDXGIDevice3> dxgiDevice; + HRESULT result = mDevice->QueryInterface(IID_PPV_ARGS(&dxgiDevice)); + if (FAILED(result)) + { + ERR("Error obtaining DXGIDevice3 on suspend: 0x%08X", result); + return S_OK; + } + + dxgiDevice->Trim(); + + return S_OK; +} +#endif + // do any one-time device initialization // NOTE: this is also needed after a device lost/reset // to reset the scene status and ensure the default states are reset. diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h index a8a722c56c..773fc26db1 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h @@ -18,6 +18,17 @@ #include "libGLESv2/renderer/d3d11/InputLayoutCache.h" #include "libGLESv2/renderer/RenderTarget.h" +#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE) +struct IInspectable; +namespace ABI { + namespace Windows { + namespace ApplicationModel { + struct ISuspendingEventArgs; + } + } +} +#endif + namespace gl { class Renderbuffer; @@ -202,6 +213,10 @@ class Renderer11 : public Renderer RenderTarget *drawRenderTarget, bool wholeBufferCopy); ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource); +#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE) + HRESULT onSuspend(IInspectable *, ABI::Windows::ApplicationModel::ISuspendingEventArgs *); +#endif + HMODULE mD3d11Module; HMODULE mDxgiModule; diff --git a/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro b/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro index 7d997d7d8b..d505c30aa6 100644 --- a/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro +++ b/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro @@ -7,6 +7,9 @@ CONFIG += \ 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 DEFINES += HAVE_CONFIG_H diff --git a/src/angle/patches/0016-ANGLE-WinRT-Call-Trim-when-application-suspends.patch b/src/angle/patches/0016-ANGLE-WinRT-Call-Trim-when-application-suspends.patch new file mode 100644 index 0000000000..bf2a1ad363 --- /dev/null +++ b/src/angle/patches/0016-ANGLE-WinRT-Call-Trim-when-application-suspends.patch @@ -0,0 +1,118 @@ +From 158b7642c53843ed954fa667ff23b8746f95f8eb Mon Sep 17 00:00:00 2001 +From: Andrew Knight <andrew.knight@digia.com> +Date: Tue, 22 Apr 2014 09:13:57 +0300 +Subject: [PATCH] ANGLE WinRT: Call Trim() when application suspends + +This is required by Windows Store Apps to pass certification. + +Task-number: QTBUG-38481 +Change-Id: I6dc00431ee5f6c7d4c64111ccc38f46483d3b9a8 +--- + .../src/libGLESv2/renderer/d3d11/Renderer11.cpp | 47 ++++++++++++++++++++++ + .../src/libGLESv2/renderer/d3d11/Renderer11.h | 15 +++++++ + 2 files changed, 62 insertions(+) + +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp +index 2de477b..e70727c 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp +@@ -40,6 +40,13 @@ + + #include "libEGL/Display.h" + ++#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE) ++# include <dxgi1_3.h> ++# include <wrl.h> ++# include <windows.applicationmodel.core.h> ++typedef ABI::Windows::Foundation::IEventHandler<ABI::Windows::ApplicationModel::SuspendingEventArgs *> SuspendEventHandler; ++#endif ++ + #ifdef _DEBUG + // this flag enables suppressing some spurious warnings that pop up in certain WebGL samples + // and conformance tests. to enable all warnings, remove this define. +@@ -426,9 +433,49 @@ EGLint Renderer11::initialize() + } + } + ++#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE) ++ // Monitor when the application suspends so that Trim() can be called ++ Microsoft::WRL::ComPtr<ABI::Windows::ApplicationModel::Core::ICoreApplication> application; ++ result = RoGetActivationFactory(Microsoft::WRL::Wrappers::HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(), ++ IID_PPV_ARGS(&application)); ++ if (FAILED(result)) ++ { ++ ERR("Error obtaining CoreApplication: 0x%08X", result); ++ return EGL_NOT_INITIALIZED; ++ } ++ ++ EventRegistrationToken cookie; ++ result = application->add_Suspending(Microsoft::WRL::Callback<SuspendEventHandler>(this, &Renderer11::onSuspend).Get(), &cookie); ++ if (FAILED(result)) ++ { ++ ERR("Error setting suspend callback: 0x%08X", result); ++ return EGL_NOT_INITIALIZED; ++ } ++#endif ++ + return EGL_SUCCESS; + } + ++#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE) ++HRESULT Renderer11::onSuspend(IInspectable *, ABI::Windows::ApplicationModel::ISuspendingEventArgs *) ++{ ++ if (!mDevice) ++ return S_OK; ++ ++ Microsoft::WRL::ComPtr<IDXGIDevice3> dxgiDevice; ++ HRESULT result = mDevice->QueryInterface(IID_PPV_ARGS(&dxgiDevice)); ++ if (FAILED(result)) ++ { ++ ERR("Error obtaining DXGIDevice3 on suspend: 0x%08X", result); ++ return S_OK; ++ } ++ ++ dxgiDevice->Trim(); ++ ++ return S_OK; ++} ++#endif ++ + // do any one-time device initialization + // NOTE: this is also needed after a device lost/reset + // to reset the scene status and ensure the default states are reset. +diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h +index a8a722c..773fc26 100644 +--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h ++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h +@@ -18,6 +18,17 @@ + #include "libGLESv2/renderer/d3d11/InputLayoutCache.h" + #include "libGLESv2/renderer/RenderTarget.h" + ++#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE) ++struct IInspectable; ++namespace ABI { ++ namespace Windows { ++ namespace ApplicationModel { ++ struct ISuspendingEventArgs; ++ } ++ } ++} ++#endif ++ + namespace gl + { + class Renderbuffer; +@@ -202,6 +213,10 @@ class Renderer11 : public Renderer + RenderTarget *drawRenderTarget, bool wholeBufferCopy); + ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource); + ++#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE) ++ HRESULT onSuspend(IInspectable *, ABI::Windows::ApplicationModel::ISuspendingEventArgs *); ++#endif ++ + HMODULE mD3d11Module; + HMODULE mDxgiModule; + +-- +1.9.0.msysgit.0 + diff --git a/src/corelib/doc/qtcore.qdocconf b/src/corelib/doc/qtcore.qdocconf index 18342d0138..c8eb15a7f7 100644 --- a/src/corelib/doc/qtcore.qdocconf +++ b/src/corelib/doc/qtcore.qdocconf @@ -26,7 +26,7 @@ qhp.QtCore.subprojects.classes.sortPages = true tagfile = ../../../doc/qtcore/qtcore.tags -depends += qtgui qtwidgets qtnetwork qtdoc qtmacextras qtquick qtlinguist qtdesigner qtconcurrent qtxml qmake +depends += activeqt qtdbus qtgui qtwidgets qtnetwork qtdoc qtmacextras qtqml qtquick qtlinguist qtdesigner qtconcurrent qtxml qmake headerdirs += .. diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qregexp.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qregexp.cpp index 779fbaa723..530819a173 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qregexp.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qregexp.cpp @@ -77,7 +77,7 @@ QRegExp mark("\\b" // word boundary QRegExp rx("^\\d\\d?$"); // match integers 0 to 99 rx.indexIn("123"); // returns -1 (no match) rx.indexIn("-6"); // returns -1 (no match) -rx.indexIn("6"); // returns 0 (matched as position 0) +rx.indexIn("6"); // returns 0 (matched at position 0) //! [4] diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 950647004a..dd880d8ede 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -842,21 +842,28 @@ #endif /* Q_CC_MSVC */ #ifdef __cplusplus +# include <utility> # if defined(Q_OS_QNX) -# include <utility> # if defined(_YVALS) || defined(_LIBCPP_VER) // QNX: libcpp (Dinkumware-based) doesn't have the <initializer_list> // header, so the feature is useless, even if the compiler supports // it. Disable. -# ifdef Q_COMPILER_INITIALIZER_LISTS -# undef Q_COMPILER_INITIALIZER_LISTS -# endif -# ifdef Q_COMPILER_RVALUE_REFS -# undef Q_COMPILER_RVALUE_REFS -# endif +# undef Q_COMPILER_INITIALIZER_LISTS +// That libcpp doesn't have std::move either, so disable everything +// related to rvalue refs. +# undef Q_COMPILER_RVALUE_REFS +# undef Q_COMPILER_REF_QUALIFIERS # endif +# endif // Q_OS_QNX +# if (defined(Q_CC_CLANG) || defined(Q_CC_INTEL)) && defined(Q_OS_MAC) && defined(__GNUC_LIBSTD__) \ + && ((__GNUC_LIBSTD__-0) * 100 + __GNUC_LIBSTD_MINOR__-0 <= 402) +// Mac OS X: Apple has not updated libstdc++ since 2007, which means it does not have +// <initializer_list> or std::move. Let's disable these features +# undef Q_COMPILER_INITIALIZER_LISTS +# undef Q_COMPILER_RVALUE_REFS +# undef Q_COMPILER_REF_QUALIFIERS # endif -#endif // Q_OS_QNX +#endif /* * C++11 keywords and expressions diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index fba8b019e7..09f2d73db4 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -45,11 +45,11 @@ #include <stddef.h> -#define QT_VERSION_STR "5.3.0" +#define QT_VERSION_STR "5.3.1" /* QT_VERSION is (major << 16) + (minor << 8) + patch. */ -#define QT_VERSION 0x050300 +#define QT_VERSION 0x050301 /* can be used like #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)) */ diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index da26490d18..4a602e4b2b 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -1207,6 +1207,23 @@ static void android_default_message_handler(QtMsgType type, static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &buf) { + // to determine logging destination and marking logging environment variable as deprecated + // ### remove when deprecated + struct LogDestination { + LogDestination(const char *deprecated, bool forceConsole) { + const char* replacement = "QT_LOGGING_TO_CONSOLE"; + bool newEnv = qEnvironmentVariableIsSet(replacement); + bool oldEnv = qEnvironmentVariableIsSet(deprecated); + if (oldEnv && !newEnv && !forceConsole) { + fprintf(stderr, "Warning: Environment variable %s is deprecated, " + "use %s instead.\n", deprecated, replacement); + fflush(stderr); + } + toConsole = newEnv || oldEnv || forceConsole; + } + bool toConsole; + }; + QString logMessage = qMessageFormatString(type, context, buf); #if defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB) @@ -1217,12 +1234,19 @@ static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &con #endif // Q_OS_WIN #if defined(QT_USE_SLOG2) - slog2_default_handler(type, logMessage.toLocal8Bit().constData()); + static const bool logToConsole = qEnvironmentVariableIsSet("QT_LOGGING_TO_CONSOLE"); + if (!logToConsole) { + slog2_default_handler(type, logMessage.toLocal8Bit().constData()); + } else { + fprintf(stderr, "%s", logMessage.toLocal8Bit().constData()); + fflush(stderr); + } #elif defined(QT_USE_JOURNALD) && !defined(QT_BOOTSTRAPPED) // We use isatty to catch the obvious case of someone running something interactively. - // We also support an environment variable for Qt Creator use, or more complicated cases like subprocesses. - static bool logToConsole = isatty(fileno(stdin)) || !qEnvironmentVariableIsEmpty("QT_NO_JOURNALD_LOG"); - if (Q_LIKELY(!logToConsole)) { + // We also support environment variables for Qt Creator use, or more complicated cases + // like subprocesses. + static const LogDestination logdest("QT_NO_JOURNALD_LOG", isatty(fileno(stdin))); + if (Q_LIKELY(!logdest.toConsole)) { // remove trailing \n, systemd appears to want them newline-less logMessage.chop(1); systemd_default_message_handler(type, context, logMessage); @@ -1231,8 +1255,8 @@ static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &con fflush(stderr); } #elif defined(Q_OS_ANDROID) - static bool logToAndroid = qEnvironmentVariableIsEmpty("QT_ANDROID_PLAIN_LOG"); - if (logToAndroid) { + static const LogDestination logdest("QT_ANDROID_PLAIN_LOG", false); + if (!logdest.toConsole) { android_default_message_handler(type, context, logMessage); } else { fprintf(stderr, "%s", logMessage.toLocal8Bit().constData()); diff --git a/src/corelib/io/qfiledevice.cpp b/src/corelib/io/qfiledevice.cpp index d2c8d37d4a..f7e58a7bed 100644 --- a/src/corelib/io/qfiledevice.cpp +++ b/src/corelib/io/qfiledevice.cpp @@ -139,10 +139,9 @@ void QFileDevicePrivate::setError(QFileDevice::FileError err, int errNum) are returned and on Windows the rights of the current user are returned. This behavior might change in a future Qt version. - Note that Qt does not by default check for permissions on NTFS - file systems, as this may decrease the performance of file - handling considerably. It is possible to force permission checking - on NTFS by including the following code in your source: + \note On NTFS file systems, ownership and permissions checking is + disabled by default for performance reasons. To enable it, + include the following line: \snippet ntfsp.cpp 0 diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp index 2cf97ef94e..60f7e47e62 100644 --- a/src/corelib/io/qfileinfo.cpp +++ b/src/corelib/io/qfileinfo.cpp @@ -271,6 +271,17 @@ QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request) groupId(). You can examine a file's permissions and ownership in a single statement using the permission() function. + \note On NTFS file systems, ownership and permissions checking is + disabled by default for performance reasons. To enable it, + include the following line: + + \snippet ntfsp.cpp 0 + + Permission checking is then turned on and off by incrementing and + decrementing \c qt_ntfs_permission_lookup by 1. + + \snippet ntfsp.cpp 1 + \section1 Performance Issues Some of QFileInfo's functions query the file system, but for diff --git a/src/corelib/io/qfilesystemengine.cpp b/src/corelib/io/qfilesystemengine.cpp index 53cf6158ad..8b6ceebc62 100644 --- a/src/corelib/io/qfilesystemengine.cpp +++ b/src/corelib/io/qfilesystemengine.cpp @@ -224,7 +224,7 @@ bool QFileSystemEngine::fillMetaData(int fd, QFileSystemMetaData &data) return false; } -#if defined(Q_OS_QNX) +#if defined(QT_EXT_QNX_READDIR_R) static void fillStat64fromStat32(struct stat64 *statBuf64, const struct stat &statBuf32) { statBuf64->st_mode = statBuf32.st_mode; @@ -289,7 +289,7 @@ void QFileSystemMetaData::fillFromStatBuf(const QT_STATBUF &statBuffer) void QFileSystemMetaData::fillFromDirEnt(const QT_DIRENT &entry) { -#if defined(Q_OS_QNX) +#if defined(QT_EXT_QNX_READDIR_R) knownFlagsMask = 0; entryFlags = 0; for (dirent_extra *extra = _DEXTRA_FIRST(&entry); _DEXTRA_VALID(extra, &entry); diff --git a/src/corelib/io/qfilesystemiterator_p.h b/src/corelib/io/qfilesystemiterator_p.h index 4164020359..18a9c2dbda 100644 --- a/src/corelib/io/qfilesystemiterator_p.h +++ b/src/corelib/io/qfilesystemiterator_p.h @@ -95,10 +95,10 @@ private: #else QT_DIR *dir; QT_DIRENT *dirEntry; -#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN) +#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN) || defined(QT_EXT_QNX_READDIR_R) // for readdir_r QScopedPointer<QT_DIRENT, QScopedPointerPodDeleter> mt_file; -#if defined(Q_OS_QNX) && defined(__EXT_QNX__READDIR_R) +#if defined(QT_EXT_QNX_READDIR_R) // for _readdir_r size_t direntSize; #endif diff --git a/src/corelib/io/qfilesystemiterator_unix.cpp b/src/corelib/io/qfilesystemiterator_unix.cpp index 0b59aa169a..0f9bbd8a29 100644 --- a/src/corelib/io/qfilesystemiterator_unix.cpp +++ b/src/corelib/io/qfilesystemiterator_unix.cpp @@ -70,7 +70,7 @@ QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDir::Fi if (!nativePath.endsWith('/')) nativePath.append('/'); -#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN) +#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN) || defined(QT_EXT_QNX_READDIR_R) // ### Race condition; we should use fpathconf and dirfd(). size_t maxPathName = ::pathconf(nativePath.constData(), _PC_NAME_MAX); if (maxPathName == size_t(-1)) @@ -81,13 +81,14 @@ QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDir::Fi Q_CHECK_PTR(p); mt_file.reset(p); -#if defined(Q_OS_QNX) && defined(__EXT_QNX__READDIR_R) +#if defined(QT_EXT_QNX_READDIR_R) direntSize = maxPathName; - // Include extra stat information in the readdir() call (d_stat member of dirent_extra_stat). - // This is used in QFileSystemMetaData::fillFromDirEnt() to avoid extra stat() calls when iterating - // over directories - if (dircntl(dir, D_SETFLAG, D_FLAG_STAT) == -1) + // Include extra stat information in the readdir() call (d_stat member of + // dirent_extra_stat). This is used in QFileSystemMetaData::fillFromDirEnt() to + // avoid extra stat() calls when iterating over directories + int flags = dircntl(dir, D_GETFLAG) | D_FLAG_STAT | D_FLAG_FILTER; + if (dircntl(dir, D_SETFLAG, flags) == -1) lastError = errno; #endif #endif @@ -105,7 +106,7 @@ bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaDa if (!dir) return false; -#if defined(Q_OS_QNX) && defined(QT_EXT_QNX_READDIR_R) +#if defined(QT_EXT_QNX_READDIR_R) lastError = QT_EXT_QNX_READDIR_R(dir, mt_file.data(), &dirEntry, direntSize); if (lastError) return false; diff --git a/src/corelib/io/qfilesystemwatcher_polling.cpp b/src/corelib/io/qfilesystemwatcher_polling.cpp index 689f05bb1b..401f95ae82 100644 --- a/src/corelib/io/qfilesystemwatcher_polling.cpp +++ b/src/corelib/io/qfilesystemwatcher_polling.cpp @@ -65,14 +65,16 @@ QStringList QPollingFileSystemWatcherEngine::addPaths(const QStringList &paths, if (!fi.exists()) continue; if (fi.isDir()) { - if (!directories->contains(path)) - directories->append(path); + if (directories->contains(path)) + continue; + directories->append(path); if (!path.endsWith(QLatin1Char('/'))) fi = QFileInfo(path + QLatin1Char('/')); this->directories.insert(path, fi); } else { - if (!files->contains(path)) - files->append(path); + if (files->contains(path)) + continue; + files->append(path); this->files.insert(path, fi); } it.remove(); diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp index df65aebcff..7dd2125e70 100644 --- a/src/corelib/io/qwindowspipereader.cpp +++ b/src/corelib/io/qwindowspipereader.cpp @@ -318,6 +318,7 @@ bool QWindowsPipeReader::waitForPipeClosed(int msecs) QElapsedTimer stopWatch; stopWatch.start(); forever { + waitForReadyRead(0); checkPipeState(); if (pipeBroken) return true; diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp index daa8068734..daad542705 100644 --- a/src/corelib/io/qwindowspipewriter.cpp +++ b/src/corelib/io/qwindowspipewriter.cpp @@ -40,7 +40,6 @@ ****************************************************************************/ #include "qwindowspipewriter_p.h" -#include <string.h> QT_BEGIN_NAMESPACE diff --git a/src/corelib/kernel/qmath.cpp b/src/corelib/kernel/qmath.cpp index b1860fa24a..9f276b4ca9 100644 --- a/src/corelib/kernel/qmath.cpp +++ b/src/corelib/kernel/qmath.cpp @@ -303,88 +303,4 @@ const qreal qt_sine_table[QT_SINE_TABLE_SIZE] = { qreal(-0.024541228522912448) }; -/*! - \headerfile <QtMath> - \title Generic Math Declarations - \ingroup funclists - - \brief The <QtMath> header file includes generic math declarations. - - These functions are partly convenience definitions for basic - operations, for instance not available in the Standard Template Library et - al. -*/ - -/*! - \fn float qDegreesToRadians(float degrees) - \relates <QtMath> - \since 5.1 - - \brief The function converts the \a degrees in float to radians. - - The purpose of the function is to aid the conversion as such a convenient - function is not part of the Standard Template Library, i.e. in <cmath> or - elsewhere. - - Example: - - \snippet code/src_corelib_kernel_qmath.cpp 0 - - \sa qRadiansToDegrees() -*/ - -/*! - \fn double qDegreesToRadians(double degrees) - \relates <QtMath> - \since 5.1 - - \brief The function converts the \a degrees in double to radians. - - The purpose of the function is to aid the conversion as such a convenient - function is not part of the Standard Template Library, i.e. in <cmath> or - elsewhere. - - Example: - - \snippet code/src_corelib_kernel_qmath.cpp 1 - - \sa qRadiansToDegrees() -*/ - -/*! - \fn float qRadiansToDegrees(float radians) - \relates <QtMath> - \since 5.1 - - \brief The function converts the \a radians in float to degrees. - - The purpose of the function is to aid the conversion as such a convenient - function is not part of the Standard Template Library, i.e. in <cmath> or - elsewhere. - - Example: - - \snippet code/src_corelib_kernel_qmath.cpp 2 - - \sa qDegreesToRadians() -*/ - -/*! - \fn double qRadiansToDegrees(double radians) - \relates <QtMath> - \since 5.1 - - \brief The function converts the \a radians in double to degrees. - - The purpose of the function is to aid the conversion as such a convenient - function is not part of the Standard Template Library, i.e. in <cmath> or - elsewhere. - - Example: - - \snippet code/src_corelib_kernel_qmath.cpp 3 - - \sa qDegreesToRadians() -*/ - QT_END_NAMESPACE diff --git a/src/corelib/kernel/qmath.qdoc b/src/corelib/kernel/qmath.qdoc index 06d8db9277..04dbbb0a3b 100644 --- a/src/corelib/kernel/qmath.qdoc +++ b/src/corelib/kernel/qmath.qdoc @@ -26,10 +26,15 @@ ****************************************************************************/ /*! - \headerfile <QtCore/qmath.h> - \title Math Functions + \headerfile <QtMath> + \title Generic Math Functions \ingroup funclists - \brief The <QtCore/qmath.h> header provides various math functions. + + \brief The <QtMath> header file provides various math functions. + + These functions are partly convenience definitions for basic math operations + not available in the C or Standard Template Libraries. + \pagekeywords math trigonometry qmath floor ceiling absolute sine cosine tangent inverse tan exponent power natural logarithm */ @@ -40,7 +45,7 @@ The ceiling is the smallest integer that is not less than \a v. For example, if \a v is 41.2, then the ceiling is 42. - \relates <QtCore/qmath.h> + \relates <QtMath> \sa qFloor() */ @@ -51,7 +56,7 @@ The floor is the largest integer that is not greater than \a v. For example, if \a v is 41.2, then the floor is 41. - \relates <QtCore/qmath.h> + \relates <QtMath> \sa qCeil() */ @@ -59,14 +64,14 @@ \fn qreal qFabs(qreal v) Returns the absolute value of \a v as a qreal. - \relates <QtCore/qmath.h> + \relates <QtMath> */ /*! \fn qreal qSin(qreal v) Returns the sine of the angle \a v in radians. - \relates <QtCore/qmath.h> + \relates <QtMath> \sa qCos(), qTan() */ @@ -74,7 +79,7 @@ \fn qreal qCos(qreal v) Returns the cosine of an angle \a v in radians. - \relates <QtCore/qmath.h> + \relates <QtMath> \sa qSin(), qTan() */ @@ -82,7 +87,7 @@ \fn qreal qTan(qreal v) Returns the tangent of an angle \a v in radians. - \relates <QtCore/qmath.h> + \relates <QtMath> \sa qSin(), qCos() */ @@ -91,7 +96,7 @@ Returns the arccosine of \a v as an angle in radians. Arccosine is the inverse operation of cosine. - \relates <QtCore/qmath.h> + \relates <QtMath> \sa qAtan(), qAsin(), qCos() */ @@ -100,7 +105,7 @@ Returns the arcsine of \a v as an angle in radians. Arcsine is the inverse operation of sine. - \relates <QtCore/qmath.h> + \relates <QtMath> \sa qSin(), qAtan(), qAcos() */ @@ -109,7 +114,7 @@ Returns the arctangent of \a v as an angle in radians. Arctangent is the inverse operation of tangent. - \relates <QtCore/qmath.h> + \relates <QtMath> \sa qTan(), qAcos(), qAsin() */ @@ -118,7 +123,7 @@ Returns the arctangent of a point specified by the coordinates \a y and \a x. This function will return the angle (argument) of that point. - \relates <QtCore/qmath.h> + \relates <QtMath> \sa qAtan() */ @@ -127,7 +132,7 @@ Returns the square root of \a v. This function returns a NaN if \a v is a negative number. - \relates <QtCore/qmath.h> + \relates <QtMath> \sa qPow() */ @@ -135,7 +140,7 @@ \fn qreal qLn(qreal v) Returns the natural logarithm of \a v. Natural logarithm uses base e. - \relates <QtCore/qmath.h> + \relates <QtMath> \sa qExp() */ @@ -143,7 +148,7 @@ \fn qreal qExp(qreal v) Returns the exponential function of \c e to the power of \a v. - \relates <QtCore/qmath.h> + \relates <QtMath> \sa qLn() */ @@ -152,6 +157,62 @@ Returns the value of \a x raised to the power of \a y. That is, \a x is the base and \a y is the exponent. - \relates <QtCore/qmath.h> + \relates <QtMath> \sa qSqrt() */ + +/*! + \fn float qDegreesToRadians(float degrees) + \relates <QtMath> + \since 5.1 + + This function converts the \a degrees in float to radians. + + Example: + + \snippet code/src_corelib_kernel_qmath.cpp 0 + + \sa qRadiansToDegrees() +*/ + +/*! + \fn double qDegreesToRadians(double degrees) + \relates <QtMath> + \since 5.1 + + This function converts the \a degrees in double to radians. + + Example: + + \snippet code/src_corelib_kernel_qmath.cpp 1 + + \sa qRadiansToDegrees() +*/ + +/*! + \fn float qRadiansToDegrees(float radians) + \relates <QtMath> + \since 5.1 + + This function converts the \a radians in float to degrees. + + Example: + + \snippet code/src_corelib_kernel_qmath.cpp 2 + + \sa qDegreesToRadians() +*/ + +/*! + \fn double qRadiansToDegrees(double radians) + \relates <QtMath> + \since 5.1 + + This function converts the \a radians in double to degrees. + + Example: + + \snippet code/src_corelib_kernel_qmath.cpp 3 + + \sa qDegreesToRadians() +*/ diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 01bedb4a3a..0e9cbfe1c9 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -4063,18 +4063,21 @@ QDebug operator<<(QDebug dbg, const QObject *o) { \macro Q_CLASSINFO(Name, Value) \relates QObject - This macro associates extra information to the class, which is - available using QObject::metaObject(). Except for the ActiveQt - extension, Qt doesn't use this information. + This macro associates extra information to the class, which is available + using QObject::metaObject(). Qt makes only limited use of this feature, in + the \l{Active Qt}, \l{Qt D-Bus} and \l{Qt QML} modules. - The extra information takes the form of a \a Name string and a \a - Value literal string. + The extra information takes the form of a \a Name string and a \a Value + literal string. Example: \snippet code/src_corelib_kernel_qobject.cpp 35 \sa QMetaObject::classInfo() + \sa QAxFactory + \sa {Using Qt D-Bus Adaptors} + \sa {Extending QML - Default Property Example} */ /*! @@ -4433,6 +4436,8 @@ void qDeleteInEventHandler(QObject *o) \snippet code/src_corelib_kernel_qobject.cpp 46 The connection will automatically disconnect if the sender is destroyed. + However, you should take care that any objects used within the functor + are still alive when the signal is emitted. \note If the compiler does not support C++11 variadic templates, the number of arguments in the signal or slot are limited to 6, and the functor object @@ -4470,6 +4475,8 @@ void qDeleteInEventHandler(QObject *o) The connection will automatically disconnect if the sender or the context is destroyed. + However, you should take care that any objects used within the functor + are still alive when the signal is emitted. \note If the compiler does not support C++11 variadic templates, the number of arguments in the signal or slot are limited to 6, and the functor object diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp index 843a6edce1..94c77302dd 100644 --- a/src/corelib/kernel/qtranslator.cpp +++ b/src/corelib/kernel/qtranslator.cpp @@ -465,6 +465,12 @@ QTranslator::~QTranslator() \li \c /opt/foolib/foo.qm \li \c /opt/foolib/foo \endlist + + Usually, it is better to use the QTranslator::load(const QLocale &, + const QString &, const QString &, const QString &, const QString &) + function instead, because it uses \l{QLocale::uiLanguages()} and not simply + the locale name, which refers to the formatting of dates and numbers and not + necessarily the UI language. */ bool QTranslator::load(const QString & filename, const QString & directory, diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index a12636778e..bdc3463b9f 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -63,6 +63,7 @@ #include <qt_windows.h> #ifdef Q_OS_WINRT +#include <qelapsedtimer.h> #include <thread> #endif @@ -680,21 +681,11 @@ bool QThread::wait(unsigned long time) break; } #else // !Q_OS_WINRT - if (d->handle->joinable()) { - HANDLE handle = d->handle->native_handle(); - switch (WaitForSingleObjectEx(handle, time, FALSE)) { - case WAIT_OBJECT_0: - ret = true; - d->handle->join(); - break; - case WAIT_FAILED: - qErrnoWarning("QThread::wait: WaitForSingleObjectEx() failed"); - break; - case WAIT_ABANDONED: - case WAIT_TIMEOUT: - default: - break; - } + if (!d->finished) { + QElapsedTimer timer; + timer.start(); + while (timer.elapsed() < time && !d->finished) + yieldCurrentThread(); } #endif // Q_OS_WINRT diff --git a/src/corelib/tools/qchar.h b/src/corelib/tools/qchar.h index 266effb66a..1955758fca 100644 --- a/src/corelib/tools/qchar.h +++ b/src/corelib/tools/qchar.h @@ -358,6 +358,9 @@ public: case QChar::Joining_Causing: return QChar::Center; case QChar::Joining_Dual: return QChar::Dual; case QChar::Joining_Right: return QChar::Right; + case QChar::Joining_None: + case QChar::Joining_Left: + case QChar::Joining_Transparent: default: return QChar::OtherJoining; } } diff --git a/src/corelib/tools/qcollator.cpp b/src/corelib/tools/qcollator.cpp index 9c97d6b158..f7dfaa7d33 100644 --- a/src/corelib/tools/qcollator.cpp +++ b/src/corelib/tools/qcollator.cpp @@ -205,6 +205,11 @@ QLocale QCollator::locale() const By default this mode is off. + \note On Windows, this functionality makes use of the \l{ICU} library. If Qt was + compiled without ICU support, it falls back to code using native Windows API, + which only works from Windows 7 onwards. On older versions of Windows, it will not work + and a warning will be emitted at runtime. + \sa numericMode() */ diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp index cadf2da019..fbcd271f1d 100644 --- a/src/corelib/tools/qregexp.cpp +++ b/src/corelib/tools/qregexp.cpp @@ -388,7 +388,7 @@ int qFindString(const QChar *haystack, int haystackLen, int from, Note: Quantifiers are normally "greedy". They always match as much text as they can. For example, \b{0+} matches the first zero it finds and all the consecutive zeros after the first zero. Applied - to '20005', it matches'2\underline{000}5'. Quantifiers can be made + to '20005', it matches '2\underline{000}5'. Quantifiers can be made non-greedy, see setMinimal(). \target capturing parentheses @@ -678,7 +678,7 @@ int qFindString(const QChar *haystack, int haystackLen, int from, QRegExp can match case insensitively using setCaseSensitivity(), and can use non-greedy matching, see setMinimal(). By default QRegExp uses full regexps but this can be changed with - setWildcard(). Searching can be forward with indexIn() or backward + setPatternSyntax(). Searching can be done forward with indexIn() or backward with lastIndexIn(). Captured text can be accessed using capturedTexts() which returns a string list of all captured strings, or using cap() which returns the captured string for the diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 2d9a42957e..359d0c49e5 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -954,6 +954,9 @@ public: case QChar::Joining_Causing: return QChar::Center; case QChar::Joining_Dual: return QChar::Dual; case QChar::Joining_Right: return QChar::Right; + case QChar::Joining_None: + case QChar::Joining_Left: + case QChar::Joining_Transparent: default: return QChar::OtherJoining; } } diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/tools/qtimezone.cpp index b30caf4289..e17ff2b249 100644 --- a/src/corelib/tools/qtimezone.cpp +++ b/src/corelib/tools/qtimezone.cpp @@ -418,6 +418,13 @@ QTimeZone::~QTimeZone() } /*! + \fn QTimeZone::swap(QTimeZone &other) + + Swaps this time zone instance with \a other. This function is very + fast and never fails. +*/ + +/*! Assignment operator, assign \a other to this. */ diff --git a/src/corelib/tools/qunicodetools.cpp b/src/corelib/tools/qunicodetools.cpp index fac795051a..fc36d07a4a 100644 --- a/src/corelib/tools/qunicodetools.cpp +++ b/src/corelib/tools/qunicodetools.cpp @@ -667,7 +667,7 @@ Q_CORE_EXPORT void initCharAttributes(const ushort *string, int length, // ---------------------------------------------------------------------------- // -// The Unicode script property. See http://www.unicode.org/reports/tr24/ (some very old version) +// The Unicode script property. See http://www.unicode.org/reports/tr24/tr24-21.html // // ---------------------------------------------------------------------------- @@ -689,15 +689,36 @@ Q_CORE_EXPORT void initScripts(const ushort *string, int length, uchar *scripts) const QUnicodeTables::Properties *prop = QUnicodeTables::properties(ucs4); - if (Q_LIKELY(prop->script == script || prop->script == QChar::Script_Inherited)) + if (Q_LIKELY(prop->script == script || prop->script <= QChar::Script_Inherited)) continue; // Never break between a combining mark (gc= Mc, Mn or Me) and its base character. // Thus, a combining mark — whatever its script property value is — should inherit // the script property value of its base character. static const int test = (FLAG(QChar::Mark_NonSpacing) | FLAG(QChar::Mark_SpacingCombining) | FLAG(QChar::Mark_Enclosing)); - if (Q_UNLIKELY(FLAG(prop->category) & test)) - continue; + if (Q_UNLIKELY(FLAG(prop->category) & test)) { + // In cases where the base character itself has the Common script property value, + // and it is followed by one or more combining marks with a specific script property value, + // it may be even better for processing to let the base acquire the script property value + // from the first mark. This approach can be generalized by treating all the characters + // of a combining character sequence as having the script property value + // of the first non-Inherited, non-Common character in the sequence if there is one, + // and otherwise treating all the characters as having the Common script property value. + if (Q_LIKELY(script > QChar::Script_Common || prop->script <= QChar::Script_Common)) + continue; + + script = QChar::Script(prop->script); + } + + if (Q_LIKELY(script != QChar::Script_Common)) { + // override preceding Common-s + while (sor > 0 && scripts[sor - 1] == QChar::Script_Common) + --sor; + } else { + // see if we are inheriting preceding run + if (sor > 0) + script = scripts[sor - 1]; + } while (sor < eor) scripts[sor++] = script; @@ -705,6 +726,15 @@ Q_CORE_EXPORT void initScripts(const ushort *string, int length, uchar *scripts) script = prop->script; } eor = length; + if (Q_LIKELY(script != QChar::Script_Common)) { + // override preceding Common-s + while (sor > 0 && scripts[sor - 1] == QChar::Script_Common) + --sor; + } else { + // see if we are inheriting preceding run + if (sor > 0) + script = scripts[sor - 1]; + } while (sor < eor) scripts[sor++] = script; } diff --git a/src/dbus/Qt5DBusMacros.cmake b/src/dbus/Qt5DBusMacros.cmake index ff497e8ebc..2364c6710c 100644 --- a/src/dbus/Qt5DBusMacros.cmake +++ b/src/dbus/Qt5DBusMacros.cmake @@ -32,6 +32,7 @@ include(MacroAddFileDependencies) +include(CMakeParseArguments) function(QT5_ADD_DBUS_INTERFACE _sources _interface _basename) get_filename_component(_infile ${_interface} ABSOLUTE) diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 5df8811f65..dd742c1bca 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1879,7 +1879,11 @@ void QGuiApplicationPrivate::processActivatedEvent(QWindowSystemInterfacePrivate return; if (previous) { - QFocusEvent focusOut(QEvent::FocusOut, e->reason); + Qt::FocusReason r = e->reason; + if ((r == Qt::OtherFocusReason || r == Qt::ActiveWindowFocusReason) && + newFocus && (newFocus->flags() & Qt::Popup) == Qt::Popup) + r = Qt::PopupFocusReason; + QFocusEvent focusOut(QEvent::FocusOut, r); QCoreApplication::sendSpontaneousEvent(previous, &focusOut); QObject::disconnect(previous, SIGNAL(focusObjectChanged(QObject*)), qApp, SLOT(_q_updateFocusObject(QObject*))); @@ -1888,7 +1892,11 @@ void QGuiApplicationPrivate::processActivatedEvent(QWindowSystemInterfacePrivate } if (QGuiApplicationPrivate::focus_window) { - QFocusEvent focusIn(QEvent::FocusIn, e->reason); + Qt::FocusReason r = e->reason; + if ((r == Qt::OtherFocusReason || r == Qt::ActiveWindowFocusReason) && + previous && (previous->flags() & Qt::Popup) == Qt::Popup) + r = Qt::PopupFocusReason; + QFocusEvent focusIn(QEvent::FocusIn, r); QCoreApplication::sendSpontaneousEvent(QGuiApplicationPrivate::focus_window, &focusIn); QObject::connect(QGuiApplicationPrivate::focus_window, SIGNAL(focusObjectChanged(QObject*)), qApp, SLOT(_q_updateFocusObject(QObject*))); diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index 7382d63a06..dbca05037b 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -61,6 +61,10 @@ #include <QDebug> +#ifndef QT_OPENGL_ES_2 +#include <QOpenGLFunctions_1_0> +#endif + QT_BEGIN_NAMESPACE class QOpenGLVersionProfilePrivate @@ -366,7 +370,9 @@ int QOpenGLContextPrivate::maxTextureSize() GLint size; GLint next = 64; funcs->glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size); + QOpenGLFunctions_1_0 *gl1funcs = q->versionFunctions<QOpenGLFunctions_1_0>(); + gl1funcs->initializeOpenGLFunctions(); + gl1funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size); if (size == 0) { return max_texture_size; } @@ -377,7 +383,7 @@ int QOpenGLContextPrivate::maxTextureSize() if (next > max_texture_size) break; funcs->glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next); + gl1funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next); } while (next > size); max_texture_size = size; diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h index b21ff67068..aa1b3b6245 100644 --- a/src/gui/kernel/qopenglcontext_p.h +++ b/src/gui/kernel/qopenglcontext_p.h @@ -127,7 +127,7 @@ private: class Q_GUI_EXPORT QOpenGLContextGroupPrivate : public QObjectPrivate { - Q_DECLARE_PUBLIC(QOpenGLContextGroup); + Q_DECLARE_PUBLIC(QOpenGLContextGroup) public: QOpenGLContextGroupPrivate() : m_context(0) diff --git a/src/gui/kernel/qplatformmenu.h b/src/gui/kernel/qplatformmenu.h index 19e2d9bccf..b88f2a7e84 100644 --- a/src/gui/kernel/qplatformmenu.h +++ b/src/gui/kernel/qplatformmenu.h @@ -86,6 +86,9 @@ public: virtual void setChecked(bool isChecked) = 0; virtual void setShortcut(const QKeySequence& shortcut) = 0; virtual void setEnabled(bool enabled) = 0; + + virtual void setNativeContents(WId item) { Q_UNUSED(item); } + Q_SIGNALS: void activated(); void hovered(); @@ -118,6 +121,8 @@ public: setVisible(true); } + virtual void dismiss() { } // Closes this and all its related menu popups + virtual QPlatformMenuItem *menuItemAt(int position) const = 0; virtual QPlatformMenuItem *menuItemForTag(quintptr tag) const = 0; diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp index eb2c98e1f5..af536fa927 100644 --- a/src/gui/opengl/qopenglfunctions.cpp +++ b/src/gui/opengl/qopenglfunctions.cpp @@ -2012,12 +2012,6 @@ void QOpenGLFunctions::initializeOpenGLFunctions() */ /*! - \fn void QOpenGLFunctions::glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params) - - \internal -*/ - -/*! \fn bool QOpenGLFunctions::isInitialized(const QOpenGLFunctionsPrivate *d) \internal */ @@ -3174,15 +3168,7 @@ static void QOPENGLF_APIENTRY qopenglfResolveGetBufferSubData(GLenum target, qop (target, offset, size, data); } -#ifndef QT_OPENGL_ES_2 -// Desktop only - -static void QOPENGLF_APIENTRY qopenglfResolveGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params) -{ - RESOLVE_FUNC_VOID(0, GetTexLevelParameteriv)(target, level, pname, params); -} - -#ifndef QT_OPENGL_DYNAMIC +#if !defined(QT_OPENGL_ES_2) && !defined(QT_OPENGL_DYNAMIC) // Special translation functions for ES-specific calls on desktop GL static void QOPENGLF_APIENTRY qopenglfTranslateClearDepthf(GLclampf depth) @@ -3194,10 +3180,7 @@ static void QOPENGLF_APIENTRY qopenglfTranslateDepthRangef(GLclampf zNear, GLcla { ::glDepthRange(zNear, zFar); } - -#endif // QT_OPENGL_DYNAMIC - -#endif // QT_OPENGL_ES2 +#endif // !ES && !DYNAMIC QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) { @@ -3256,8 +3239,6 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) TexParameteriv = qopenglfResolveTexParameteriv; TexSubImage2D = qopenglfResolveTexSubImage2D; Viewport = qopenglfResolveViewport; - - GetTexLevelParameteriv = qopenglfResolveGetTexLevelParameteriv; } else { #ifndef QT_OPENGL_DYNAMIC // Use the functions directly. This requires linking QtGui to an OpenGL implementation. @@ -3308,8 +3289,6 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *) TexParameteriv = ::glTexParameteriv; TexSubImage2D = ::glTexSubImage2D; Viewport = ::glViewport; - - GetTexLevelParameteriv = ::glGetTexLevelParameteriv; #else // QT_OPENGL_DYNAMIC // This should not happen. qFatal("QOpenGLFunctions: Dynamic OpenGL builds do not support platforms with insufficient function resolving capabilities"); diff --git a/src/gui/opengl/qopenglfunctions.h b/src/gui/opengl/qopenglfunctions.h index 03c12200d5..de1de39db2 100644 --- a/src/gui/opengl/qopenglfunctions.h +++ b/src/gui/opengl/qopenglfunctions.h @@ -407,9 +407,6 @@ public: void glVertexAttrib4fv(GLuint indx, const GLfloat* values); void glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr); - // OpenGL1, not GLES2 - void glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params); - protected: QOpenGLFunctionsPrivate *d_ptr; static bool isInitialized(const QOpenGLFunctionsPrivate *d) { return d != 0; } @@ -565,9 +562,6 @@ struct QOpenGLFunctionsPrivate void (QOPENGLF_APIENTRYP VertexAttrib4fv)(GLuint indx, const GLfloat* values); void (QOPENGLF_APIENTRYP VertexAttribPointer)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr); - // OpenGL1 only, not GLES2 - void (QOPENGLF_APIENTRYP GetTexLevelParameteriv)(GLenum target, GLint level, GLenum pname, GLint *params); - // Special non-ES OpenGL variants, not to be called directly void (QOPENGLF_APIENTRYP ClearDepth)(GLdouble depth); void (QOPENGLF_APIENTRYP DepthRange)(GLdouble zNear, GLdouble zFar); @@ -2154,24 +2148,6 @@ inline void QOpenGLFunctions::glVertexAttribPointer(GLuint indx, GLint size, GLe Q_OPENGL_FUNCTIONS_DEBUG } -// OpenGL1, not GLES2 - -inline void QOpenGLFunctions::glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params) -{ -#ifdef QT_OPENGL_ES_2 - Q_UNUSED(target); - Q_UNUSED(level); - Q_UNUSED(pname); - Q_UNUSED(params); - // Cannot get here. - qFatal("QOpenGLFunctions: glGetTexLevelParameteriv not available with OpenGL ES"); -#else - Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr)); - d_ptr->GetTexLevelParameteriv(target, level, pname, params); -#endif - Q_OPENGL_FUNCTIONS_DEBUG -} - QT_END_NAMESPACE #endif // QT_NO_OPENGL diff --git a/src/gui/opengl/qopenglshaderprogram.cpp b/src/gui/opengl/qopenglshaderprogram.cpp index bfde270446..58cb60ed92 100644 --- a/src/gui/opengl/qopenglshaderprogram.cpp +++ b/src/gui/opengl/qopenglshaderprogram.cpp @@ -2236,6 +2236,10 @@ void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix2x2& v Sets the uniform variable at \a location in the current context to a 2x3 matrix \a value. + \note This function is not aware of non square matrix support, + that is, GLSL types like mat2x3, that is present in modern OpenGL + versions. Instead, it treats the uniform as an array of vec3. + \sa setAttributeValue() */ void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix2x3& value) @@ -2251,6 +2255,10 @@ void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix2x3& value Sets the uniform variable called \a name in the current context to a 2x3 matrix \a value. + \note This function is not aware of non square matrix support, + that is, GLSL types like mat2x3, that is present in modern OpenGL + versions. Instead, it treats the uniform as an array of vec3. + \sa setAttributeValue() */ void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix2x3& value) @@ -2262,6 +2270,10 @@ void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix2x3& v Sets the uniform variable at \a location in the current context to a 2x4 matrix \a value. + \note This function is not aware of non square matrix support, + that is, GLSL types like mat2x4, that is present in modern OpenGL + versions. Instead, it treats the uniform as an array of vec4. + \sa setAttributeValue() */ void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix2x4& value) @@ -2277,6 +2289,10 @@ void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix2x4& value Sets the uniform variable called \a name in the current context to a 2x4 matrix \a value. + \note This function is not aware of non square matrix support, + that is, GLSL types like mat2x4, that is present in modern OpenGL + versions. Instead, it treats the uniform as an array of vec4. + \sa setAttributeValue() */ void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix2x4& value) @@ -2288,6 +2304,10 @@ void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix2x4& v Sets the uniform variable at \a location in the current context to a 3x2 matrix \a value. + \note This function is not aware of non square matrix support, + that is, GLSL types like mat3x2, that is present in modern OpenGL + versions. Instead, it treats the uniform as an array of vec2. + \sa setAttributeValue() */ void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix3x2& value) @@ -2303,6 +2323,10 @@ void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix3x2& value Sets the uniform variable called \a name in the current context to a 3x2 matrix \a value. + \note This function is not aware of non square matrix support, + that is, GLSL types like mat3x2, that is present in modern OpenGL + versions. Instead, it treats the uniform as an array of vec2. + \sa setAttributeValue() */ void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix3x2& value) @@ -2340,6 +2364,10 @@ void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix3x3& v Sets the uniform variable at \a location in the current context to a 3x4 matrix \a value. + \note This function is not aware of non square matrix support, + that is, GLSL types like mat3x4, that is present in modern OpenGL + versions. Instead, it treats the uniform as an array of vec4. + \sa setAttributeValue() */ void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix3x4& value) @@ -2355,6 +2383,10 @@ void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix3x4& value Sets the uniform variable called \a name in the current context to a 3x4 matrix \a value. + \note This function is not aware of non square matrix support, + that is, GLSL types like mat3x4, that is present in modern OpenGL + versions. Instead, it treats the uniform as an array of vec4. + \sa setAttributeValue() */ void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix3x4& value) @@ -2366,6 +2398,10 @@ void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix3x4& v Sets the uniform variable at \a location in the current context to a 4x2 matrix \a value. + \note This function is not aware of non square matrix support, + that is, GLSL types like mat4x2, that is present in modern OpenGL + versions. Instead, it treats the uniform as an array of vec2. + \sa setAttributeValue() */ void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix4x2& value) @@ -2381,6 +2417,10 @@ void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix4x2& value Sets the uniform variable called \a name in the current context to a 4x2 matrix \a value. + \note This function is not aware of non square matrix support, + that is, GLSL types like mat4x2, that is present in modern OpenGL + versions. Instead, it treats the uniform as an array of vec2. + \sa setAttributeValue() */ void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix4x2& value) @@ -2392,6 +2432,10 @@ void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix4x2& v Sets the uniform variable at \a location in the current context to a 4x3 matrix \a value. + \note This function is not aware of non square matrix support, + that is, GLSL types like mat4x3, that is present in modern OpenGL + versions. Instead, it treats the uniform as an array of vec3. + \sa setAttributeValue() */ void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix4x3& value) @@ -2407,6 +2451,10 @@ void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix4x3& value Sets the uniform variable called \a name in the current context to a 4x3 matrix \a value. + \note This function is not aware of non square matrix support, + that is, GLSL types like mat4x3, that is present in modern OpenGL + versions. Instead, it treats the uniform as an array of vec3. + \sa setAttributeValue() */ void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix4x3& value) diff --git a/src/gui/opengl/qopengltexture.cpp b/src/gui/opengl/qopengltexture.cpp index 078274eabd..51d35cbd59 100644 --- a/src/gui/opengl/qopengltexture.cpp +++ b/src/gui/opengl/qopengltexture.cpp @@ -180,6 +180,10 @@ bool QOpenGLTexturePrivate::create() void QOpenGLTexturePrivate::destroy() { + if (!context) { + // not created or already destroyed + return; + } if (QOpenGLContext::currentContext() != context) { qWarning("Requires a valid current OpenGL context.\n" "Texture has not been destroyed"); diff --git a/src/gui/painting/qblittable_p.h b/src/gui/painting/qblittable_p.h index 159e60079f..f65549d63c 100644 --- a/src/gui/painting/qblittable_p.h +++ b/src/gui/painting/qblittable_p.h @@ -68,7 +68,7 @@ public: // Internal ones OutlineCapability = 0x0001000 }; - Q_DECLARE_FLAGS (Capabilities, Capability); + Q_DECLARE_FLAGS (Capabilities, Capability) QBlittable(const QSize &size, Capabilities caps); virtual ~QBlittable(); diff --git a/src/gui/painting/qpaintengine_blitter.cpp b/src/gui/painting/qpaintengine_blitter.cpp index 26eacacd49..67a692e2db 100644 --- a/src/gui/painting/qpaintengine_blitter.cpp +++ b/src/gui/painting/qpaintengine_blitter.cpp @@ -238,7 +238,7 @@ private: class QBlitterPaintEnginePrivate : public QRasterPaintEnginePrivate { - Q_DECLARE_PUBLIC(QBlitterPaintEngine); + Q_DECLARE_PUBLIC(QBlitterPaintEngine) public: QBlitterPaintEnginePrivate(QBlittablePlatformPixmap *p) : QRasterPaintEnginePrivate() diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index bfcb24ae3a..ce8c1d1ca7 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.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 QtGui module of the Qt Toolkit. @@ -235,21 +235,6 @@ static const QRectF boundingRect(const QPointF *points, int pointCount) } #endif -template <typename T> static inline bool isRect(const T *pts, int elementCount) { - return (elementCount == 5 // 5-point polygon, check for closed rect - && pts[0] == pts[8] && pts[1] == pts[9] // last point == first point - && pts[0] == pts[6] && pts[2] == pts[4] // x values equal - && pts[1] == pts[3] && pts[5] == pts[7] // y values equal... - && pts[0] < pts[4] && pts[1] < pts[5] - ) || - (elementCount == 4 // 4-point polygon, check for unclosed rect - && pts[0] == pts[6] && pts[2] == pts[4] // x values equal - && pts[1] == pts[3] && pts[5] == pts[7] // y values equal... - && pts[0] < pts[4] && pts[1] < pts[5] - ); -} - - static void qt_ft_outline_move_to(qfixed x, qfixed y, void *data) { ((QOutlineMapper *) data)->moveTo(QPointF(qt_fixed_to_real(x), qt_fixed_to_real(y))); @@ -1193,22 +1178,14 @@ void QRasterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) Q_D(QRasterPaintEngine); QRasterPaintEngineState *s = state(); - const qreal *points = path.points(); - const QPainterPath::ElementType *types = path.elements(); - // There are some cases that are not supported by clip(QRect) if (op != Qt::IntersectClip || !s->clip || s->clip->hasRectClip || s->clip->hasRegionClip) { if (s->matrix.type() <= QTransform::TxScale - && ((path.shape() == QVectorPath::RectangleHint) - || (isRect(points, path.elementCount()) - && (!types || (types[0] == QPainterPath::MoveToElement - && types[1] == QPainterPath::LineToElement - && types[2] == QPainterPath::LineToElement - && types[3] == QPainterPath::LineToElement))))) { + && path.isRect()) { #ifdef QT_DEBUG_DRAW qDebug() << " --- optimizing vector clip to rect clip..."; #endif - + const qreal *points = path.points(); QRectF r(points[0], points[1], points[4]-points[0], points[5]-points[1]); if (setClipRectInDeviceCoords(s->matrix.mapRect(r).toRect(), op)) return; @@ -1939,7 +1916,7 @@ void QRasterPaintEngine::drawPolygon(const QPointF *points, int pointCount, Poly #endif Q_ASSERT(pointCount >= 2); - if (mode != PolylineMode && isRect((qreal *) points, pointCount)) { + if (mode != PolylineMode && QVectorPath::isRect((qreal *) points, pointCount)) { QRectF r(points[0], points[2]); drawRects(&r, 1); return; @@ -1980,7 +1957,7 @@ void QRasterPaintEngine::drawPolygon(const QPoint *points, int pointCount, Polyg qDebug() << " - " << points[i]; #endif Q_ASSERT(pointCount >= 2); - if (mode != PolylineMode && isRect((int *) points, pointCount)) { + if (mode != PolylineMode && QVectorPath::isRect((int *) points, pointCount)) { QRect r(points[0].x(), points[0].y(), points[2].x() - points[0].x(), diff --git a/src/gui/painting/qvectorpath_p.h b/src/gui/painting/qvectorpath_p.h index e97d6e1dce..ca95c32597 100644 --- a/src/gui/painting/qvectorpath_p.h +++ b/src/gui/painting/qvectorpath_p.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 QtGui module of the Qt Toolkit. @@ -167,6 +167,32 @@ public: return 0; } + template <typename T> static inline bool isRect(const T *pts, int elementCount) { + return (elementCount == 5 // 5-point polygon, check for closed rect + && pts[0] == pts[8] && pts[1] == pts[9] // last point == first point + && pts[0] == pts[6] && pts[2] == pts[4] // x values equal + && pts[1] == pts[3] && pts[5] == pts[7] // y values equal... + && pts[0] < pts[4] && pts[1] < pts[5] + ) || + (elementCount == 4 // 4-point polygon, check for unclosed rect + && pts[0] == pts[6] && pts[2] == pts[4] // x values equal + && pts[1] == pts[3] && pts[5] == pts[7] // y values equal... + && pts[0] < pts[4] && pts[1] < pts[5] + ); + } + + inline bool isRect() const + { + const QPainterPath::ElementType * const types = elements(); + + return (shape() == QVectorPath::RectangleHint) + || (isRect(points(), elementCount()) + && (!types || (types[0] == QPainterPath::MoveToElement + && types[1] == QPainterPath::LineToElement + && types[2] == QPainterPath::LineToElement + && types[3] == QPainterPath::LineToElement))); + } + private: Q_DISABLE_COPY(QVectorPath) diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 35950c709b..34788dc4dc 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -122,20 +122,9 @@ private: return; const int end = start + length; for (int i = start + 1; i < end; ++i) { - // According to the unicode spec we should be treating characters in the Common script - // (punctuation, spaces, etc) as being the same script as the surrounding text for the - // purpose of splitting up text. This is important because, for example, a fullstop - // (0x2E) can be used to indicate an abbreviation and so must be treated as part of a - // word. Thus it must be passed along with the word in languages that have to calculate - // word breaks. For example the thai word "ครม." has no word breaks but the word "ครม" - // does. - // Unfortuntely because we split up the strings for both wordwrapping and for setting - // the font and because Japanese and Chinese are also aliases of the script "Common", - // doing this would break too many things. So instead we only pass the full stop - // along, and nothing else. if (m_analysis[i].bidiLevel == m_analysis[start].bidiLevel && m_analysis[i].flags == m_analysis[start].flags - && (m_analysis[i].script == m_analysis[start].script || m_string[i] == QLatin1Char('.')) + && m_analysis[i].script == m_analysis[start].script && m_analysis[i].flags < QScriptAnalysis::SpaceTabOrObject && i - start < MaxItemLength) continue; @@ -1515,26 +1504,22 @@ void QTextEngine::itemize() const while (uc < e) { switch (*uc) { case QChar::ObjectReplacementCharacter: - analysis->script = QChar::Script_Common; analysis->flags = QScriptAnalysis::Object; break; case QChar::LineSeparator: if (analysis->bidiLevel % 2) --analysis->bidiLevel; - analysis->script = QChar::Script_Common; analysis->flags = QScriptAnalysis::LineOrParagraphSeparator; if (option.flags() & QTextOption::ShowLineAndParagraphSeparators) *const_cast<ushort*>(uc) = 0x21B5; // visual line separator break; case QChar::Tabulation: - analysis->script = QChar::Script_Common; analysis->flags = QScriptAnalysis::Tab; analysis->bidiLevel = control.baseLevel(); break; case QChar::Space: case QChar::Nbsp: if (option.flags() & QTextOption::ShowTabsAndSpaces) { - analysis->script = QChar::Script_Common; analysis->flags = QScriptAnalysis::Space; analysis->bidiLevel = control.baseLevel(); break; @@ -1556,8 +1541,10 @@ void QTextEngine::itemize() const #ifdef QT_ENABLE_HARFBUZZ_NG analysis = scriptAnalysis.data(); if (useHarfbuzzNG) { + // ### pretend HB-old behavior for now for (int i = 0; i < length; ++i) { switch (analysis[i].script) { + case QChar::Script_Latin: case QChar::Script_Han: case QChar::Script_Hiragana: case QChar::Script_Katakana: diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index 4b2d1c372e..db1d3dc96b 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -74,6 +74,7 @@ typedef ITypedEventHandler<StreamSocketListener *, StreamSocketListenerConnectio typedef ITypedEventHandler<DatagramSocket *, DatagramSocketMessageReceivedEventArgs *> DatagramReceivedHandler; typedef IAsyncOperationWithProgressCompletedHandler<IBuffer *, UINT32> SocketReadCompletedHandler; typedef IAsyncOperationWithProgressCompletedHandler<UINT32, UINT32> SocketWriteCompletedHandler; +typedef IAsyncOperationWithProgress<IBuffer *, UINT32> IAsyncBufferOperation; QT_BEGIN_NAMESPACE @@ -130,6 +131,8 @@ QString qt_QStringFromHSTRING(HSTRING string) return QString::fromWCharArray(rawString, length); } +#define READ_BUFFER_SIZE 8192 + class ByteArrayBuffer : public Microsoft::WRL::RuntimeClass<RuntimeClassFlags<WinRtClassicComMix>, IBuffer, Windows::Storage::Streams::IBufferByteAccess> { @@ -167,16 +170,6 @@ public: return S_OK; } - QNativeSocketEngine *engine() const - { - return m_engine; - } - - void setEngine(QNativeSocketEngine *engine) - { - m_engine = engine; - } - ComPtr<IInputStream> inputStream() const { return m_stream; @@ -190,13 +183,33 @@ public: private: QByteArray m_bytes; UINT32 m_length; - QPointer<QNativeSocketEngine> m_engine; ComPtr<IInputStream> m_stream; }; +template <typename T> +static AsyncStatus opStatus(const ComPtr<T> &op) +{ + ComPtr<IAsyncInfo> info; + HRESULT hr = op.As(&info); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to cast op to IAsyncInfo."); + return Error; + } + AsyncStatus status; + hr = info->get_Status(&status); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to get AsyncStatus."); + return Error; + } + return status; +} + QNativeSocketEngine::QNativeSocketEngine(QObject *parent) : QAbstractSocketEngine(*new QNativeSocketEnginePrivate(), parent) { + connect(this, SIGNAL(connectionReady()), SLOT(connectionNotification()), Qt::QueuedConnection); + connect(this, SIGNAL(readReady()), SLOT(readNotification()), Qt::QueuedConnection); + connect(this, SIGNAL(writeReady()), SLOT(writeNotification()), Qt::QueuedConnection); } QNativeSocketEngine::~QNativeSocketEngine() @@ -230,7 +243,7 @@ bool QNativeSocketEngine::initialize(qintptr socketDescriptor, QAbstractSocket:: // Currently, only TCP sockets are initialized this way. SocketHandler *handler = gSocketHandler(); - d->tcp = handler->pendingTcpSockets.value(socketDescriptor, Q_NULLPTR); + d->tcp = handler->pendingTcpSockets.take(socketDescriptor); d->socketType = QAbstractSocket::TcpSocket; if (!d->tcp || !d->fetchConnectionParameters()) @@ -271,23 +284,33 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port) return false; } + ComPtr<IAsyncAction> op; const QString portString = QString::number(port); HStringReference portReference(reinterpret_cast<LPCWSTR>(portString.utf16())); - ComPtr<IAsyncAction> action; HRESULT hr = E_FAIL; if (d->socketType == QAbstractSocket::TcpSocket) - hr = d->tcp->ConnectAsync(remoteHost.Get(), portReference.Get(), &action); + hr = d->tcp->ConnectAsync(remoteHost.Get(), portReference.Get(), &op); else if (d->socketType == QAbstractSocket::UdpSocket) - hr = d->udp->ConnectAsync(remoteHost.Get(), portReference.Get(), &action); + hr = d->udp->ConnectAsync(remoteHost.Get(), portReference.Get(), &op); if (FAILED(hr)) { qWarning("QNativeSocketEnginePrivate::nativeConnect:: Could not obtain connect action"); return false; } - action->put_Completed(Callback<IAsyncActionCompletedHandler>(&QNativeSocketEnginePrivate::interruptEventDispatcher).Get()); - hr = action->GetResults(); - while ((hr = action->GetResults()) == E_ILLEGAL_METHOD_CALL) - QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents); + hr = op->put_Completed(Callback<IAsyncActionCompletedHandler>( + d, &QNativeSocketEnginePrivate::handleConnectToHost).Get()); + if (FAILED(hr)) { + qErrnoWarning(hr, "Unable to set host connection callback."); + return false; + } + d->socketState = QAbstractSocket::ConnectingState; + while (opStatus(op) == Started) + d->eventLoop.processEvents(); + + AsyncStatus status = opStatus(op); + if (status == Error || status == Canceled) + return false; + if (hr == 0x8007274c) { // A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. d->setError(QAbstractSocket::NetworkError, d->ConnectionTimeOutErrorString); d->socketState = QAbstractSocket::UnconnectedState; @@ -305,24 +328,21 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port) } if (d->socketType == QAbstractSocket::TcpSocket) { - UINT32 capacity; - hr = d->inputBuffer->get_Capacity(&capacity); - if (FAILED(hr)) - return false; IInputStream *stream; hr = d->tcp->get_InputStream(&stream); if (FAILED(hr)) return false; - ByteArrayBuffer *buffer = static_cast<ByteArrayBuffer *>(d->inputBuffer.Get()); - buffer->setEngine(this); + ByteArrayBuffer *buffer = static_cast<ByteArrayBuffer *>(d->readBuffer.Get()); buffer->setInputStream(stream); - ComPtr<IAsyncOperationWithProgress<IBuffer *, UINT32>> op; - hr = stream->ReadAsync(buffer, capacity, InputStreamOptions_Partial, &op); + ComPtr<IAsyncBufferOperation> op; + hr = stream->ReadAsync(buffer, READ_BUFFER_SIZE, InputStreamOptions_Partial, &op); if (FAILED(hr)) return false; - hr = op->put_Completed(Callback<SocketReadCompletedHandler>(&QNativeSocketEnginePrivate::handleReadyRead).Get()); - if (FAILED(hr)) + hr = op->put_Completed(Callback<SocketReadCompletedHandler>(d, &QNativeSocketEnginePrivate::handleReadyRead).Get()); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to set socket read callback."); return false; + } } d->socketState = QAbstractSocket::ConnectedState; return true; @@ -358,21 +378,35 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port) d->tcpListener->add_ConnectionReceived(Callback<ClientConnectedHandler>(d, &QNativeSocketEnginePrivate::handleClientConnection).Get(), &token); hr = d->tcpListener->BindEndpointAsync(hostAddress.Get(), portString.Get(), &op); if (FAILED(hr)) { - qWarning("Unable to bind"); // ### Set error message + qErrnoWarning(hr, "Unable to bind socket."); // ### Set error message return false; } } else if (d->socketType == QAbstractSocket::UdpSocket) { hr = d->udp->BindEndpointAsync(hostAddress.Get(), portString.Get(), &op); if (FAILED(hr)) { - qWarning("unable to bind"); // ### Set error message + qErrnoWarning(hr, "Unable to bind socket."); // ### Set error message + return false; + } + hr = op->put_Completed(Callback<IAsyncActionCompletedHandler>(d, &QNativeSocketEnginePrivate::handleBindCompleted).Get()); + if (FAILED(hr)) { + qErrnoWarning(hr, "Unable to set bind callback."); return false; } } if (op) { - // Wait for connection to enter bound state - TODO: timeout, check result - while ((hr = op->GetResults()) == E_ILLEGAL_METHOD_CALL) - QCoreApplication::processEvents(); + while (opStatus(op) == Started) + d->eventLoop.processEvents(); + + AsyncStatus status = opStatus(op); + if (status == Error || status == Canceled) + return false; + + hr = op->GetResults(); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to bind socket"); + return false; + } d->socketState = QAbstractSocket::BoundState; d->fetchConnectionParameters(); @@ -410,17 +444,22 @@ int QNativeSocketEngine::accept() if (d->socketType == QAbstractSocket::TcpSocket) { IStreamSocket *socket = d->pendingConnections.takeFirst(); - UINT32 capacity; - d->inputBuffer->get_Capacity(&capacity); IInputStream *stream; socket->get_InputStream(&stream); // TODO: delete buffer and stream on socket close - ByteArrayBuffer *buffer = static_cast<ByteArrayBuffer *>(d->inputBuffer.Get()); - buffer->setEngine(this); + ByteArrayBuffer *buffer = static_cast<ByteArrayBuffer *>(d->readBuffer.Get()); buffer->setInputStream(stream); - ComPtr<IAsyncOperationWithProgress<IBuffer *, UINT32>> op; - stream->ReadAsync(buffer, capacity, InputStreamOptions_Partial, &op); - op->put_Completed(Callback<SocketReadCompletedHandler>(&QNativeSocketEnginePrivate::handleReadyRead).Get()); + ComPtr<IAsyncBufferOperation> op; + HRESULT hr = stream->ReadAsync(buffer, READ_BUFFER_SIZE, InputStreamOptions_Partial, &op); + if (FAILED(hr)) { + qErrnoWarning(hr, "Faild to read from the socket buffer."); + return -1; + } + hr = op->put_Completed(Callback<SocketReadCompletedHandler>(d, &QNativeSocketEnginePrivate::handleReadyRead).Get()); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to set socket read callback."); + return -1; + } d->currentConnections.append(socket); SocketHandler *handler = gSocketHandler(); @@ -445,7 +484,6 @@ void QNativeSocketEngine::close() d->closingDown = true; socket->Close(); socket->Release(); - closeNotification(); d->socketDescriptor = -1; } d->socketDescriptor = -1; @@ -493,13 +531,7 @@ qint64 QNativeSocketEngine::bytesAvailable() const if (d->socketType != QAbstractSocket::TcpSocket) return -1; - if (d->inputBuffer) { - UINT32 len; - d->inputBuffer->get_Length(&len); - return len; - } - - return -1; + return d->readBytes.size() - d->readBytes.pos(); } qint64 QNativeSocketEngine::read(char *data, qint64 maxlen) @@ -508,54 +540,56 @@ qint64 QNativeSocketEngine::read(char *data, qint64 maxlen) if (d->socketType != QAbstractSocket::TcpSocket) return -1; - ComPtr<IDataReaderStatics> dataReaderStatics; - GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_DataReader).Get(), &dataReaderStatics); - ComPtr<IDataReader> reader; - - dataReaderStatics->FromBuffer(d->inputBuffer.Get(), &reader); - - UINT32 bufferCapacity; - d->inputBuffer->get_Capacity(&bufferCapacity); - qint64 lengthToRead = maxlen < bufferCapacity ? maxlen : bufferCapacity; - - UINT32 bufferLength; - d->inputBuffer->get_Length(&bufferLength); - - lengthToRead = bufferLength < lengthToRead ? bufferLength : lengthToRead; - reader->ReadBytes(lengthToRead, (unsigned char*)data); - return lengthToRead; + QMutexLocker mutexLocker(&d->readMutex); + return d->readBytes.read(data, maxlen); } -template <typename T> -static qint64 nativeWrite(T *socket, const char *data, qint64 len) +qint64 QNativeSocketEngine::write(const char *data, qint64 len) { + Q_D(QNativeSocketEngine); + HRESULT hr = E_FAIL; ComPtr<IOutputStream> stream; - HRESULT hr = socket->get_OutputStream(&stream); - if (FAILED(hr)) + if (d->socketType == QAbstractSocket::TcpSocket) + hr = d->tcp->get_OutputStream(&stream); + else if (d->socketType == QAbstractSocket::UdpSocket) + hr = d->udp->get_OutputStream(&stream); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to get output stream to socket."); return -1; + } + ComPtr<ByteArrayBuffer> buffer = Make<ByteArrayBuffer>(data, len); ComPtr<IAsyncOperationWithProgress<UINT32, UINT32>> op; hr = stream->WriteAsync(buffer.Get(), &op); - if (FAILED(hr)) + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to write to socket."); + return -1; + } + hr = op->put_Completed(Callback<IAsyncOperationWithProgressCompletedHandler<UINT32, UINT32>>( + d, &QNativeSocketEnginePrivate::handleWriteCompleted).Get()); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to set socket write callback."); return -1; + } + + while (opStatus(op) == Started) + d->eventLoop.processEvents(); + + AsyncStatus status = opStatus(op); + if (status == Error || status == Canceled) + return -1; + UINT32 bytesWritten; - while ((hr = op->GetResults(&bytesWritten)) == E_ILLEGAL_METHOD_CALL) - QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); - return bytesWritten; -} + hr = op->GetResults(&bytesWritten); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to get written socket length."); + return -1; + } -qint64 QNativeSocketEngine::write(const char *data, qint64 len) -{ - Q_D(QNativeSocketEngine); - qint64 bytesWritten = -1; - if (d->socketType == QAbstractSocket::TcpSocket) - bytesWritten = nativeWrite(d->tcp, data, len); - else if (d->socketType == QAbstractSocket::UdpSocket) - bytesWritten = nativeWrite(d->udp, data, len); - if (bytesWritten != -1 && d->notifyOnWrite) - writeNotification(); - return bytesWritten; + if (bytesWritten && d->notifyOnWrite) + emit writeReady(); + return bytesWritten; } qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QHostAddress *addr, quint16 *port) @@ -698,7 +732,7 @@ bool QNativeSocketEngine::setOption(QAbstractSocketEngine::SocketOption option, bool QNativeSocketEngine::waitForRead(int msecs, bool *timedOut) { - Q_D(const QNativeSocketEngine); + Q_D(QNativeSocketEngine); Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForRead(), false); Q_CHECK_NOT_STATE(QNativeSocketEngine::waitForRead(), QAbstractSocket::UnconnectedState, false); @@ -714,14 +748,12 @@ bool QNativeSocketEngine::waitForRead(int msecs, bool *timedOut) return true; // If we are a client, we are ready to read if our buffer has data - UINT32 length; - if (FAILED(d->inputBuffer->get_Length(&length))) - return false; - if (length) + QMutexLocker locker(&d->readMutex); + if (!d->readBytes.atEnd()) return true; // Nothing to do, wait for more events - QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents|QEventLoop::WaitForMoreEvents); + d->eventLoop.processEvents(); } d->setError(QAbstractSocket::SocketTimeoutError, @@ -832,8 +864,8 @@ QNativeSocketEnginePrivate::QNativeSocketEnginePrivate() , closingDown(false) , socketDescriptor(-1) { - ComPtr<ByteArrayBuffer> buffer = Make<ByteArrayBuffer>(8192); - inputBuffer = buffer; + ComPtr<ByteArrayBuffer> buffer = Make<ByteArrayBuffer>(READ_BUFFER_SIZE); + readBuffer = buffer; } QNativeSocketEnginePrivate::~QNativeSocketEnginePrivate() @@ -1119,6 +1151,11 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters() return true; } +HRESULT QNativeSocketEnginePrivate::handleBindCompleted(IAsyncAction *, AsyncStatus) +{ + return S_OK; +} + HRESULT QNativeSocketEnginePrivate::handleClientConnection(IStreamSocketListener *listener, IStreamSocketListenerConnectionReceivedEventArgs *args) { Q_Q(QNativeSocketEngine); @@ -1126,47 +1163,91 @@ HRESULT QNativeSocketEnginePrivate::handleClientConnection(IStreamSocketListener IStreamSocket *socket; args->get_Socket(&socket); pendingConnections.append(socket); - q->connectionNotification(); - q->readNotification(); - return interruptEventDispatcher(0, Completed); + emit q->connectionReady(); + emit q->readReady(); + return S_OK; } -HRESULT QNativeSocketEnginePrivate::interruptEventDispatcher(IAsyncAction *, AsyncStatus) +HRESULT QNativeSocketEnginePrivate::handleConnectToHost(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus) { - if (QThread *thread = QThread::currentThread()) { - if (QAbstractEventDispatcher *dispatcher = thread->eventDispatcher()) - dispatcher->interrupt(); - } return S_OK; } -HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncOperationWithProgress<IBuffer *, UINT32> *asyncInfo, AsyncStatus) +HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *asyncInfo, AsyncStatus status) { + Q_Q(QNativeSocketEngine); + if (wasDeleted || isDeletingChildren) + return S_OK; + + if (status == Error || status == Canceled) + return S_OK; + ByteArrayBuffer *buffer = 0; HRESULT hr = asyncInfo->GetResults((IBuffer **)&buffer); - if (FAILED(hr)) - return hr; + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to get ready read results."); + return S_OK; + } UINT32 len; buffer->get_Length(&len); - QNativeSocketEngine *q = buffer->engine(); - if (!q) + if (!len) { + if (q->isReadNotificationEnabled()) + emit q->readReady(); + return S_OK; + } + + byte *data; + buffer->Buffer(&data); + + readMutex.lock(); + if (readBytes.atEnd()) // Everything has been read; the buffer is safe to reset + readBytes.close(); + if (!readBytes.isOpen()) + readBytes.open(QBuffer::ReadWrite|QBuffer::Truncate); + qint64 readPos = readBytes.pos(); + readBytes.seek(readBytes.size()); + Q_ASSERT(readBytes.atEnd()); + readBytes.write(reinterpret_cast<const char*>(data), qint64(len)); + readBytes.seek(readPos); + readMutex.unlock(); + + if (q->isReadNotificationEnabled()) + emit q->readReady(); + + ComPtr<IAsyncBufferOperation> op; + hr = buffer->inputStream()->ReadAsync(buffer, READ_BUFFER_SIZE, InputStreamOptions_Partial, &op); + if (FAILED(hr)) { + qErrnoWarning(hr, "Could not read into socket stream buffer."); return S_OK; - if (len > 0 && q->isReadNotificationEnabled()) { - q->readNotification(); } + hr = op->put_Completed(Callback<SocketReadCompletedHandler>(this, &QNativeSocketEnginePrivate::handleReadyRead).Get()); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to set socket read callback."); + return S_OK; + } + return S_OK; +} - // Continue reading ### TODO: read into offset!!! - UINT32 capacity; - buffer->get_Capacity(&capacity); - ComPtr<IAsyncOperationWithProgress<IBuffer *, UINT32>> op; - if (SUCCEEDED(buffer->inputStream()->ReadAsync(buffer, capacity, InputStreamOptions_Partial, &op))) { - if (q) - return op->put_Completed(Callback<SocketReadCompletedHandler>(&QNativeSocketEnginePrivate::handleReadyRead).Get()); - else - return op->put_Completed(nullptr); +HRESULT QNativeSocketEnginePrivate::handleWriteCompleted(IAsyncOperationWithProgress<UINT32, UINT32> *op, AsyncStatus status) +{ + if (status == Error) { + ComPtr<IAsyncInfo> info; + HRESULT hr = op->QueryInterface(IID_PPV_ARGS(&info)); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to cast operation."); + return S_OK; + } + HRESULT errorCode; + hr = info->get_ErrorCode(&errorCode); + if (FAILED(hr)) { + qErrnoWarning(hr, "Failed to get error code."); + return S_OK; + } + qErrnoWarning(errorCode, "A socket error occurred."); + return S_OK; } - return E_FAIL; + return S_OK; } HRESULT QNativeSocketEnginePrivate::handleNewDatagram(IDatagramSocket *socket, IDatagramSocketMessageReceivedEventArgs *args) @@ -1174,7 +1255,7 @@ HRESULT QNativeSocketEnginePrivate::handleNewDatagram(IDatagramSocket *socket, I Q_Q(QNativeSocketEngine); Q_ASSERT(udp == socket); pendingDatagrams.append(args); - q->readNotification(); + emit q->readReady(); return S_OK; } diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h index b5be5fa830..ec2e1b3ad4 100644 --- a/src/network/socket/qnativesocketengine_winrt_p.h +++ b/src/network/socket/qnativesocketengine_winrt_p.h @@ -52,6 +52,8 @@ // // We mean it. // +#include <QtCore/QEventLoop> +#include <QtCore/QBuffer> #include "QtNetwork/qhostaddress.h" #include "private/qabstractsocketengine_p.h" #include <wrl.h> @@ -127,6 +129,11 @@ public: bool isExceptionNotificationEnabled() const; void setExceptionNotificationEnabled(bool enable); +signals: + void connectionReady(); + void readReady(); + void writeReady(); + private: Q_DECLARE_PRIVATE(QNativeSocketEngine) Q_DISABLE_COPY(QNativeSocketEngine) @@ -191,17 +198,22 @@ private: ABI::Windows::Networking::Sockets::IDatagramSocket *udp; }; Microsoft::WRL::ComPtr<ABI::Windows::Networking::Sockets::IStreamSocketListener> tcpListener; - Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IBuffer> inputBuffer; + Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IBuffer> readBuffer; + QBuffer readBytes; + QMutex readMutex; QList<ABI::Windows::Networking::Sockets::IDatagramSocketMessageReceivedEventArgs *> pendingDatagrams; QList<ABI::Windows::Networking::Sockets::IStreamSocket *> pendingConnections; QList<ABI::Windows::Networking::Sockets::IStreamSocket *> currentConnections; + QEventLoop eventLoop; + HRESULT handleBindCompleted(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus); HRESULT handleNewDatagram(ABI::Windows::Networking::Sockets::IDatagramSocket *socket, ABI::Windows::Networking::Sockets::IDatagramSocketMessageReceivedEventArgs *args); HRESULT handleClientConnection(ABI::Windows::Networking::Sockets::IStreamSocketListener *tcpListener, ABI::Windows::Networking::Sockets::IStreamSocketListenerConnectionReceivedEventArgs *args); - static HRESULT interruptEventDispatcher(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus); - static HRESULT handleReadyRead(ABI::Windows::Foundation::IAsyncOperationWithProgress<ABI::Windows::Storage::Streams::IBuffer *, UINT32> *asyncInfo, ABI::Windows::Foundation::AsyncStatus); + HRESULT handleConnectToHost(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus); + HRESULT handleReadyRead(ABI::Windows::Foundation::IAsyncOperationWithProgress<ABI::Windows::Storage::Streams::IBuffer *, UINT32> *asyncInfo, ABI::Windows::Foundation::AsyncStatus); + HRESULT handleWriteCompleted(ABI::Windows::Foundation::IAsyncOperationWithProgress<UINT32, UINT32> *, ABI::Windows::Foundation::AsyncStatus); }; QT_END_NAMESPACE diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 2b49e4d2d1..2ec4434d57 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -223,11 +223,19 @@ void QGL2PaintEngineExPrivate::updateBrushTexture() if (currentBrushPixmap.width() > max_texture_size || currentBrushPixmap.height() > max_texture_size) currentBrushPixmap = currentBrushPixmap.scaled(max_texture_size, max_texture_size, Qt::KeepAspectRatio); + GLuint wrapMode = GL_REPEAT; + if (ctx->contextHandle()->isES()) { + // OpenGL ES does not support GL_REPEAT wrap modes for NPOT textures. So instead, + // we emulate GL_REPEAT by only taking the fractional part of the texture coords + // in the qopenglslTextureBrushSrcFragmentShader program. + wrapMode = GL_CLAMP_TO_EDGE; + } + funcs.glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); QGLTexture *tex = ctx->d_func()->bindTexture(currentBrushPixmap, GL_TEXTURE_2D, GL_RGBA, QGLContext::InternalBindOption | QGLContext::CanFlipNativePixmapBindOption); - updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform); + updateTextureFilter(GL_TEXTURE_2D, wrapMode, q->state()->renderHints & QPainter::SmoothPixmapTransform); textureInvertedY = tex->options & QGLContext::InvertedYBindOption ? -1 : 1; } brushTextureDirty = false; diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 3cfdcc549c..d73109dfd9 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -2497,7 +2497,19 @@ QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, } if (!texture) { - QImage image = pixmap.toImage(); + QImage image; + QPaintEngine* paintEngine = pixmap.paintEngine(); + if (!paintEngine || paintEngine->type() != QPaintEngine::Raster) + image = pixmap.toImage(); + else { + // QRasterPixmapData::toImage() will deep-copy the backing QImage if there's an active QPainter on it. + // For performance reasons, we don't want that here, so we temporarily redirect the paint engine. + QPaintDevice* currentPaintDevice = paintEngine->paintDevice(); + paintEngine->setPaintDevice(0); + image = pixmap.toImage(); + paintEngine->setPaintDevice(currentPaintDevice); + } + // If the system depth is 16 and the pixmap doesn't have an alpha channel // then we convert it to RGB16 in the hope that it gets uploaded as a 16 // bit texture which is much faster to access than a 32-bit one. diff --git a/src/platformsupport/eglconvenience/qeglconvenience.cpp b/src/platformsupport/eglconvenience/qeglconvenience.cpp index e6624fb9ff..ed18a23c4f 100644 --- a/src/platformsupport/eglconvenience/qeglconvenience.cpp +++ b/src/platformsupport/eglconvenience/qeglconvenience.cpp @@ -66,26 +66,30 @@ QVector<EGLint> q_createConfigAttributesFromFormat(const QSurfaceFormat &format) int stencilSize = format.stencilBufferSize(); int sampleCount = format.samples(); - // We want to make sure 16-bit configs are chosen over 32-bit configs as they will provide - // the best performance. The EGL config selection algorithm is a bit stange in this regard: - // The selection criteria for EGL_BUFFER_SIZE is "AtLeast", so we can't use it to discard - // 32-bit configs completely from the selection. So it then comes to the sorting algorithm. - // The red/green/blue sizes have a sort priority of 3, so they are sorted by first. The sort - // order is special and described as "by larger _total_ number of color bits.". So EGL will - // put 32-bit configs in the list before the 16-bit configs. However, the spec also goes on - // to say "If the requested number of bits in attrib_list for a particular component is 0, - // then the number of bits for that component is not considered". This part of the spec also - // seems to imply that setting the red/green/blue bits to zero means none of the components - // are considered and EGL disregards the entire sorting rule. It then looks to the next - // highest priority rule, which is EGL_BUFFER_SIZE. Despite the selection criteria being - // "AtLeast" for EGL_BUFFER_SIZE, it's sort order is "smaller" meaning 16-bit configs are - // put in the list before 32-bit configs. So, to make sure 16-bit is preffered over 32-bit, - // we must set the red/green/blue sizes to zero. This has an unfortunate consequence that - // if the application sets the red/green/blue size to 5/6/5 on the QSurfaceFormat, - // they might still get a 32-bit config, even when there's an RGB565 config available. - QVector<EGLint> configAttributes; + // Map default, unspecified values (-1) to 0. This is important due to sorting rule #3 + // in section 3.4.1 of the spec and allows picking a potentially faster 16-bit config + // over 32-bit ones when there is no explicit request for the color channel sizes: + // + // The red/green/blue sizes have a sort priority of 3, so they are sorted by + // first. (unless a caveat like SLOW or NON_CONFORMANT is present) The sort order is + // Special and described as "by larger _total_ number of color bits.". So EGL will put + // 32-bit configs in the list before the 16-bit configs. However, the spec also goes + // on to say "If the requested number of bits in attrib_list for a particular + // component is 0, then the number of bits for that component is not considered". This + // part of the spec also seems to imply that setting the red/green/blue bits to zero + // means none of the components are considered and EGL disregards the entire sorting + // rule. It then looks to the next highest priority rule, which is + // EGL_BUFFER_SIZE. Despite the selection criteria being "AtLeast" for + // EGL_BUFFER_SIZE, it's sort order is "smaller" meaning 16-bit configs are put in the + // list before 32-bit configs. + // + // This also means that explicitly specifying a size like 565 will still result in + // having larger (888) configs first in the returned list. We need to handle this + // ourselves later by manually filtering the list, instead of just blindly taking the + // first config from it. + configAttributes.append(EGL_RED_SIZE); configAttributes.append(redSize > 0 ? redSize : 0); @@ -293,6 +297,13 @@ EGLConfig QEglConfigChooser::chooseConfig() if (!cfg && matching > 0) cfg = configs.first(); + // Filter the list. Due to the EGL sorting rules configs with higher depth are + // placed first when the minimum color channel sizes have been specified (i.e. the + // QSurfaceFormat contains color sizes > 0). To prevent returning a 888 config + // when the QSurfaceFormat explicitly asked for 565, go through the returned + // configs and look for one that exactly matches the requested sizes. When no + // sizes have been given, take the first, which will be a config with the smaller + // (e.g. 16-bit) depth. for (int i = 0; i < configs.size(); ++i) { if (filterConfig(configs[i])) return configs.at(i); @@ -306,6 +317,8 @@ EGLConfig QEglConfigChooser::chooseConfig() bool QEglConfigChooser::filterConfig(EGLConfig config) const { + // If we are fine with the highest depth (e.g. RGB888 configs) even when something + // smaller (565) was explicitly requested, do nothing. if (m_ignore) return true; @@ -314,6 +327,7 @@ bool QEglConfigChooser::filterConfig(EGLConfig config) const EGLint blue = 0; EGLint alpha = 0; + // Compare only if a size was given. Otherwise just accept. if (m_confAttrRed) eglGetConfigAttrib(display(), config, EGL_RED_SIZE, &red); if (m_confAttrGreen) diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h index 74a25c1370..9493218024 100644 --- a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h +++ b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h @@ -197,7 +197,7 @@ public: Privacy = 0x1 }; - Q_DECLARE_FLAGS(ApFlags, ApFlag); + Q_DECLARE_FLAGS(ApFlags, ApFlag) enum ApSecurityFlag { ApSecurityNone = 0x0, @@ -213,7 +213,7 @@ public: Key8021x = 0x200 }; - Q_DECLARE_FLAGS(ApSecurityFlags, ApSecurityFlag); + Q_DECLARE_FLAGS(ApSecurityFlags, ApSecurityFlag) explicit QNetworkManagerInterfaceAccessPoint(const QString &dbusPathName, QObject *parent = 0); ~QNetworkManagerInterfaceAccessPoint(); diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp index 3324d9ba49..02fda19d76 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.cpp +++ b/src/plugins/platforms/android/qandroidinputcontext.cpp @@ -338,7 +338,7 @@ static JNINativeMethod methods[] = { QAndroidInputContext::QAndroidInputContext() - : QPlatformInputContext(), m_blockUpdateSelection(false), m_batchEditNestingLevel(0) + : QPlatformInputContext(), m_blockUpdateSelection(false), m_batchEditNestingLevel(0), m_focusObject(0) { QtAndroid::AttachedJNIEnv env; if (!env.jniEnv) @@ -532,6 +532,18 @@ void QAndroidInputContext::clear() m_extractedText.clear(); } + +void QAndroidInputContext::setFocusObject(QObject *object) +{ + if (object != m_focusObject) { + m_focusObject = object; + if (!m_composingText.isEmpty()) + finishComposingText(); + reset(); + } + QPlatformInputContext::setFocusObject(object); +} + void QAndroidInputContext::sendEvent(QObject *receiver, QInputMethodEvent *event) { QCoreApplication::sendEvent(receiver, event); @@ -678,7 +690,7 @@ QString QAndroidInputContext::getTextBeforeCursor(jint length, jint /*flags*/) { QVariant textBefore = queryFocusObjectThreadSafe(Qt::ImTextBeforeCursor, QVariant(length)); if (textBefore.isValid()) { - return textBefore.toString().left(length) + m_composingText; + return textBefore.toString().right(length) + m_composingText; } //compatibility code for old controls that do not implement the new API diff --git a/src/plugins/platforms/android/qandroidinputcontext.h b/src/plugins/platforms/android/qandroidinputcontext.h index f7b29a855f..3ce141ae15 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.h +++ b/src/plugins/platforms/android/qandroidinputcontext.h @@ -95,6 +95,7 @@ public: bool isComposing() const; void clear(); + void setFocusObject(QObject *object); //---------------// jboolean beginBatchEdit(); @@ -136,6 +137,7 @@ private: QMetaObject::Connection m_updateCursorPosConnection; bool m_blockUpdateSelection; int m_batchEditNestingLevel; + QObject *m_focusObject; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm index 1df4230385..dd3b9f53db 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm @@ -168,6 +168,14 @@ // TODO: multi-selection: NSAccessibilitySelectedTextRangesAttribute, } + if (iface->valueInterface()) { + [attributes addObjectsFromArray: [[NSArray alloc] initWithObjects: + NSAccessibilityMinValueAttribute, + NSAccessibilityMaxValueAttribute, + nil + ]]; + } + return [attributes autorelease]; } @@ -191,6 +199,19 @@ return [QCocoaAccessibleElement elementWithId: parentId]; } + +- (id) minValueAttribute:(QAccessibleInterface*)iface { + if (QAccessibleValueInterface *val = iface->valueInterface()) + return [NSNumber numberWithDouble: val->minimumValue().toDouble()]; + return nil; +} + +- (id) maxValueAttribute:(QAccessibleInterface*)iface { + if (QAccessibleValueInterface *val = iface->valueInterface()) + return [NSNumber numberWithDouble: val->maximumValue().toDouble()]; + return nil; +} + - (id)accessibilityAttributeValue:(NSString *)attribute { QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); if (!iface) { @@ -272,6 +293,10 @@ return [NSNumber numberWithInt: textBeforeCursor.count(QLatin1Char('\n'))]; } return nil; + } else if ([attribute isEqualToString:NSAccessibilityMinValueAttribute]) { + return [self minValueAttribute:iface]; + } else if ([attribute isEqualToString:NSAccessibilityMaxValueAttribute]) { + return [self maxValueAttribute:iface]; } return nil; @@ -332,7 +357,7 @@ startOffset = text.indexOf(QLatin1Char('\n'), startOffset) + 1; if (startOffset < 0) // invalid line number, return the first line startOffset = 0; - int endOffset = text.indexOf(QLatin1Char('\n'), startOffset + 1); + int endOffset = text.indexOf(QLatin1Char('\n'), startOffset); if (endOffset == -1) endOffset = text.length(); return [NSValue valueWithRange:NSMakeRange(quint32(startOffset), quint32(endOffset - startOffset))]; @@ -359,6 +384,12 @@ if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) { return iface->state().focusable ? YES : NO; + } else if ([attribute isEqualToString:NSAccessibilityValueAttribute]) { + if (iface->textInterface() && iface->state().editable) + return YES; + if (iface->valueInterface()) + return YES; + return NO; } else if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) { return iface->textInterface() ? YES : NO; } @@ -372,6 +403,14 @@ if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) { if (QAccessibleActionInterface *action = iface->actionInterface()) action->doAction(QAccessibleActionInterface::setFocusAction()); + } else if ([attribute isEqualToString:NSAccessibilityValueAttribute]) { + if (iface->textInterface()) { + QString text = QString::fromNSString((NSString *)value); + iface->setText(QAccessible::Value, text); + } else if (QAccessibleValueInterface *valueIface = iface->valueInterface()) { + double val = [value doubleValue]; + valueIface->setCurrentValue(val); + } } else if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) { if (QAccessibleTextInterface *text = iface->textInterface()) { NSRange range = [value rangeValue]; diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h index 0274ed8201..de6c6585e9 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h @@ -134,6 +134,8 @@ public: void interrupt(); void flush(); + bool event(QEvent *); + friend void qt_mac_maybeCancelWaitForMoreEventsForwarder(QAbstractEventDispatcher *eventDispatcher); }; @@ -163,7 +165,6 @@ public: // The following variables help organizing modal sessions: QStack<QCocoaModalSessionInfo> cocoaModalSessionStack; bool currentExecIsNSAppRun; - bool modalSessionOnNSAppRun; bool nsAppRunCalledByQt; bool cleanupModalSessionsNeeded; uint processEventsCalled; diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index 495a54cac4..e0ce9f9648 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -734,13 +734,25 @@ void QCocoaEventDispatcherPrivate::beginModalSession(QWindow *window) updateChildrenWorksWhenModal(); currentModalSessionCached = 0; if (currentExecIsNSAppRun) { - modalSessionOnNSAppRun = true; - q->wakeUp(); + QEvent *e = new QEvent(QEvent::User); + qApp->postEvent(q, e, Qt::HighEventPriority); } else { q->interrupt(); } } +bool QCocoaEventDispatcher::event(QEvent *e) +{ + Q_D(QCocoaEventDispatcher); + + if (e->type() == QEvent::User) { + d->q_func()->processEvents(QEventLoop::DialogExec | QEventLoop::EventLoopExec | QEventLoop::WaitForMoreEvents); + return true; + } + + return QObject::event(e); +} + void QCocoaEventDispatcherPrivate::endModalSession(QWindow *window) { Q_Q(QCocoaEventDispatcher); @@ -777,7 +789,6 @@ QCocoaEventDispatcherPrivate::QCocoaEventDispatcherPrivate() runLoopTimerRef(0), blockSendPostedEvents(false), currentExecIsNSAppRun(false), - modalSessionOnNSAppRun(false), nsAppRunCalledByQt(false), cleanupModalSessionsNeeded(false), processEventsCalled(0), @@ -908,14 +919,6 @@ void QCocoaEventDispatcherPrivate::postedEventsSourceCallback(void *info) // processEvents() was called "manually," ignore this source for now d->maybeCancelWaitForMoreEvents(); return; - } else if (d->modalSessionOnNSAppRun) { - // We're about to spawn the 1st modal session on top of the main runloop. - // Instead of calling processPostedEvents(), which would need us stop - // NSApp, we just re-enter processEvents(). This is equivalent to calling - // QDialog::exec() except that it's done in a non-blocking way. - d->modalSessionOnNSAppRun = false; - d->q_func()->processEvents(QEventLoop::DialogExec | QEventLoop::EventLoopExec | QEventLoop::WaitForMoreEvents); - return; } d->processPostedEvents(); d->maybeCancelWaitForMoreEvents(); diff --git a/src/plugins/platforms/cocoa/qcocoamenu.h b/src/plugins/platforms/cocoa/qcocoamenu.h index 59fda96dff..3ee1dab84d 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.h +++ b/src/plugins/platforms/cocoa/qcocoamenu.h @@ -68,6 +68,7 @@ public: void setEnabled(bool enabled); void setVisible(bool visible); void showPopup(const QWindow *parentWindow, QPoint pos, const QPlatformMenuItem *item); + void dismiss(); void syncSeparatorsCollapsible(bool enable); diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index 6acc062eb9..44bc3b8f69 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -490,6 +490,11 @@ void QCocoaMenu::showPopup(const QWindow *parentWindow, QPoint pos, const QPlatf [(QNSView *)view resetMouseButtons]; } +void QCocoaMenu::dismiss() +{ + [m_nativeMenu cancelTracking]; +} + QPlatformMenuItem *QCocoaMenu::menuItemAt(int position) const { if (0 <= position && position < m_menuItems.count()) diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm index ffc0fabdce..aceb9b619b 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.mm +++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm @@ -124,6 +124,8 @@ void QCocoaMenuBar::insertMenu(QPlatformMenu *platformMenu, QPlatformMenu *befor m_menus.insert(beforeMenu ? m_menus.indexOf(beforeMenu) : m_menus.size(), menu); if (!menu->menuBar()) insertNativeMenu(menu, beforeMenu); + if (m_window && m_window->window()->isActive()) + updateMenuBarImmediately(); } void QCocoaMenuBar::removeNativeMenu(QCocoaMenu *menu) diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.h b/src/plugins/platforms/cocoa/qcocoamenuitem.h index 61706c19bc..1efc9f9bfd 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.h +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.h @@ -57,6 +57,7 @@ QT_FORWARD_DECLARE_OBJC_CLASS(NSMenuItem); QT_FORWARD_DECLARE_OBJC_CLASS(NSMenu); QT_FORWARD_DECLARE_OBJC_CLASS(NSObject); +QT_FORWARD_DECLARE_OBJC_CLASS(NSView); QT_BEGIN_NAMESPACE @@ -86,6 +87,8 @@ public: void setChecked(bool isChecked); void setEnabled(bool isEnabled); + void setNativeContents(WId item); + inline QString text() const { return m_text; } inline NSMenuItem * nsItem() { return m_native; } NSMenuItem *sync(); @@ -105,6 +108,7 @@ private: QKeySequence mergeAccel(); NSMenuItem *m_native; + NSView *m_itemView; QString m_text; bool m_textSynced; QIcon m_icon; diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm index 58fe07bc62..99d26034bf 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm @@ -91,6 +91,7 @@ NSUInteger keySequenceModifierMask(const QKeySequence &accel) QCocoaMenuItem::QCocoaMenuItem() : m_native(NULL), + m_itemView(nil), m_textSynced(false), m_menu(NULL), m_isVisible(true), @@ -110,6 +111,8 @@ QCocoaMenuItem::~QCocoaMenuItem() } else { [m_native release]; } + + [m_itemView release]; } void QCocoaMenuItem::setText(const QString &text) @@ -178,6 +181,17 @@ void QCocoaMenuItem::setEnabled(bool enabled) m_enabled = enabled; } +void QCocoaMenuItem::setNativeContents(WId item) +{ + NSView *itemView = (NSView *)item; + [m_itemView release]; + m_itemView = [itemView retain]; + [m_itemView setAutoresizesSubviews:YES]; + [m_itemView setAutoresizingMask:NSViewWidthSizable]; + [m_itemView setHidden:NO]; + [m_itemView setNeedsDisplay:YES]; +} + NSMenuItem *QCocoaMenuItem::sync() { if (m_isSeparator != [m_native isSeparatorItem]) { @@ -281,6 +295,7 @@ NSMenuItem *QCocoaMenuItem::sync() [m_native setHidden: !m_isVisible]; [m_native setEnabled: m_enabled]; + [m_native setView:m_itemView]; QString text = mergeText(); QKeySequence accel = mergeAccel(); diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 0b9683a3ef..5d20764c87 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -42,6 +42,7 @@ #include <QtCore/qglobal.h> #include <Carbon/Carbon.h> +#include <dlfcn.h> #include "qnsview.h" #include "qcocoawindow.h" @@ -65,6 +66,9 @@ static QTouchDevice *touchDevice = 0; +// ### HACK Remove once 10.8 is unsupported +static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; + @interface NSEvent (Qt_Compile_Leopard_DeviceDelta) - (CGFloat)deviceDeltaX; - (CGFloat)deviceDeltaY; @@ -73,6 +77,13 @@ static QTouchDevice *touchDevice = 0; @implementation QNSView ++ (void)initialize +{ + NSString **notificationNameVar = (NSString **)dlsym(RTLD_NEXT, "NSWindowDidChangeOcclusionStateNotification"); + if (notificationNameVar) + _q_NSWindowDidChangeOcclusionStateNotification = *notificationNameVar; +} + - (id) init { self = [super initWithFrame : NSMakeRect(0,0, 300,300)]; @@ -192,6 +203,19 @@ static QTouchDevice *touchDevice = 0; } } +- (void)viewDidMoveToWindow +{ + if (self.window) { + // This is the case of QWidgetAction's generated QWidget inserted in an NSMenu. + // 10.9 and newer get the NSWindowDidChangeOcclusionStateNotification + if (!_q_NSWindowDidChangeOcclusionStateNotification + && [self.window.className isEqualToString:@"NSCarbonMenuWindow"]) + m_platformWindow->exposeWindow(); + } else { + m_platformWindow->obscureWindow(); + } +} + - (void)viewWillMoveToWindow:(NSWindow *)newWindow { // ### Merge "normal" window code path with this one for 5.1. @@ -325,6 +349,23 @@ static QTouchDevice *touchDevice = 0; m_platformWindow->obscureWindow(); } else if ([notificationName isEqualToString: @"NSWindowDidOrderOnScreenAndFinishAnimatingNotification"]) { m_platformWindow->exposeWindow(); + } else if (_q_NSWindowDidChangeOcclusionStateNotification + && [notificationName isEqualToString:_q_NSWindowDidChangeOcclusionStateNotification]) { +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9 +// ### HACK Remove the enum declaration, the warning disabling and the cast further down once 10.8 is unsupported +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-method-access" + enum { NSWindowOcclusionStateVisible = 1UL << 1 }; +#endif + // Older versions managed in -[QNSView viewDidMoveToWindow]. + // Support QWidgetAction in NSMenu. Mavericks only sends this notification. + // Ideally we should support this in Qt as well, in order to disable animations + // when the window is occluded. + if ((NSUInteger)[self.window occlusionState] & NSWindowOcclusionStateVisible) + m_platformWindow->exposeWindow(); +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9 +#pragma clang diagnostic pop +#endif } else if (notificationName == NSWindowDidChangeScreenNotification) { if (m_window) { NSUInteger screenIndex = [[NSScreen screens] indexOfObject:self.window.screen]; @@ -639,8 +680,12 @@ static QTouchDevice *touchDevice = 0; if (m_platformWindow->m_activePopupWindow) { QWindowSystemInterface::handleCloseEvent(m_platformWindow->m_activePopupWindow); QWindowSystemInterface::flushWindowSystemEvents(); + Qt::WindowType type = m_platformWindow->m_activePopupWindow->type(); m_platformWindow->m_activePopupWindow = 0; - return; + // Consume the mouse event when closing the popup, except for tool tips + // were it's expected that the event is processed normally. + if (type != Qt::ToolTip) + return; } if ([self hasMarkedText]) { NSInputManager* inputManager = [NSInputManager currentInputManager]; diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dhelpers.h b/src/plugins/platforms/direct2d/qwindowsdirect2dhelpers.h index 98248515e6..3be05ee1e0 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dhelpers.h +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dhelpers.h @@ -84,8 +84,6 @@ Q_DECL_CONSTEXPR inline D2D1::ColorF to_d2d_color_f(const QColor &c) Q_DECL_CONSTEXPR inline D2D1_MATRIX_3X2_F to_d2d_matrix_3x2_f(const QTransform &transform) { - Q_ASSERT(transform.isAffine()); - return D2D1::Matrix3x2F(transform.m11(), transform.m12(), transform.m21(), transform.m22(), transform.m31(), transform.m32()); diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp index d8f34fc3ed..1e7c175252 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.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. @@ -52,6 +52,7 @@ #include "qwindowsfontdatabase.h" #include "qwindowsintegration.h" +#include <QtCore/QStack> #include <QtGui/private/qpaintengine_p.h> #include <QtGui/private/qtextengine_p.h> #include <QtGui/private/qfontengine_p.h> @@ -80,9 +81,14 @@ enum { //Clipping flags enum { - UserClip = 0x1, - SimpleSystemClip = 0x2 + SimpleSystemClip = 0x1 }; + +enum ClipType { + AxisAlignedClip, + LayerClip +}; + #define D2D_TAG(tag) d->dc()->SetTags(tag, tag) Q_GUI_EXPORT QImage qt_imageForBrush(int brushStyle, bool invert); @@ -92,51 +98,124 @@ static inline ID2D1Factory1 *factory() return QWindowsDirect2DContext::instance()->d2dFactory(); } -// XXX reduce code duplication between painterPathToPathGeometry and -// vectorPathToID2D1PathGeometry, the two are quite similar - -static ComPtr<ID2D1PathGeometry1> painterPathToPathGeometry(const QPainterPath &path) +class Direct2DPathGeometryWriter { - ComPtr<ID2D1PathGeometry1> geometry; - ComPtr<ID2D1GeometrySink> sink; +public: + Direct2DPathGeometryWriter() + : m_inFigure(false) + , m_roundCoordinates(false) + { - HRESULT hr = factory()->CreatePathGeometry(&geometry); - if (FAILED(hr)) { - qWarning("%s: Could not create path geometry: %#x", __FUNCTION__, hr); - return NULL; } - hr = geometry->Open(&sink); - if (FAILED(hr)) { - qWarning("%s: Could not create geometry sink: %#x", __FUNCTION__, hr); - return NULL; + bool begin() + { + HRESULT hr = factory()->CreatePathGeometry(&m_geometry); + if (FAILED(hr)) { + qWarning("%s: Could not create path geometry: %#x", __FUNCTION__, hr); + return false; + } + + hr = m_geometry->Open(&m_sink); + if (FAILED(hr)) { + qWarning("%s: Could not create geometry sink: %#x", __FUNCTION__, hr); + return false; + } + + return true; } - switch (path.fillRule()) { - case Qt::WindingFill: - sink->SetFillMode(D2D1_FILL_MODE_WINDING); - break; - case Qt::OddEvenFill: - sink->SetFillMode(D2D1_FILL_MODE_ALTERNATE); - break; + void setWindingFillEnabled(bool enable) + { + if (enable) + m_sink->SetFillMode(D2D1_FILL_MODE_WINDING); + else + m_sink->SetFillMode(D2D1_FILL_MODE_ALTERNATE); + } + + void setAliasingEnabled(bool enable) + { + m_roundCoordinates = enable; + } + + bool isInFigure() const + { + return m_inFigure; + } + + void moveTo(const QPointF &point) + { + if (m_inFigure) + m_sink->EndFigure(D2D1_FIGURE_END_OPEN); + + m_sink->BeginFigure(adjusted(point), D2D1_FIGURE_BEGIN_FILLED); + m_inFigure = true; + } + + void lineTo(const QPointF &point) + { + m_sink->AddLine(adjusted(point)); + } + + void curveTo(const QPointF &p1, const QPointF &p2, const QPointF &p3) + { + D2D1_BEZIER_SEGMENT segment = { + adjusted(p1), + adjusted(p2), + adjusted(p3) + }; + + m_sink->AddBezier(segment); + } + + void close() + { + if (m_inFigure) + m_sink->EndFigure(D2D1_FIGURE_END_OPEN); + + m_sink->Close(); + } + + ComPtr<ID2D1PathGeometry1> geometry() const + { + return m_geometry; + } + +private: + D2D1_POINT_2F adjusted(const QPointF &point) + { + if (m_roundCoordinates) + return to_d2d_point_2f(point.toPoint()); + else + return to_d2d_point_2f(point); } - bool inFigure = false; + ComPtr<ID2D1PathGeometry1> m_geometry; + ComPtr<ID2D1GeometrySink> m_sink; + + bool m_inFigure; + bool m_roundCoordinates; +}; + +static ComPtr<ID2D1PathGeometry1> painterPathToID2D1PathGeometry(const QPainterPath &path, bool alias) +{ + Direct2DPathGeometryWriter writer; + if (!writer.begin()) + return NULL; + + writer.setWindingFillEnabled(path.fillRule() == Qt::WindingFill); + writer.setAliasingEnabled(alias); for (int i = 0; i < path.elementCount(); i++) { const QPainterPath::Element element = path.elementAt(i); switch (element.type) { case QPainterPath::MoveToElement: - if (inFigure) - sink->EndFigure(D2D1_FIGURE_END_OPEN); - - sink->BeginFigure(to_d2d_point_2f(element), D2D1_FIGURE_BEGIN_FILLED); - inFigure = true; + writer.moveTo(element); break; case QPainterPath::LineToElement: - sink->AddLine(to_d2d_point_2f(element)); + writer.lineTo(element); break; case QPainterPath::CurveToElement: @@ -149,13 +228,7 @@ static ComPtr<ID2D1PathGeometry1> painterPathToPathGeometry(const QPainterPath & Q_ASSERT(data1.type == QPainterPath::CurveToDataElement); Q_ASSERT(data2.type == QPainterPath::CurveToDataElement); - D2D1_BEZIER_SEGMENT segment; - - segment.point1 = to_d2d_point_2f(element); - segment.point2 = to_d2d_point_2f(data1); - segment.point3 = to_d2d_point_2f(data2); - - sink->AddBezier(segment); + writer.curveTo(element, data1, data2); } break; @@ -165,55 +238,22 @@ static ComPtr<ID2D1PathGeometry1> painterPathToPathGeometry(const QPainterPath & } } - if (inFigure) - sink->EndFigure(D2D1_FIGURE_END_OPEN); - - sink->Close(); - - return geometry; + writer.close(); + return writer.geometry(); } static ComPtr<ID2D1PathGeometry1> vectorPathToID2D1PathGeometry(const QVectorPath &path, bool alias) { - ComPtr<ID2D1PathGeometry1> pathGeometry; - HRESULT hr = factory()->CreatePathGeometry(pathGeometry.GetAddressOf()); - if (FAILED(hr)) { - qWarning("%s: Could not create path geometry: %#x", __FUNCTION__, hr); + Direct2DPathGeometryWriter writer; + if (!writer.begin()) return NULL; - } - - if (path.isEmpty()) - return pathGeometry; - ComPtr<ID2D1GeometrySink> sink; - hr = pathGeometry->Open(sink.GetAddressOf()); - if (FAILED(hr)) { - qWarning("%s: Could not create geometry sink: %#x", __FUNCTION__, hr); - return NULL; - } - - sink->SetFillMode(path.hasWindingFill() ? D2D1_FILL_MODE_WINDING - : D2D1_FILL_MODE_ALTERNATE); - - bool inFigure = false; + writer.setWindingFillEnabled(path.hasWindingFill()); + writer.setAliasingEnabled(alias); const QPainterPath::ElementType *types = path.elements(); const int count = path.elementCount(); - const qreal *points = 0; - - QScopedArrayPointer<qreal> rounded_points; - - if (alias) { - // Aliased painting, round to whole numbers - rounded_points.reset(new qreal[count * 2]); - points = rounded_points.data(); - - for (int i = 0; i < (count * 2); i++) - rounded_points[i] = qRound(path.points()[i]); - } else { - // Antialiased painting, keep original numbers - points = path.points(); - } + const qreal *points = path.points(); Q_ASSERT(points); @@ -226,15 +266,11 @@ static ComPtr<ID2D1PathGeometry1> vectorPathToID2D1PathGeometry(const QVectorPat switch (types[i]) { case QPainterPath::MoveToElement: - if (inFigure) - sink->EndFigure(D2D1_FIGURE_END_OPEN); - - sink->BeginFigure(D2D1::Point2F(x, y), D2D1_FIGURE_BEGIN_FILLED); - inFigure = true; + writer.moveTo(QPointF(x, y)); break; case QPainterPath::LineToElement: - sink->AddLine(D2D1::Point2F(x, y)); + writer.lineTo(QPointF(x, y)); break; case QPainterPath::CurveToElement: @@ -251,13 +287,7 @@ static ComPtr<ID2D1PathGeometry1> vectorPathToID2D1PathGeometry(const QVectorPat const qreal x3 = points[i * 2]; const qreal y3 = points[i * 2 + 1]; - D2D1_BEZIER_SEGMENT segment = { - D2D1::Point2F(x, y), - D2D1::Point2F(x2, y2), - D2D1::Point2F(x3, y3) - }; - - sink->AddBezier(segment); + writer.curveTo(QPointF(x, y), QPointF(x2, y2), QPointF(x3, y3)); } break; @@ -267,23 +297,17 @@ static ComPtr<ID2D1PathGeometry1> vectorPathToID2D1PathGeometry(const QVectorPat } } } else { - sink->BeginFigure(D2D1::Point2F(points[0], points[1]), D2D1_FIGURE_BEGIN_FILLED); - inFigure = true; - + writer.moveTo(QPointF(points[0], points[1])); for (int i = 1; i < count; i++) - sink->AddLine(D2D1::Point2F(points[i * 2], points[i * 2 + 1])); + writer.lineTo(QPointF(points[i * 2], points[i * 2 + 1])); } - if (inFigure) { + if (writer.isInFigure()) if (path.hasImplicitClose()) - sink->AddLine(D2D1::Point2F(points[0], points[1])); + writer.lineTo(QPointF(points[0], points[1])); - sink->EndFigure(D2D1_FIGURE_END_OPEN); - } - - sink->Close(); - - return pathGeometry; + writer.close(); + return writer.geometry(); } class QWindowsDirect2DPaintEnginePrivate : public QPaintEngineExPrivate @@ -302,8 +326,8 @@ public: QWindowsDirect2DBitmap *bitmap; - QPainterPath clipPath; unsigned int clipFlags; + QStack<ClipType> pushedClips; QPointF currentBrushOrigin; @@ -354,81 +378,97 @@ public: : D2D1_ANTIALIAS_MODE_ALIASED; } - void updateTransform() + void updateTransform(const QTransform &transform) { - Q_Q(const QWindowsDirect2DPaintEngine); - // Note the loss of info going from 3x3 to 3x2 matrix here - dc()->SetTransform(to_d2d_matrix_3x2_f(q->state()->transform())); + dc()->SetTransform(to_d2d_matrix_3x2_f(transform)); } - void updateOpacity() + void updateOpacity(qreal opacity) { - Q_Q(const QWindowsDirect2DPaintEngine); - qreal opacity = q->state()->opacity; if (brush.brush) brush.brush->SetOpacity(opacity); if (pen.brush) pen.brush->SetOpacity(opacity); } - void pushClip() + void pushClip(const QVectorPath &path) { - popClip(); + Q_Q(QWindowsDirect2DPaintEngine); + + if (path.isEmpty()) { + D2D_RECT_F rect = {0, 0, 0, 0}; + dc()->PushAxisAlignedClip(rect, antialiasMode()); + pushedClips.push(AxisAlignedClip); + } else if (path.isRect() && (q->state()->matrix.type() <= QTransform::TxScale)) { + const qreal * const points = path.points(); + D2D_RECT_F rect = { + points[0], // left + points[1], // top + points[2], // right, + points[5] // bottom + }; - ComPtr<ID2D1PathGeometry1> geometry = painterPathToPathGeometry(clipPath); - if (!geometry) - return; + dc()->PushAxisAlignedClip(rect, antialiasMode()); + pushedClips.push(AxisAlignedClip); + } else { + ComPtr<ID2D1PathGeometry1> geometry = vectorPathToID2D1PathGeometry(path, antialiasMode() == D2D1_ANTIALIAS_MODE_ALIASED); + if (!geometry) { + qWarning("%s: Could not convert vector path to painter path!", __FUNCTION__); + return; + } - dc()->PushLayer(D2D1::LayerParameters1(D2D1::InfiniteRect(), - geometry.Get(), - antialiasMode(), - D2D1::IdentityMatrix(), - 1.0, - NULL, - D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND), - NULL); - clipFlags |= UserClip; + dc()->PushLayer(D2D1::LayerParameters1(D2D1::InfiniteRect(), + geometry.Get(), + antialiasMode(), + D2D1::IdentityMatrix(), + 1.0, + NULL, + D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND), + NULL); + pushedClips.push(LayerClip); + } } - void popClip() + void clearClips() { - if (clipFlags & UserClip) { - dc()->PopLayer(); - clipFlags &= ~UserClip; + while (!pushedClips.isEmpty()) { + switch (pushedClips.pop()) { + case AxisAlignedClip: + dc()->PopAxisAlignedClip(); + break; + case LayerClip: + dc()->PopLayer(); + break; + } } } - void updateClipEnabled() + void updateClipEnabled(bool enabled) { - Q_Q(const QWindowsDirect2DPaintEngine); - if (!q->state()->clipEnabled) - popClip(); - else if (!(clipFlags & UserClip)) - pushClip(); + if (!enabled) + clearClips(); + else if (pushedClips.isEmpty()) + replayClipOperations(); } - void updateClipPath(const QPainterPath &path, Qt::ClipOperation operation) + void clip(const QVectorPath &path, Qt::ClipOperation operation) { switch (operation) { case Qt::NoClip: - popClip(); + clearClips(); break; case Qt::ReplaceClip: - clipPath = path; - pushClip(); + clearClips(); + pushClip(path); break; case Qt::IntersectClip: - clipPath &= path; - pushClip(); + pushClip(path); break; } } - void updateCompositionMode() + void updateCompositionMode(QPainter::CompositionMode mode) { - Q_Q(const QWindowsDirect2DPaintEngine); - QPainter::CompositionMode mode = q->state()->compositionMode(); - switch (mode) { case QPainter::CompositionMode_Source: dc()->SetPrimitiveBlend(D2D1_PRIMITIVE_BLEND_COPY); @@ -447,7 +487,7 @@ public: { Q_Q(const QWindowsDirect2DPaintEngine); - if (qbrush_fast_equals(brush.qbrush, newBrush)) + if (qbrush_fast_equals(brush.qbrush, newBrush) && (brush.brush || brush.emulate)) return; brush.brush = to_d2d_brush(newBrush, &brush.emulate); @@ -459,12 +499,10 @@ public: } } - void updateBrushOrigin() + void updateBrushOrigin(const QPointF &brushOrigin) { - Q_Q(const QWindowsDirect2DPaintEngine); - negateCurrentBrushOrigin(); - applyBrushOrigin(q->state()->brushOrigin); + applyBrushOrigin(brushOrigin); } void negateCurrentBrushOrigin() @@ -492,12 +530,10 @@ public: currentBrushOrigin = origin; } - void updatePen() + void updatePen(const QPen &newPen) { Q_Q(const QWindowsDirect2DPaintEngine); - const QPen &newPen = q->state()->pen; - - if (qpen_fast_equals(newPen, pen.qpen)) + if (qpen_fast_equals(newPen, pen.qpen) && (pen.brush || pen.emulate)) return; pen.reset(); @@ -658,7 +694,91 @@ public: break; case Qt::LinearGradientPattern: + if (newBrush.gradient()->spread() != QGradient::PadSpread) { + *needsEmulation = true; + } else { + ComPtr<ID2D1LinearGradientBrush> linear; + const QLinearGradient *qlinear = static_cast<const QLinearGradient *>(newBrush.gradient()); + + D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES linearGradientBrushProperties; + ComPtr<ID2D1GradientStopCollection> gradientStopCollection; + + const QGradientStops &qstops = qlinear->stops(); + QVector<D2D1_GRADIENT_STOP> stops(qstops.count()); + + linearGradientBrushProperties.startPoint = to_d2d_point_2f(qlinear->start()); + linearGradientBrushProperties.endPoint = to_d2d_point_2f(qlinear->finalStop()); + + for (int i = 0; i < stops.size(); i++) { + stops[i].position = qstops[i].first; + stops[i].color = to_d2d_color_f(qstops[i].second); + } + + hr = dc()->CreateGradientStopCollection(stops.constData(), stops.size(), &gradientStopCollection); + if (FAILED(hr)) { + qWarning("%s: Could not create gradient stop collection for linear gradient: %#x", __FUNCTION__, hr); + break; + } + + hr = dc()->CreateLinearGradientBrush(linearGradientBrushProperties, gradientStopCollection.Get(), + &linear); + if (FAILED(hr)) { + qWarning("%s: Could not create Direct2D linear gradient brush: %#x", __FUNCTION__, hr); + break; + } + + hr = linear.As(&result); + if (FAILED(hr)) { + qWarning("%s: Could not convert Direct2D linear gradient brush: %#x", __FUNCTION__, hr); + break; + } + } + break; + case Qt::RadialGradientPattern: + if (newBrush.gradient()->spread() != QGradient::PadSpread) { + *needsEmulation = true; + } else { + ComPtr<ID2D1RadialGradientBrush> radial; + const QRadialGradient *qradial = static_cast<const QRadialGradient *>(newBrush.gradient()); + + D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES radialGradientBrushProperties; + ComPtr<ID2D1GradientStopCollection> gradientStopCollection; + + const QGradientStops &qstops = qradial->stops(); + QVector<D2D1_GRADIENT_STOP> stops(qstops.count()); + + radialGradientBrushProperties.center = to_d2d_point_2f(qradial->center()); + radialGradientBrushProperties.gradientOriginOffset = to_d2d_point_2f(qradial->focalPoint() - qradial->center()); + radialGradientBrushProperties.radiusX = qradial->radius(); + radialGradientBrushProperties.radiusY = qradial->radius(); + + for (int i = 0; i < stops.size(); i++) { + stops[i].position = qstops[i].first; + stops[i].color = to_d2d_color_f(qstops[i].second); + } + + hr = dc()->CreateGradientStopCollection(stops.constData(), stops.size(), &gradientStopCollection); + if (FAILED(hr)) { + qWarning("%s: Could not create gradient stop collection for radial gradient: %#x", __FUNCTION__, hr); + break; + } + + hr = dc()->CreateRadialGradientBrush(radialGradientBrushProperties, gradientStopCollection.Get(), + &radial); + if (FAILED(hr)) { + qWarning("%s: Could not create Direct2D radial gradient brush: %#x", __FUNCTION__, hr); + break; + } + + radial.As(&result); + if (FAILED(hr)) { + qWarning("%s: Could not convert Direct2D radial gradient brush: %#x", __FUNCTION__, hr); + break; + } + } + break; + case Qt::ConicalGradientPattern: *needsEmulation = true; break; @@ -706,16 +826,9 @@ QWindowsDirect2DPaintEngine::QWindowsDirect2DPaintEngine(QWindowsDirect2DBitmap : QPaintEngineEx(*(new QWindowsDirect2DPaintEnginePrivate(bitmap))) { QPaintEngine::PaintEngineFeatures unsupported = - // As of 1.1 Direct2D gradient support is deficient for linear and radial gradients - QPaintEngine::LinearGradientFill - | QPaintEngine::RadialGradientFill - - // As of 1.1 Direct2D does not support conical gradients at all - | QPaintEngine::ConicalGradientFill - // As of 1.1 Direct2D does not natively support complex composition modes // However, using Direct2D effects that implement them should be possible - | QPaintEngine::PorterDuff + QPaintEngine::PorterDuff | QPaintEngine::BlendModes | QPaintEngine::RasterOpModes @@ -739,7 +852,7 @@ bool QWindowsDirect2DPaintEngine::begin(QPaintDevice * pdev) QPainterPath p; p.addRegion(systemClip()); - ComPtr<ID2D1PathGeometry1> geometry = painterPathToPathGeometry(p); + ComPtr<ID2D1PathGeometry1> geometry = painterPathToID2D1PathGeometry(p, d->antialiasMode() == D2D1_ANTIALIAS_MODE_ALIASED); if (!geometry) return false; @@ -768,7 +881,7 @@ bool QWindowsDirect2DPaintEngine::end() { Q_D(QWindowsDirect2DPaintEngine); // First pop any user-applied clipping - d->popClip(); + d->clearClips(); // Now the system clip from begin() above if (d->clipFlags & SimpleSystemClip) { d->dc()->PopAxisAlignedClip(); @@ -784,6 +897,23 @@ QPaintEngine::Type QWindowsDirect2DPaintEngine::type() const return QPaintEngine::Direct2D; } +void QWindowsDirect2DPaintEngine::setState(QPainterState *s) +{ + Q_D(QWindowsDirect2DPaintEngine); + + QPaintEngineEx::setState(s); + d->clearClips(); + + clipEnabledChanged(); + penChanged(); + brushChanged(); + brushOriginChanged(); + opacityChanged(); + compositionModeChanged(); + renderHintsChanged(); + transformChanged(); +} + void QWindowsDirect2DPaintEngine::fill(const QVectorPath &path, const QBrush &brush) { Q_D(QWindowsDirect2DPaintEngine); @@ -792,83 +922,53 @@ void QWindowsDirect2DPaintEngine::fill(const QVectorPath &path, const QBrush &br if (path.isEmpty()) return; - d->updateBrush(brush); - - if (d->brush.emulate) { - // We mostly (only?) get here when gradients are required. - // We could probably natively support linear and radial gradients that have pad reflect - - QImage img(d->bitmap->size(), QImage::Format_ARGB32); - img.fill(Qt::transparent); - - QPainter p; - QPaintEngine *engine = img.paintEngine(); - if (engine->isExtended() && p.begin(&img)) { - QPaintEngineEx *extended = static_cast<QPaintEngineEx *>(engine); - extended->fill(path, brush); - if (!p.end()) - qWarning("%s: Paint Engine end returned false", __FUNCTION__); - - drawImage(img.rect(), img, img.rect()); - } else { - qWarning("%s: Could not fall back to QImage", __FUNCTION__); - } + ensureBrush(brush); + if (!state()->matrix.isAffine() || d->brush.emulate) { + rasterFill(path, brush); return; } if (!d->brush.brush) return; - ComPtr<ID2D1Geometry> geometry = vectorPathToID2D1PathGeometry(path, d->antialiasMode() == D2D1_ANTIALIAS_MODE_ALIASED); - if (!geometry) { - qWarning("%s: Could not convert path to d2d geometry", __FUNCTION__); - return; - } - - d->dc()->FillGeometry(geometry.Get(), d->brush.brush.Get()); -} - -// For clipping we convert everything to painter paths since it allows -// calculating intersections easily. It might be faster to convert to -// ID2D1Geometry and use its operations, although that needs to measured. -// The implementation would be more complex in any case. - -void QWindowsDirect2DPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) -{ - clip(path.convertToPainterPath(), op); -} + if (path.isRect()) { + const qreal * const points = path.points(); + D2D_RECT_F rect = { + points[0], // left + points[1], // top + points[2], // right, + points[5] // bottom + }; -void QWindowsDirect2DPaintEngine::clip(const QRect &rect, Qt::ClipOperation op) -{ - QPainterPath p; - p.addRect(rect); - clip(p, op); -} + d->dc()->FillRectangle(rect, d->brush.brush.Get()); + } else { + ComPtr<ID2D1Geometry> geometry = vectorPathToID2D1PathGeometry(path, d->antialiasMode() == D2D1_ANTIALIAS_MODE_ALIASED); + if (!geometry) { + qWarning("%s: Could not convert path to d2d geometry", __FUNCTION__); + return; + } -void QWindowsDirect2DPaintEngine::clip(const QRegion ®ion, Qt::ClipOperation op) -{ - QPainterPath p; - p.addRegion(region); - clip(p, op); + d->dc()->FillGeometry(geometry.Get(), d->brush.brush.Get()); + } } -void QWindowsDirect2DPaintEngine::clip(const QPainterPath &path, Qt::ClipOperation op) +void QWindowsDirect2DPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) { Q_D(QWindowsDirect2DPaintEngine); - d->updateClipPath(path, op); + d->clip(path, op); } void QWindowsDirect2DPaintEngine::clipEnabledChanged() { Q_D(QWindowsDirect2DPaintEngine); - d->updateClipEnabled(); + d->updateClipEnabled(state()->clipEnabled); } void QWindowsDirect2DPaintEngine::penChanged() { Q_D(QWindowsDirect2DPaintEngine); - d->updatePen(); + d->updatePen(state()->pen); } void QWindowsDirect2DPaintEngine::brushChanged() @@ -880,19 +980,19 @@ void QWindowsDirect2DPaintEngine::brushChanged() void QWindowsDirect2DPaintEngine::brushOriginChanged() { Q_D(QWindowsDirect2DPaintEngine); - d->updateBrushOrigin(); + d->updateBrushOrigin(state()->brushOrigin); } void QWindowsDirect2DPaintEngine::opacityChanged() { Q_D(QWindowsDirect2DPaintEngine); - d->updateOpacity(); + d->updateOpacity(state()->opacity); } void QWindowsDirect2DPaintEngine::compositionModeChanged() { Q_D(QWindowsDirect2DPaintEngine); - d->updateCompositionMode(); + d->updateCompositionMode(state()->compositionMode()); } void QWindowsDirect2DPaintEngine::renderHintsChanged() @@ -904,7 +1004,7 @@ void QWindowsDirect2DPaintEngine::renderHintsChanged() void QWindowsDirect2DPaintEngine::transformChanged() { Q_D(QWindowsDirect2DPaintEngine); - d->updateTransform(); + d->updateTransform(state()->transform()); } void QWindowsDirect2DPaintEngine::drawImage(const QRectF &rectangle, const QImage &image, @@ -938,6 +1038,8 @@ void QWindowsDirect2DPaintEngine::drawPixmap(const QRectF &r, QWindowsDirect2DPlatformPixmap *pp = static_cast<QWindowsDirect2DPlatformPixmap *>(pm.handle()); QWindowsDirect2DBitmap *bitmap = pp->bitmap(); + ensurePen(); + if (bitmap->bitmap() != d->bitmap->bitmap()) { // Good, src bitmap != dst bitmap if (sr.isValid()) @@ -1036,12 +1138,11 @@ void QWindowsDirect2DPaintEngine::drawStaticTextItem(QStaticTextItem *staticText Q_D(QWindowsDirect2DPaintEngine); D2D_TAG(D2DDebugDrawStaticTextItemTag); - if (qpen_style(d->pen.qpen) == Qt::NoPen) - return; - if (staticTextItem->numGlyphs == 0) return; + 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) { @@ -1086,13 +1187,12 @@ void QWindowsDirect2DPaintEngine::drawTextItem(const QPointF &p, const QTextItem Q_D(QWindowsDirect2DPaintEngine); D2D_TAG(D2DDebugDrawTextItemTag); - if (qpen_style(d->pen.qpen) == Qt::NoPen) - return; - const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem); if (ti.glyphs.numGlyphs == 0) return; + 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) { @@ -1194,4 +1294,89 @@ void QWindowsDirect2DPaintEngine::drawGlyphRun(const D2D1_POINT_2F &pos, DWRITE_MEASURING_MODE_GDI_CLASSIC); } +void QWindowsDirect2DPaintEngine::ensureBrush() +{ + ensureBrush(state()->brush); +} + +void QWindowsDirect2DPaintEngine::ensureBrush(const QBrush &brush) +{ + Q_D(QWindowsDirect2DPaintEngine); + d->updateBrush(brush); +} + +void QWindowsDirect2DPaintEngine::ensurePen() +{ + ensurePen(state()->pen); +} + +void QWindowsDirect2DPaintEngine::ensurePen(const QPen &pen) +{ + Q_D(QWindowsDirect2DPaintEngine); + d->updatePen(pen); +} + +void QWindowsDirect2DPaintEngine::rasterFill(const QVectorPath &path, const QBrush &brush) +{ + Q_D(QWindowsDirect2DPaintEngine); + + QImage img(d->bitmap->size(), QImage::Format_ARGB32); + img.fill(Qt::transparent); + + QPainter p; + QPaintEngine *engine = img.paintEngine(); + + if (engine->isExtended() && p.begin(&img)) { + p.setRenderHints(state()->renderHints); + p.setCompositionMode(state()->compositionMode()); + p.setOpacity(state()->opacity); + p.setBrushOrigin(state()->brushOrigin); + p.setBrush(state()->brush); + p.setPen(state()->pen); + + QPaintEngineEx *extended = static_cast<QPaintEngineEx *>(engine); + foreach (const QPainterClipInfo &info, state()->clipInfo) { + extended->state()->matrix = info.matrix; + extended->transformChanged(); + + switch (info.clipType) { + case QPainterClipInfo::RegionClip: + extended->clip(info.region, info.operation); + break; + case QPainterClipInfo::PathClip: + extended->clip(info.path, info.operation); + break; + case QPainterClipInfo::RectClip: + extended->clip(info.rect, info.operation); + break; + case QPainterClipInfo::RectFClip: + qreal right = info.rectf.x() + info.rectf.width(); + qreal bottom = info.rectf.y() + info.rectf.height(); + qreal pts[] = { info.rectf.x(), info.rectf.y(), + right, info.rectf.y(), + right, bottom, + info.rectf.x(), bottom }; + QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint); + extended->clip(vp, info.operation); + break; + } + } + + extended->state()->matrix = state()->matrix; + extended->transformChanged(); + + extended->fill(path, brush); + if (!p.end()) + qWarning("%s: Paint Engine end returned false", __FUNCTION__); + + d->updateClipEnabled(false); + d->updateTransform(QTransform()); + drawImage(img.rect(), img, img.rect()); + transformChanged(); + clipEnabledChanged(); + } else { + qWarning("%s: Could not fall back to QImage", __FUNCTION__); + } +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h index 6c74a07e88..93ccf809e4 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.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. @@ -65,12 +65,10 @@ public: Type type() const Q_DECL_OVERRIDE; - void fill(const QVectorPath &path, const QBrush &brush) Q_DECL_OVERRIDE; + void setState(QPainterState *s) Q_DECL_OVERRIDE; + void fill(const QVectorPath &path, const QBrush &brush) Q_DECL_OVERRIDE; void clip(const QVectorPath &path, Qt::ClipOperation op) Q_DECL_OVERRIDE; - void clip(const QRect &rect, Qt::ClipOperation op) Q_DECL_OVERRIDE; - void clip(const QRegion ®ion, Qt::ClipOperation op) Q_DECL_OVERRIDE; - void clip(const QPainterPath &path, Qt::ClipOperation op) Q_DECL_OVERRIDE; void clipEnabledChanged() Q_DECL_OVERRIDE; void penChanged() Q_DECL_OVERRIDE; @@ -91,6 +89,13 @@ private: void drawGlyphRun(const D2D1_POINT_2F &pos, IDWriteFontFace *fontFace, const QFont &font, int numGlyphs, const UINT16 *glyphIndices, const FLOAT *glyphAdvances, const DWRITE_GLYPH_OFFSET *glyphOffsets, bool rtl); + + void ensureBrush(); + void ensureBrush(const QBrush &brush); + void ensurePen(); + void ensurePen(const QPen &pen); + + void rasterFill(const QVectorPath &path, const QBrush &brush); }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp index bf860f982e..50d0cb81f5 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp @@ -54,6 +54,9 @@ QWindowsDirect2DWindow::QWindowsDirect2DWindow(QWindow *window, const QWindowsWi : QWindowsWindow(window, data) , m_needsFullFlush(true) { + if (window->type() == Qt::Desktop) + return; // No further handling for Qt::Desktop + DXGI_SWAP_CHAIN_DESC1 desc = {}; desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; @@ -125,7 +128,7 @@ void QWindowsDirect2DWindow::flush(QWindowsDirect2DBitmap *bitmap, const QRegion } m_bitmap->deviceContext()->end(); - m_swapChain->Present(1, 0); + m_swapChain->Present(0, 0); } void QWindowsDirect2DWindow::resizeSwapChain(const QSize &size) diff --git a/src/plugins/platforms/eglfs/qeglfswindow.h b/src/plugins/platforms/eglfs/qeglfswindow.h index c8c31816a0..f3fd06037e 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.h +++ b/src/plugins/platforms/eglfs/qeglfswindow.h @@ -91,7 +91,7 @@ private: Created = 0x01, HasNativeWindow = 0x02 }; - Q_DECLARE_FLAGS(Flags, Flag); + Q_DECLARE_FLAGS(Flags, Flag) Flags m_flags; }; diff --git a/src/plugins/platforms/ios/quiview_textinput.mm b/src/plugins/platforms/ios/quiview_textinput.mm index 28fb23d57b..3f6c6d1256 100644 --- a/src/plugins/platforms/ios/quiview_textinput.mm +++ b/src/plugins/platforms/ios/quiview_textinput.mm @@ -473,6 +473,8 @@ Q_GLOBAL_STATIC(StaticVariables, staticVariables); QCoreApplication::sendEvent(focusObject, &e); QFont qfont = qvariant_cast<QFont>(e.value(Qt::ImFont)); UIFont *uifont = [UIFont fontWithName:qfont.family().toNSString() size:qfont.pointSize()]; + if (!uifont) + return [NSDictionary dictionary]; return [NSDictionary dictionaryWithObject:uifont forKey:UITextInputTextFontKey]; } diff --git a/src/plugins/platforms/qnx/qqnxfiledialoghelper.h b/src/plugins/platforms/qnx/qqnxfiledialoghelper.h index e83fc445d6..83af966a00 100644 --- a/src/plugins/platforms/qnx/qqnxfiledialoghelper.h +++ b/src/plugins/platforms/qnx/qqnxfiledialoghelper.h @@ -88,7 +88,9 @@ Q_SIGNALS: void dialogClosed(); private Q_SLOTS: +#if !defined(Q_OS_BLACKBERRY_TABLET) void emitSignals(); +#endif private: void setNameFilter(const QString &filter); diff --git a/src/plugins/platforms/qnx/qqnxrasterwindow.cpp b/src/plugins/platforms/qnx/qqnxrasterwindow.cpp index eb9fac540f..ead6e73a87 100644 --- a/src/plugins/platforms/qnx/qqnxrasterwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxrasterwindow.cpp @@ -64,10 +64,13 @@ QQnxRasterWindow::QQnxRasterWindow(QWindow *window, screen_context_t context, bo initWindow(); // Set window usage + if (window->type() == Qt::Desktop) + return; + const int val = SCREEN_USAGE_NATIVE | SCREEN_USAGE_READ | SCREEN_USAGE_WRITE; const int result = screen_set_window_property_iv(nativeHandle(), SCREEN_PROPERTY_USAGE, &val); if (result != 0) - qFatal("QQnxEglWindow: failed to set window alpha usage, errno=%d", errno); + qFatal("QQnxRasterWindow: failed to set window alpha usage, errno=%d", errno); } void QQnxRasterWindow::post(const QRegion &dirty) diff --git a/src/plugins/platforms/qnx/qqnxscreen.cpp b/src/plugins/platforms/qnx/qqnxscreen.cpp index 2707f14db2..9ba0f5cd2e 100644 --- a/src/plugins/platforms/qnx/qqnxscreen.cpp +++ b/src/plugins/platforms/qnx/qqnxscreen.cpp @@ -97,9 +97,9 @@ static QSize determineScreenSize(screen_display_t display, bool primaryScreen) { const int envHeight = envPhySizeStrList.size() == 2 ? envPhySizeStrList[1].toInt() : -1; if (envWidth <= 0 || envHeight <= 0) { - qFatal("QQnxScreen: The value of QQNX_PHYSICAL_SCREEN_SIZE must be in the format " - "\"width,height\" in mm, with width, height > 0. " - "Example: QQNX_PHYSICAL_SCREEN_SIZE=150,90"); + qWarning("QQnxScreen: The value of QQNX_PHYSICAL_SCREEN_SIZE must be in the format " + "\"width,height\" in mm, with width, height > 0. Defaulting to 150x90. " + "Example: QQNX_PHYSICAL_SCREEN_SIZE=150,90"); return QSize(150, 90); } @@ -114,8 +114,8 @@ static QSize determineScreenSize(screen_display_t display, bool primaryScreen) { return defSize; #else if (primaryScreen) - qFatal("QQnxScreen: QQNX_PHYSICAL_SCREEN_SIZE variable not set. " - "Could not determine physical screen size."); + qWarning("QQnxScreen: QQNX_PHYSICAL_SCREEN_SIZE variable not set. " + "Could not determine physical screen size. Defaulting to 150x90."); return QSize(150, 90); #endif } diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp index 2e0febff20..5a405f9577 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxwindow.cpp @@ -174,7 +174,7 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, bool needRootW // indication that we want to create a child window and join that window group. const QVariant windowGroup = window->property("qnxInitialWindowGroup"); - if (window->type() == Qt::CoverWindow || window->type() == Qt::Desktop) { + if (window->type() == Qt::CoverWindow) { // Cover windows have to be top level to be accessible to window delegate (i.e. navigator) // Desktop windows also need to be toplevel because they are not // supposed to be part of the window hierarchy tree @@ -189,10 +189,13 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, bool needRootW m_isTopLevel = !needRootWindow || !platformScreen->rootWindow(); } + if (window->type() == Qt::Desktop) // A desktop widget does not need a libscreen window + return; + if (m_isTopLevel) { Q_SCREEN_CRITICALERROR(screen_create_window(&m_window, m_screenContext), "Could not create top level window"); // Creates an application window - if (window->type() != Qt::CoverWindow && window->type() != Qt::Desktop) { + if (window->type() != Qt::CoverWindow) { if (needRootWindow) platformScreen->setRootWindow(this); } @@ -245,9 +248,9 @@ void QQnxWindow::setGeometry(const QRect &rect) if (shouldMakeFullScreen()) newGeometry = screen()->geometry(); - setGeometryHelper(newGeometry); + if (window()->type() != Qt::Desktop) + setGeometryHelper(newGeometry); - QWindowSystemInterface::handleGeometryChange(window(), newGeometry); if (isExposed()) QWindowSystemInterface::handleExposeEvent(window(), newGeometry); } @@ -278,13 +281,15 @@ void QQnxWindow::setGeometryHelper(const QRect &rect) "Failed to set window source size"); screen_flush_context(m_screenContext, 0); + + QWindowSystemInterface::handleGeometryChange(window(), rect); } void QQnxWindow::setVisible(bool visible) { qWindowDebug() << Q_FUNC_INFO << "window =" << window() << "visible =" << visible; - if (m_visible == visible) + if (m_visible == visible || window()->type() == Qt::Desktop) return; // The first time through we join a window group if appropriate. @@ -667,6 +672,9 @@ void QQnxWindow::setRotation(int rotation) void QQnxWindow::initWindow() { + if (window()->type() == Qt::Desktop) + return; + // Alpha channel is always pre-multiplied if present int val = SCREEN_PRE_MULTIPLIED_ALPHA; Q_SCREEN_CHECKERROR(screen_set_window_property_iv(m_window, SCREEN_PROPERTY_ALPHA_MODE, &val), @@ -711,12 +719,7 @@ void QQnxWindow::initWindow() if (window()->parent() && window()->parent()->handle()) setParent(window()->parent()->handle()); - if (shouldMakeFullScreen()) - setGeometryHelper(screen()->geometry()); - else - setGeometryHelper(window()->geometry()); - - QWindowSystemInterface::handleGeometryChange(window(), screen()->geometry()); + setGeometryHelper(shouldMakeFullScreen() ? screen()->geometry() : window()->geometry()); } void QQnxWindow::createWindowGroup() diff --git a/src/plugins/platforms/qnx/qqnxwindow.h b/src/plugins/platforms/qnx/qqnxwindow.h index 9a2006396f..94df903336 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.h +++ b/src/plugins/platforms/qnx/qqnxwindow.h @@ -75,7 +75,7 @@ public: bool isExposed() const; - WId winId() const { return (WId)m_window; } + WId winId() const { return window()->type() == Qt::Desktop ? -1 : (WId)m_window; } screen_window_t nativeHandle() const { return m_window; } void setBufferSize(const QSize &size); diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 6462cb8d3e..ead29556b7 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch> -** 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. @@ -49,11 +49,11 @@ #include "qwindowsmime.h" #include "qwindowsinputcontext.h" #include "qwindowstabletsupport.h" +#include <private/qguiapplication_p.h> #ifndef QT_NO_ACCESSIBILITY # include "accessible/qwindowsaccessibility.h" #endif #if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER) -# include <private/qguiapplication_p.h> # include <private/qsessionmanager_p.h> # include "qwindowssessionmanager.h" #endif @@ -76,6 +76,9 @@ #include <stdlib.h> #include <stdio.h> #include <windowsx.h> +#ifndef Q_OS_WINCE +# include <comdef.h> +#endif QT_BEGIN_NAMESPACE @@ -213,7 +216,7 @@ bool QWindowsUser32DLL::initTouch() unregisterTouchWindow = (UnregisterTouchWindow)(library.resolve("UnregisterTouchWindow")); getTouchInputInfo = (GetTouchInputInfo)(library.resolve("GetTouchInputInfo")); closeTouchInputHandle = (CloseTouchInputHandle)(library.resolve("CloseTouchInputHandle")); - return registerTouchWindow && unregisterTouchWindow && getTouchInputInfo && getTouchInputInfo; + return registerTouchWindow && unregisterTouchWindow && getTouchInputInfo && closeTouchInputHandle; } /*! @@ -309,6 +312,10 @@ QWindowsContextPrivate::QWindowsContextPrivate() m_systemInfo |= QWindowsContext::SI_RTL_Extensions; m_keyMapper.setUseRTLExtensions(true); } + if (FAILED(m_oleInitializeResult)) { + qWarning() << "QWindowsContext: OleInitialize() failed: " + << QWindowsContext::comErrorString(m_oleInitializeResult); + } } QWindowsContext::QWindowsContext() : @@ -691,45 +698,70 @@ HWND QWindowsContext::createDummyWindow(const QString &classNameIn, QByteArray QWindowsContext::comErrorString(HRESULT hr) { + QByteArray result = QByteArrayLiteral("COM error 0x") + + QByteArray::number(quintptr(hr), 16) + ' '; switch (hr) { case S_OK: - return QByteArrayLiteral("S_OK"); + result += QByteArrayLiteral("S_OK"); + break; case S_FALSE: - return QByteArrayLiteral("S_FALSE"); + result += QByteArrayLiteral("S_FALSE"); + break; case E_UNEXPECTED: - return QByteArrayLiteral("E_UNEXPECTED"); + result += QByteArrayLiteral("E_UNEXPECTED"); + break; case CO_E_ALREADYINITIALIZED: - return QByteArrayLiteral("CO_E_ALREADYINITIALIZED"); + result += QByteArrayLiteral("CO_E_ALREADYINITIALIZED"); + break; case CO_E_NOTINITIALIZED: - return QByteArrayLiteral("CO_E_NOTINITIALIZED"); + result += QByteArrayLiteral("CO_E_NOTINITIALIZED"); + break; case RPC_E_CHANGED_MODE: - return QByteArrayLiteral("RPC_E_CHANGED_MODE"); + result += QByteArrayLiteral("RPC_E_CHANGED_MODE"); + break; case OLE_E_WRONGCOMPOBJ: - return QByteArrayLiteral("OLE_E_WRONGCOMPOBJ"); + result += QByteArrayLiteral("OLE_E_WRONGCOMPOBJ"); + break; case CO_E_NOT_SUPPORTED: - return QByteArrayLiteral("CO_E_NOT_SUPPORTED"); + result += QByteArrayLiteral("CO_E_NOT_SUPPORTED"); + break; case E_NOTIMPL: - return QByteArrayLiteral("E_NOTIMPL"); + result += QByteArrayLiteral("E_NOTIMPL"); + break; case E_INVALIDARG: - return QByteArrayLiteral("E_INVALIDARG"); + result += QByteArrayLiteral("E_INVALIDARG"); + break; case E_NOINTERFACE: - return QByteArrayLiteral("E_NOINTERFACE"); + result += QByteArrayLiteral("E_NOINTERFACE"); + break; case E_POINTER: - return QByteArrayLiteral("E_POINTER"); + result += QByteArrayLiteral("E_POINTER"); + break; case E_HANDLE: - return QByteArrayLiteral("E_HANDLE"); + result += QByteArrayLiteral("E_HANDLE"); + break; case E_ABORT: - return QByteArrayLiteral("E_ABORT"); + result += QByteArrayLiteral("E_ABORT"); + break; case E_FAIL: - return QByteArrayLiteral("E_FAIL"); + result += QByteArrayLiteral("E_FAIL"); + break; case RPC_E_WRONG_THREAD: - return QByteArrayLiteral("RPC_E_WRONG_THREAD"); + result += QByteArrayLiteral("RPC_E_WRONG_THREAD"); + break; case RPC_E_THREAD_NOT_INIT: - return QByteArrayLiteral("RPC_E_THREAD_NOT_INIT"); + result += QByteArrayLiteral("RPC_E_THREAD_NOT_INIT"); + break; default: break; } - return "Unknown error 0x" + QByteArray::number(quint64(hr), 16); +#ifndef Q_OS_WINCE + _com_error error(hr); + result += QByteArrayLiteral(" ("); + result += QString::fromWCharArray(error.ErrorMessage()).toLocal8Bit(); + result += ')'; +#endif // !Q_OS_WINCE + return result; } /*! @@ -1025,6 +1057,21 @@ void QWindowsContext::handleFocusEvent(QtWindows::WindowsEventType et, { QWindow *nextActiveWindow = 0; if (et == QtWindows::FocusInEvent) { + QWindow *topWindow = QWindowsWindow::topLevelOf(platformWindow->window()); + QWindow *modalWindow = 0; + if (QGuiApplicationPrivate::instance()->isWindowBlocked(topWindow, &modalWindow) && topWindow != modalWindow) { + modalWindow->requestActivate(); + return; + } + // QTBUG-32867: Invoking WinAPI SetParent() can cause focus-in for the + // window which is not desired for native child widgets. + if (platformWindow->testFlag(QWindowsWindow::WithinSetParent)) { + QWindow *currentFocusWindow = QGuiApplication::focusWindow(); + if (currentFocusWindow && currentFocusWindow != platformWindow->window()) { + currentFocusWindow->requestActivate(); + return; + } + } nextActiveWindow = platformWindow->window(); } else { // Focus out: Is the next window known and different diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp index 1432dfdcd9..940d75614c 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp @@ -1040,7 +1040,11 @@ QWindowsFontDatabase::~QWindowsFontDatabase() QFontEngineMulti *QWindowsFontDatabase::fontEngineMulti(QFontEngine *fontEngine, QChar::Script script) { - return new QWindowsMultiFontEngine(fontEngine, script); + if (script == QChar::Script_Common) + return new QWindowsMultiFontEngine(fontEngine, script); + // ### as long as fallbacksForFamily() does not take script parameter into account, + // prefer QFontEngineMultiQPA's loadEngine() implementation for complex scripts + return QPlatformFontDatabase::fontEngineMulti(fontEngine, script); } QFontEngine * QWindowsFontDatabase::fontEngine(const QFontDef &fontDef, void *handle) @@ -1619,8 +1623,7 @@ QStringList QWindowsFontDatabase::fallbacksForFamily(const QString &family, QFon result << QString::fromLatin1("Arial"); } - if (script == QChar::Script_Common || script == QChar::Script_Han) - result.append(QWindowsFontDatabase::extraTryFontsForFamily(family)); + result.append(QWindowsFontDatabase::extraTryFontsForFamily(family)); qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint << script << result << m_families.size(); diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp index 51961014d9..734f645e65 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp @@ -477,8 +477,7 @@ QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString &family, QF } #endif - if (script == QChar::Script_Common || script == QChar::Script_Han) - result.append(QWindowsFontDatabase::extraTryFontsForFamily(family)); + result.append(QWindowsFontDatabase::extraTryFontsForFamily(family)); qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint << script << result << m_families; diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp index 4f3a007bd7..29c43fc7a5 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.cpp +++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp @@ -1032,7 +1032,7 @@ QWindowsNativeImage *QWindowsFontEngine::drawGDIGlyph(HFONT font, glyph_t glyph, int iw = gm.width.toInt(); int ih = gm.height.toInt(); - if (iw <= 0 || iw <= 0) + if (iw <= 0 || ih <= 0) return 0; bool has_transformation = t.type() > QTransform::TxTranslate; diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp index 6349c1e355..6a3930dc78 100644 --- a/src/plugins/platforms/windows/qwindowstheme.cpp +++ b/src/plugins/platforms/windows/qwindowstheme.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. @@ -230,12 +230,16 @@ static inline QPalette toolTipPalette(const QPalette &systemPalette) result.setColor(QPalette::All, QPalette::Text, tipTextColor); result.setColor(QPalette::All, QPalette::WindowText, tipTextColor); result.setColor(QPalette::All, QPalette::ButtonText, tipTextColor); + result.setColor(QPalette::All, QPalette::ToolTipBase, tipBgColor); + result.setColor(QPalette::All, QPalette::ToolTipText, tipTextColor); const QColor disabled = mixColors(result.foreground().color(), result.button().color()); result.setColor(QPalette::Disabled, QPalette::WindowText, disabled); result.setColor(QPalette::Disabled, QPalette::Text, disabled); + result.setColor(QPalette::Disabled, QPalette::ToolTipText, disabled); result.setColor(QPalette::Disabled, QPalette::Base, Qt::white); result.setColor(QPalette::Disabled, QPalette::BrightText, Qt::white); + result.setColor(QPalette::Disabled, QPalette::ToolTipBase, Qt::white); return result; } diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index ee9bf9936c..db06525508 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1016,17 +1016,17 @@ QWindow *QWindowsWindow::topLevelOf(QWindow *w) while (QWindow *parent = w->parent()) w = parent; - const QWindowsWindow *ww = static_cast<const QWindowsWindow *>(w->handle()); - - // In case the topmost parent is embedded, find next ancestor using native methods - if (ww->isEmbedded(0)) { - HWND parentHWND = GetAncestor(ww->handle(), GA_PARENT); - const HWND desktopHwnd = GetDesktopWindow(); - const QWindowsContext *ctx = QWindowsContext::instance(); - while (parentHWND && parentHWND != desktopHwnd) { - if (QWindowsWindow *ancestor = ctx->findPlatformWindow(parentHWND)) - return topLevelOf(ancestor->window()); - parentHWND = GetAncestor(parentHWND, GA_PARENT); + if (const QPlatformWindow *handle = w->handle()) { + const QWindowsWindow *ww = static_cast<const QWindowsWindow *>(handle); + if (ww->isEmbedded(0)) { + HWND parentHWND = GetAncestor(ww->handle(), GA_PARENT); + const HWND desktopHwnd = GetDesktopWindow(); + const QWindowsContext *ctx = QWindowsContext::instance(); + while (parentHWND && parentHWND != desktopHwnd) { + if (QWindowsWindow *ancestor = ctx->findPlatformWindow(parentHWND)) + return topLevelOf(ancestor->window()); + parentHWND = GetAncestor(parentHWND, GA_PARENT); + } } } return w; diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 2e38f81499..583441f396 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -1020,7 +1020,9 @@ HRESULT QWinRTScreen::onOrientationChanged(IInspectable *) HRESULT QWinRTScreen::onBackButtonPressed(IInspectable *, IBackPressedEventArgs *args) { QKeyEvent backPress(QEvent::KeyPress, Qt::Key_Back, Qt::NoModifier); + QKeyEvent backRelease(QEvent::KeyRelease, Qt::Key_Back, Qt::NoModifier); backPress.setAccepted(false); + backRelease.setAccepted(false); QObject *receiver = m_visibleWindows.isEmpty() ? static_cast<QObject *>(QGuiApplication::instance()) @@ -1028,12 +1030,8 @@ HRESULT QWinRTScreen::onBackButtonPressed(IInspectable *, IBackPressedEventArgs // If the event is ignored, the app will suspend QGuiApplication::sendEvent(receiver, &backPress); - if (backPress.isAccepted()) { - args->put_Handled(true); - // If the app accepts the event, send the release for symmetry - QKeyEvent backRelease(QEvent::KeyRelease, Qt::Key_Back, Qt::NoModifier); - QGuiApplication::sendEvent(receiver, &backRelease); - } + QGuiApplication::sendEvent(receiver, &backRelease); + args->put_Handled(backPress.isAccepted() || backRelease.isAccepted()); return S_OK; } diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp index c183deb3b8..f78d3bcc4e 100644 --- a/src/plugins/platforms/xcb/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/qglxintegration.cpp @@ -449,12 +449,32 @@ bool QGLXContext::m_supportsThreading = true; // binary search. static const char *qglx_threadedgl_blacklist_renderer[] = { "Chromium", // QTBUG-32225 (initialization fails) - "Mesa DRI Intel(R) Sandybridge Mobile", // QTBUG-34492 (flickering in fullscreen) 0 }; +// This disables threaded rendering on anything using mesa, e.g. +// - nvidia/nouveau +// - amd/gallium +// - intel +// - some software opengl implementations +// +// The client glx vendor string is used to identify those setups as that seems to show the least +// variance between the bad configurations. It's always "Mesa Project and SGI". There are some +// configurations which don't use mesa and which can do threaded rendering (amd and nvidia chips +// with their own proprietary drivers). +// +// This, of course, is very broad and disables threaded rendering on a lot of devices which would +// be able to use it. However, the bugs listed below don't follow any easily recognizable pattern +// and we should rather be safe. +// +// http://cgit.freedesktop.org/xcb/libxcb/commit/?id=be0fe56c3bcad5124dcc6c47a2fad01acd16f71a will +// fix some of the issues. Basically, the proprietary drivers seem to have a way of working around +// a fundamental flaw with multithreaded access to xcb, but mesa doesn't. The blacklist should be +// reevaluated once that patch is released in some version of xcb. static const char *qglx_threadedgl_blacklist_vendor[] = { - "nouveau", // QTCREATORBUG-10875 (crash in creator) + "Mesa Project and SGI", // QTCREATORBUG-10875 (crash in creator) + // QTBUG-34492 (flickering in fullscreen) + // QTBUG-38221 0 }; @@ -502,9 +522,9 @@ void QGLXContext::queryDummyContext() } } - if (const char *vendor = (const char *) glGetString(GL_VENDOR)) { + if (glxvendor) { for (int i = 0; qglx_threadedgl_blacklist_vendor[i]; ++i) { - if (strstr(vendor, qglx_threadedgl_blacklist_vendor[i]) != 0) { + if (strstr(glxvendor, qglx_threadedgl_blacklist_vendor[i]) != 0) { m_supportsThreading = false; break; } diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index a95bba9ab6..80a8f471d7 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -467,6 +467,10 @@ public: QXcbSystemTrayTracker *systemTrayTracker(); +#ifdef XCB_USE_XINPUT2 + void handleEnterEvent(const xcb_enter_notify_event_t *); +#endif + private slots: void processXcbEvents(); diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index d80b49ccbb..d7b3c75aee 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -524,6 +524,35 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) } } +void QXcbConnection::handleEnterEvent(const xcb_enter_notify_event_t *) +{ +#ifdef XCB_USE_XINPUT21 + QHash<int, ScrollingDevice>::iterator it = m_scrollingDevices.begin(); + const QHash<int, ScrollingDevice>::iterator end = m_scrollingDevices.end(); + while (it != end) { + ScrollingDevice& scrollingDevice = it.value(); + int nrDevices = 0; + XIDeviceInfo* xiDeviceInfo = XIQueryDevice(static_cast<Display *>(m_xlib_display), scrollingDevice.deviceId, &nrDevices); + if (nrDevices <= 0) { + it = m_scrollingDevices.erase(it); + continue; + } + for (int c = 0; c < xiDeviceInfo->num_classes; ++c) { + if (xiDeviceInfo->classes[c]->type == XIValuatorClass) { + XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(xiDeviceInfo->classes[c]); + const int valuatorAtom = qatom(vci->label); + if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel) + scrollingDevice.lastScrollPosition.setX(vci->value); + else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel) + scrollingDevice.lastScrollPosition.setY(vci->value); + } + } + XIFreeDeviceInfo(xiDeviceInfo); + ++it; + } +#endif +} + void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollingDevice) { #ifdef XCB_USE_XINPUT21 diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 22b49f526a..830a490fd9 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -491,7 +491,7 @@ QXcbWindow::~QXcbWindow() void QXcbWindow::destroy() { if (connection()->focusWindow() == this) - connection()->setFocusWindow(0); + doFocusOut(); if (m_syncCounter && m_usingSyncProtocol) Q_XCB_CALL(xcb_sync_destroy_counter(xcb_connection(), m_syncCounter)); @@ -560,7 +560,7 @@ QMargins QXcbWindow::frameMargins() const xcb_query_tree_reply_t *reply = xcb_query_tree_reply(xcb_connection(), cookie, NULL); if (reply) { - if (reply->root == reply->parent || virtualRoots.indexOf(reply->parent) != -1) { + if (reply->root == reply->parent || virtualRoots.indexOf(reply->parent) != -1 || reply->parent == XCB_WINDOW_NONE) { foundRoot = true; } else { window = parent; @@ -677,6 +677,9 @@ void QXcbWindow::show() Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window)); + if (QGuiApplication::modalWindow() == window()) + requestActivateWindow(); + m_screen->windowShown(this); connection()->sync(); @@ -700,6 +703,68 @@ void QXcbWindow::hide() m_mapped = false; } +static QWindow *tlWindow(QWindow *window) +{ + if (window && window->parent()) + return tlWindow(window->parent()); + return window; +} + +bool QXcbWindow::relayFocusToModalWindow() const +{ + QWindow *w = tlWindow(static_cast<QWindowPrivate *>(QObjectPrivate::get(window()))->eventReceiver()); + QWindow *modal_window = 0; + if (QGuiApplicationPrivate::instance()->isWindowBlocked(w,&modal_window) && modal_window != w) { + modal_window->requestActivate(); + connection()->flush(); + return true; + } + + return false; +} + +void QXcbWindow::doFocusIn() +{ + if (relayFocusToModalWindow()) + return; + QWindow *w = static_cast<QWindowPrivate *>(QObjectPrivate::get(window()))->eventReceiver(); + connection()->setFocusWindow(static_cast<QXcbWindow *>(w->handle())); + QWindowSystemInterface::handleWindowActivated(w, Qt::ActiveWindowFocusReason); +} + +static bool focusInPeeker(QXcbConnection *connection, xcb_generic_event_t *event) +{ + if (!event) { + // FocusIn event is not in the queue, proceed with FocusOut normally. + QWindowSystemInterface::handleWindowActivated(0, Qt::ActiveWindowFocusReason); + return true; + } + uint response_type = event->response_type & ~0x80; + if (response_type == XCB_FOCUS_IN) + return true; + + /* We are also interested in XEMBED_FOCUS_IN events */ + if (response_type == XCB_CLIENT_MESSAGE) { + xcb_client_message_event_t *cme = (xcb_client_message_event_t *)event; + if (cme->type == connection->atom(QXcbAtom::_XEMBED) + && cme->data.data32[1] == XEMBED_FOCUS_IN) + return true; + } + + return false; +} + +void QXcbWindow::doFocusOut() +{ + if (relayFocusToModalWindow()) + return; + connection()->setFocusWindow(0); + // Do not set the active window to 0 if there is a FocusIn coming. + // There is however no equivalent for XPutBackEvent so register a + // callback for QXcbConnection instead. + connection()->addPeekFunc(focusInPeeker); +} + struct QtMotifWmHints { quint32 flags, functions, decorations; qint32 input_mode; @@ -1520,6 +1585,8 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even QWindowSystemInterface::handleCloseEvent(window()); } else if (event->data.data32[0] == atom(QXcbAtom::WM_TAKE_FOCUS)) { connection()->setTime(event->data.data32[1]); + relayFocusToModalWindow(); + return; } else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_PING)) { if (event->window == m_screen->root()) return; @@ -1555,8 +1622,7 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even } else if (event->type == atom(QXcbAtom::_XEMBED)) { handleXEmbedMessage(event); } else if (event->type == atom(QXcbAtom::_NET_ACTIVE_WINDOW)) { - connection()->setFocusWindow(this); - QWindowSystemInterface::handleWindowActivated(window(), Qt::ActiveWindowFocusReason); + doFocusIn(); } else if (event->type == atom(QXcbAtom::MANAGER) || event->type == atom(QXcbAtom::_NET_WM_STATE) || event->type == atom(QXcbAtom::WM_CHANGE_STATE)) { @@ -1788,6 +1854,9 @@ public: void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event) { connection()->setTime(event->time); +#ifdef XCB_USE_XINPUT2 + connection()->handleEnterEvent(event); +#endif if ((event->mode != XCB_NOTIFY_MODE_NORMAL && event->mode != XCB_NOTIFY_MODE_UNGRAB) || event->detail == XCB_NOTIFY_DETAIL_VIRTUAL @@ -1875,41 +1944,13 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev void QXcbWindow::handleFocusInEvent(const xcb_focus_in_event_t *) { - QWindow *w = window(); - w = static_cast<QWindowPrivate *>(QObjectPrivate::get(w))->eventReceiver(); - connection()->setFocusWindow(static_cast<QXcbWindow *>(w->handle())); - QWindowSystemInterface::handleWindowActivated(w, Qt::ActiveWindowFocusReason); + doFocusIn(); } -static bool focusInPeeker(QXcbConnection *connection, xcb_generic_event_t *event) -{ - if (!event) { - // FocusIn event is not in the queue, proceed with FocusOut normally. - QWindowSystemInterface::handleWindowActivated(0, Qt::ActiveWindowFocusReason); - return true; - } - uint response_type = event->response_type & ~0x80; - if (response_type == XCB_FOCUS_IN) - return true; - - /* We are also interested in XEMBED_FOCUS_IN events */ - if (response_type == XCB_CLIENT_MESSAGE) { - xcb_client_message_event_t *cme = (xcb_client_message_event_t *)event; - if (cme->type == connection->atom(QXcbAtom::_XEMBED) - && cme->data.data32[1] == XEMBED_FOCUS_IN) - return true; - } - - return false; -} void QXcbWindow::handleFocusOutEvent(const xcb_focus_out_event_t *) { - connection()->setFocusWindow(0); - // Do not set the active window to 0 if there is a FocusIn coming. - // There is however no equivalent for XPutBackEvent so register a - // callback for QXcbConnection instead. - connection()->addPeekFunc(focusInPeeker); + doFocusOut(); } void QXcbWindow::updateSyncRequestCounter() diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index a90ad7b5ed..12d17023fb 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -176,6 +176,10 @@ private: void show(); void hide(); + bool relayFocusToModalWindow() const; + void doFocusIn(); + void doFocusOut(); + QXcbScreen *m_screen; xcb_window_t m_window; diff --git a/src/plugins/printsupport/windows/windows.pro b/src/plugins/printsupport/windows/windows.pro index 364e19e68e..3366262ef0 100644 --- a/src/plugins/printsupport/windows/windows.pro +++ b/src/plugins/printsupport/windows/windows.pro @@ -21,4 +21,4 @@ HEADERS += \ OTHER_FILES += windows.json -LIBS += -lwinspool -lcomdlg32 +LIBS += -lwinspool -lcomdlg32 -lgdi32 -luser32 diff --git a/src/printsupport/dialogs/qprintdialog_mac.mm b/src/printsupport/dialogs/qprintdialog_mac.mm index 9ff7c4766a..ef3e88be39 100644 --- a/src/printsupport/dialogs/qprintdialog_mac.mm +++ b/src/printsupport/dialogs/qprintdialog_mac.mm @@ -143,11 +143,11 @@ QT_USE_NAMESPACE CFURLGetFileSystemRepresentation(file, true, localFile, sizeof(localFile)); printer->setOutputFileName(QString::fromUtf8(reinterpret_cast<const char *>(localFile))); } else { - // Keep output format. - QPrinter::OutputFormat format; - format = printer->outputFormat(); - printer->setOutputFileName(QString()); - printer->setOutputFormat(format); + PMPrinter macPrinter; + PMSessionGetCurrentPrinter(session, &macPrinter); + QString printerId = QString::fromCFString(PMPrinterGetID(macPrinter)); + if (printer->printerName() != printerId) + printer->setPrinterName(printerId); } } @@ -160,13 +160,13 @@ QT_USE_NAMESPACE PMOrientation orientation; PMGetOrientation(pageFormat, &orientation); QPageSize pageSize; - QCFString key; + CFStringRef key; double width = 0; double height = 0; // If the PPD name is empty then is custom, for some reason PMPaperIsCustom doesn't work here PMPaperGetPPDPaperName(paper, &key); if (PMPaperGetWidth(paper, &width) == noErr && PMPaperGetHeight(paper, &height) == noErr) { - QString ppdKey = key; + QString ppdKey = QString::fromCFString(key); if (ppdKey.isEmpty()) { // Is using a custom page size as defined in the Print Dialog custom settings using mm or inches. // We can't ask PMPaper what those units actually are, we can only get the point size which may return @@ -185,7 +185,7 @@ QT_USE_NAMESPACE pageSize = QPageSize(QSizeF(w / 100.0, h / 100.0), QPageSize::Inch); } } else { - pageSize = QPlatformPrintDevice::createPageSize(key, QSize(width, height), QString()); + pageSize = QPlatformPrintDevice::createPageSize(ppdKey, QSize(width, height), QString()); } } if (pageSize.isValid() && !pageSize.isEquivalentTo(printer->pageLayout().pageSize())) diff --git a/src/printsupport/printsupport.pro b/src/printsupport/printsupport.pro index b32ba91c07..6dd3eaab3c 100644 --- a/src/printsupport/printsupport.pro +++ b/src/printsupport/printsupport.pro @@ -1,7 +1,6 @@ TARGET = QtPrintSupport QT = core-private gui-private widgets-private -MODULE_CONFIG = needs_printsupport_plugin DEFINES += QT_NO_USING_NAMESPACE MODULE_PLUGIN_TYPES = \ diff --git a/src/tools/moc/token.cpp b/src/tools/moc/token.cpp index a936555980..36b413ca84 100644 --- a/src/tools/moc/token.cpp +++ b/src/tools/moc/token.cpp @@ -47,174 +47,9 @@ QT_BEGIN_NAMESPACE const char *tokenTypeName(Token t) { switch (t) { - case NOTOKEN: return "NOTOKEN"; - case IDENTIFIER: return "IDENTIFIER"; - case INTEGER_LITERAL: return "INTEGER_LITERAL"; - case CHARACTER_LITERAL: return "CHARACTER_LITERAL"; - case STRING_LITERAL: return "STRING_LITERAL"; - case BOOLEAN_LITERAL: return "BOOLEAN_LITERAL"; - case HEADER_NAME: return "HEADER_NAME"; - case LANGLE: return "LANGLE"; - case RANGLE: return "RANGLE"; - case LPAREN: return "LPAREN"; - case RPAREN: return "RPAREN"; - case ELIPSIS: return "ELIPSIS"; - case LBRACK: return "LBRACK"; - case RBRACK: return "RBRACK"; - case LBRACE: return "LBRACE"; - case RBRACE: return "RBRACE"; - case EQ: return "EQ"; - case SCOPE: return "SCOPE"; - case SEMIC: return "SEMIC"; - case COLON: return "COLON"; - case DOTSTAR: return "DOTSTAR"; - case QUESTION: return "QUESTION"; - case DOT: return "DOT"; - case DYNAMIC_CAST: return "DYNAMIC_CAST"; - case STATIC_CAST: return "STATIC_CAST"; - case REINTERPRET_CAST: return "REINTERPRET_CAST"; - case CONST_CAST: return "CONST_CAST"; - case TYPEID: return "TYPEID"; - case THIS: return "THIS"; - case TEMPLATE: return "TEMPLATE"; - case THROW: return "THROW"; - case TRY: return "TRY"; - case CATCH: return "CATCH"; - case TYPEDEF: return "TYPEDEF"; - case FRIEND: return "FRIEND"; - case CLASS: return "CLASS"; - case NAMESPACE: return "NAMESPACE"; - case ENUM: return "ENUM"; - case STRUCT: return "STRUCT"; - case UNION: return "UNION"; - case VIRTUAL: return "VIRTUAL"; - case PRIVATE: return "PRIVATE"; - case PROTECTED: return "PROTECTED"; - case PUBLIC: return "PUBLIC"; - case EXPORT: return "EXPORT"; - case AUTO: return "AUTO"; - case REGISTER: return "REGISTER"; - case EXTERN: return "EXTERN"; - case MUTABLE: return "MUTABLE"; - case ASM: return "ASM"; - case USING: return "USING"; - case INLINE: return "INLINE"; - case EXPLICIT: return "EXPLICIT"; - case STATIC: return "STATIC"; - case CONST: return "CONST"; - case VOLATILE: return "VOLATILE"; - case OPERATOR: return "OPERATOR"; - case SIZEOF: return "SIZEOF"; - case NEW: return "NEW"; - case DELETE: return "DELETE"; - case PLUS: return "PLUS"; - case MINUS: return "MINUS"; - case STAR: return "STAR"; - case SLASH: return "SLASH"; - case PERCENT: return "PERCENT"; - case HAT: return "HAT"; - case AND: return "AND"; - case OR: return "OR"; - case TILDE: return "TILDE"; - case NOT: return "NOT"; - case PLUS_EQ: return "PLUS_EQ"; - case MINUS_EQ: return "MINUS_EQ"; - case STAR_EQ: return "STAR_EQ"; - case SLASH_EQ: return "SLASH_EQ"; - case PERCENT_EQ: return "PERCENT_EQ"; - case HAT_EQ: return "HAT_EQ"; - case AND_EQ: return "AND_EQ"; - case OR_EQ: return "OR_EQ"; - case LTLT: return "LTLT"; - case GTGT: return "GTGT"; - case GTGT_EQ: return "GTGT_EQ"; - case LTLT_EQ: return "LTLT_EQ"; - case EQEQ: return "EQEQ"; - case NE: return "NE"; - case LE: return "LE"; - case GE: return "GE"; - case ANDAND: return "ANDAND"; - case OROR: return "OROR"; - case INCR: return "INCR"; - case DECR: return "DECR"; - case COMMA: return "COMMA"; - case ARROW_STAR: return "ARROW_STAR"; - case ARROW: return "ARROW"; - case CHAR: return "CHAR"; - case WCHAR: return "WCHAR"; - case BOOL: return "BOOL"; - case SHORT: return "SHORT"; - case INT: return "INT"; - case LONG: return "LONG"; - case SIGNED: return "SIGNED"; - case UNSIGNED: return "UNSIGNED"; - case FLOAT: return "FLOAT"; - case DOUBLE: return "DOUBLE"; - case VOID: return "VOID"; - case CASE: return "CASE"; - case DEFAULT: return "DEFAULT"; - case IF: return "IF"; - case ELSE: return "ELSE"; - case SWITCH: return "SWITCH"; - case WHILE: return "WHILE"; - case DO: return "DO"; - case FOR: return "FOR"; - case BREAK: return "BREAK"; - case CONTINUE: return "CONTINUE"; - case GOTO: return "GOTO"; - case SIGNALS: return "SIGNALS"; - case SLOTS: return "SLOTS"; - case RETURN: return "RETURN"; - case Q_OBJECT_TOKEN: return "Q_OBJECT_TOKEN"; - case Q_GADGET_TOKEN: return "Q_GADGET_TOKEN"; - case Q_PROPERTY_TOKEN: return "Q_PROPERTY_TOKEN"; - case Q_ENUMS_TOKEN: return "Q_ENUMS_TOKEN"; - case Q_FLAGS_TOKEN: return "Q_FLAGS_TOKEN"; - case Q_DECLARE_FLAGS_TOKEN: return "Q_DECLARE_FLAGS_TOKEN"; - case Q_DECLARE_INTERFACE_TOKEN: return "Q_DECLARE_INTERFACE_TOKEN"; - case Q_CLASSINFO_TOKEN: return "Q_CLASSINFO_TOKEN"; - case Q_INTERFACES_TOKEN: return "Q_INTERFACES_TOKEN"; - case Q_SIGNALS_TOKEN: return "Q_SIGNALS_TOKEN"; - case Q_SLOTS_TOKEN: return "Q_SLOTS_TOKEN"; - case Q_SIGNAL_TOKEN: return "Q_SIGNAL_TOKEN"; - case Q_SLOT_TOKEN: return "Q_SLOT_TOKEN"; - case Q_PRIVATE_SLOT_TOKEN: return "Q_PRIVATE_SLOT_TOKEN"; - case Q_PRIVATE_PROPERTY_TOKEN: return "Q_PRIVATE_PROPERTY_TOKEN"; - case Q_REVISION_TOKEN: return "Q_REVISION_TOKEN"; - case SPECIAL_TREATMENT_MARK: return "SPECIAL_TREATMENT_MARK"; - case MOC_INCLUDE_BEGIN: return "MOC_INCLUDE_BEGIN"; - case MOC_INCLUDE_END: return "MOC_INCLUDE_END"; - case CPP_COMMENT: return "CPP_COMMENT"; - case C_COMMENT: return "C_COMMENT"; - case FLOATING_LITERAL: return "FLOATING_LITERAL"; - case HASH: return "HASH"; - case QUOTE: return "QUOTE"; - case SINGLEQUOTE: return "SINGLEQUOTE"; - case DIGIT: return "DIGIT"; - case CHARACTER: return "CHARACTER"; - case NEWLINE: return "NEWLINE"; - case WHITESPACE: return "WHITESPACE"; - case BACKSLASH: return "BACKSLASH"; - case INCOMPLETE: return "INCOMPLETE"; - case PP_DEFINE: return "PP_DEFINE"; - case PP_UNDEF: return "PP_UNDEF"; - case PP_IF: return "PP_IF"; - case PP_IFDEF: return "PP_IFDEF"; - case PP_IFNDEF: return "PP_IFNDEF"; - case PP_ELIF: return "PP_ELIF"; - case PP_ELSE: return "PP_ELSE"; - case PP_ENDIF: return "PP_ENDIF"; - case PP_INCLUDE: return "PP_INCLUDE"; - case PP_HASHHASH: return "PP_HASHHASH"; - case PP_HASH: return "PP_HASH"; - case PP_DEFINED: return "PP_DEFINED"; - case PP_INCOMPLETE: return "PP_INCOMPLETE"; - case PP_MOC_TRUE: return "PP_MOC_TRUE"; - case PP_MOC_FALSE: return "PP_MOC_FALSE"; - case Q_DECLARE_METATYPE_TOKEN: return "Q_DECLARE_METATYPE_TOKEN"; - case Q_MOC_COMPAT_TOKEN: return "Q_MOC_COMPAT_TOKEN"; - case Q_INVOKABLE_TOKEN: return "Q_INVOKABLE_TOKEN"; - case Q_SCRIPTABLE_TOKEN: return "Q_SCRIPTABLE_TOKEN"; +#define CREATE_CASE(Name) case Name: return #Name; + FOR_ALL_TOKENS(CREATE_CASE) +#undef CREATE_CASE } return ""; } diff --git a/src/tools/moc/token.h b/src/tools/moc/token.h index 378d4c63f7..2920fadbb9 100644 --- a/src/tools/moc/token.h +++ b/src/tools/moc/token.h @@ -46,222 +46,228 @@ QT_BEGIN_NAMESPACE -enum Token { - NOTOKEN, - IDENTIFIER, - INTEGER_LITERAL, - CHARACTER_LITERAL, - STRING_LITERAL, - BOOLEAN_LITERAL, - HEADER_NAME, - LANGLE, - RANGLE, - LPAREN, - RPAREN, - ELIPSIS, - LBRACK, - RBRACK, - LBRACE, - RBRACE, - EQ, - SCOPE, - SEMIC, - COLON, - DOTSTAR, - QUESTION, - DOT, - DYNAMIC_CAST, - STATIC_CAST, - REINTERPRET_CAST, - CONST_CAST, - TYPEID, - THIS, - TEMPLATE, - THROW, - TRY, - CATCH, - TYPEDEF, - FRIEND, - CLASS, - NAMESPACE, - ENUM, - STRUCT, - UNION, - VIRTUAL, - PRIVATE, - PROTECTED, - PUBLIC, - EXPORT, - AUTO, - REGISTER, - EXTERN, - MUTABLE, - ASM, - USING, - INLINE, - EXPLICIT, - STATIC, - CONST, - VOLATILE, - OPERATOR, - SIZEOF, - NEW, - DELETE, - PLUS, - MINUS, - STAR, - SLASH, - PERCENT, - HAT, - AND, - OR, - TILDE, - NOT, - PLUS_EQ, - MINUS_EQ, - STAR_EQ, - SLASH_EQ, - PERCENT_EQ, - HAT_EQ, - AND_EQ, - OR_EQ, - LTLT, - GTGT, - GTGT_EQ, - LTLT_EQ, - EQEQ, - NE, - LE, - GE, - ANDAND, - OROR, - INCR, - DECR, - COMMA, - ARROW_STAR, - ARROW, - CHAR, - WCHAR, - BOOL, - SHORT, - INT, - LONG, - SIGNED, - UNSIGNED, - FLOAT, - DOUBLE, - VOID, - CASE, - DEFAULT, - IF, - ELSE, - SWITCH, - WHILE, - DO, - FOR, - BREAK, - CONTINUE, - GOTO, - SIGNALS, - SLOTS, - RETURN, - Q_META_TOKEN_BEGIN, - Q_OBJECT_TOKEN = Q_META_TOKEN_BEGIN, - Q_GADGET_TOKEN, - Q_PROPERTY_TOKEN, - Q_PLUGIN_METADATA_TOKEN, - Q_ENUMS_TOKEN, - Q_FLAGS_TOKEN, - Q_DECLARE_FLAGS_TOKEN, - Q_DECLARE_INTERFACE_TOKEN, - Q_DECLARE_METATYPE_TOKEN, - Q_CLASSINFO_TOKEN, - Q_INTERFACES_TOKEN, - Q_SIGNALS_TOKEN, - Q_SLOTS_TOKEN, - Q_SIGNAL_TOKEN, - Q_SLOT_TOKEN, - Q_PRIVATE_SLOT_TOKEN, - Q_MOC_COMPAT_TOKEN, - Q_INVOKABLE_TOKEN, - Q_SCRIPTABLE_TOKEN, - Q_PRIVATE_PROPERTY_TOKEN, - Q_REVISION_TOKEN, - Q_META_TOKEN_END, - SPECIAL_TREATMENT_MARK = Q_META_TOKEN_END, - MOC_INCLUDE_BEGIN, - MOC_INCLUDE_END, - CPP_COMMENT, - C_COMMENT, - FLOATING_LITERAL, - HASH, - QUOTE, - SINGLEQUOTE, - LANGLE_SCOPE, - DIGIT, - CHARACTER, - NEWLINE, - WHITESPACE, - BACKSLASH, - INCOMPLETE, +#define FOR_ALL_TOKENS(F) \ + F(NOTOKEN) \ + F(IDENTIFIER) \ + F(INTEGER_LITERAL) \ + F(CHARACTER_LITERAL) \ + F(STRING_LITERAL) \ + F(BOOLEAN_LITERAL) \ + F(HEADER_NAME) \ + F(LANGLE) \ + F(RANGLE) \ + F(LPAREN) \ + F(RPAREN) \ + F(ELIPSIS) \ + F(LBRACK) \ + F(RBRACK) \ + F(LBRACE) \ + F(RBRACE) \ + F(EQ) \ + F(SCOPE) \ + F(SEMIC) \ + F(COLON) \ + F(DOTSTAR) \ + F(QUESTION) \ + F(DOT) \ + F(DYNAMIC_CAST) \ + F(STATIC_CAST) \ + F(REINTERPRET_CAST) \ + F(CONST_CAST) \ + F(TYPEID) \ + F(THIS) \ + F(TEMPLATE) \ + F(THROW) \ + F(TRY) \ + F(CATCH) \ + F(TYPEDEF) \ + F(FRIEND) \ + F(CLASS) \ + F(NAMESPACE) \ + F(ENUM) \ + F(STRUCT) \ + F(UNION) \ + F(VIRTUAL) \ + F(PRIVATE) \ + F(PROTECTED) \ + F(PUBLIC) \ + F(EXPORT) \ + F(AUTO) \ + F(REGISTER) \ + F(EXTERN) \ + F(MUTABLE) \ + F(ASM) \ + F(USING) \ + F(INLINE) \ + F(EXPLICIT) \ + F(STATIC) \ + F(CONST) \ + F(VOLATILE) \ + F(OPERATOR) \ + F(SIZEOF) \ + F(NEW) \ + F(DELETE) \ + F(PLUS) \ + F(MINUS) \ + F(STAR) \ + F(SLASH) \ + F(PERCENT) \ + F(HAT) \ + F(AND) \ + F(OR) \ + F(TILDE) \ + F(NOT) \ + F(PLUS_EQ) \ + F(MINUS_EQ) \ + F(STAR_EQ) \ + F(SLASH_EQ) \ + F(PERCENT_EQ) \ + F(HAT_EQ) \ + F(AND_EQ) \ + F(OR_EQ) \ + F(LTLT) \ + F(GTGT) \ + F(GTGT_EQ) \ + F(LTLT_EQ) \ + F(EQEQ) \ + F(NE) \ + F(LE) \ + F(GE) \ + F(ANDAND) \ + F(OROR) \ + F(INCR) \ + F(DECR) \ + F(COMMA) \ + F(ARROW_STAR) \ + F(ARROW) \ + F(CHAR) \ + F(WCHAR) \ + F(BOOL) \ + F(SHORT) \ + F(INT) \ + F(LONG) \ + F(SIGNED) \ + F(UNSIGNED) \ + F(FLOAT) \ + F(DOUBLE) \ + F(VOID) \ + F(CASE) \ + F(DEFAULT) \ + F(IF) \ + F(ELSE) \ + F(SWITCH) \ + F(WHILE) \ + F(DO) \ + F(FOR) \ + F(BREAK) \ + F(CONTINUE) \ + F(GOTO) \ + F(SIGNALS) \ + F(SLOTS) \ + F(RETURN) \ + F(Q_OBJECT_TOKEN) \ + F(Q_GADGET_TOKEN) \ + F(Q_PROPERTY_TOKEN) \ + F(Q_PLUGIN_METADATA_TOKEN) \ + F(Q_ENUMS_TOKEN) \ + F(Q_FLAGS_TOKEN) \ + F(Q_DECLARE_FLAGS_TOKEN) \ + F(Q_DECLARE_INTERFACE_TOKEN) \ + F(Q_DECLARE_METATYPE_TOKEN) \ + F(Q_CLASSINFO_TOKEN) \ + F(Q_INTERFACES_TOKEN) \ + F(Q_SIGNALS_TOKEN) \ + F(Q_SLOTS_TOKEN) \ + F(Q_SIGNAL_TOKEN) \ + F(Q_SLOT_TOKEN) \ + F(Q_PRIVATE_SLOT_TOKEN) \ + F(Q_MOC_COMPAT_TOKEN) \ + F(Q_INVOKABLE_TOKEN) \ + F(Q_SCRIPTABLE_TOKEN) \ + F(Q_PRIVATE_PROPERTY_TOKEN) \ + F(Q_REVISION_TOKEN) \ + F(SPECIAL_TREATMENT_MARK) \ + F(MOC_INCLUDE_BEGIN) \ + F(MOC_INCLUDE_END) \ + F(CPP_COMMENT) \ + F(C_COMMENT) \ + F(FLOATING_LITERAL) \ + F(HASH) \ + F(QUOTE) \ + F(SINGLEQUOTE) \ + F(LANGLE_SCOPE) \ + F(DIGIT) \ + F(CHARACTER) \ + F(NEWLINE) \ + F(WHITESPACE) \ + F(BACKSLASH) \ + F(INCOMPLETE) \ + F(PP_DEFINE) \ + F(PP_UNDEF) \ + F(PP_IF) \ + F(PP_IFDEF) \ + F(PP_IFNDEF) \ + F(PP_ELIF) \ + F(PP_ELSE) \ + F(PP_ENDIF) \ + F(PP_INCLUDE) \ + F(PP_HASHHASH) \ + F(PP_HASH) \ + F(PP_DEFINED) \ + F(PP_INCOMPLETE) \ + F(PP_MOC_TRUE) \ + F(PP_MOC_FALSE) + - PP_DEFINE, - PP_UNDEF, - PP_IF, - PP_IFDEF, - PP_IFNDEF, - PP_ELIF, - PP_ELSE, - PP_ENDIF, - PP_INCLUDE, - PP_HASHHASH, - PP_HASH, - PP_DEFINED, - PP_INCOMPLETE, +enum Token { - PP_MOC_TRUE, - PP_MOC_FALSE, +#define CREATE_ENUM_VALUE(Name) Name, + FOR_ALL_TOKENS(CREATE_ENUM_VALUE) +#undef CREATE_ENUM_VALUE - PP_NOTOKEN = NOTOKEN, + // aliases + PP_AND = AND, + PP_ANDAND = ANDAND, + PP_BACKSLASH = BACKSLASH, + PP_CHARACTER = CHARACTER, + PP_CHARACTER_LITERAL = CHARACTER_LITERAL, + PP_COLON = COLON, + PP_COMMA = COMMA, + PP_CPP_COMMENT = CPP_COMMENT, + PP_C_COMMENT = C_COMMENT, + PP_DIGIT = DIGIT, + PP_EQEQ = EQEQ, + PP_FLOATING_LITERAL = FLOATING_LITERAL, + PP_GE = GE, + PP_GTGT = GTGT, + PP_HAT = HAT, PP_IDENTIFIER = IDENTIFIER, PP_INTEGER_LITERAL = INTEGER_LITERAL, - PP_CHARACTER_LITERAL = CHARACTER_LITERAL, - PP_STRING_LITERAL = STRING_LITERAL, PP_LANGLE = LANGLE, - PP_RANGLE = RANGLE, + PP_LE = LE, PP_LPAREN = LPAREN, - PP_RPAREN = RPAREN, - PP_COMMA = COMMA, - PP_PLUS = PLUS, - PP_MINUS = MINUS, - PP_STAR = STAR, - PP_SLASH = SLASH, - PP_PERCENT = PERCENT, - PP_HAT = HAT, - PP_AND = AND, - PP_OR = OR, - PP_TILDE = TILDE, - PP_NOT = NOT, PP_LTLT = LTLT, - PP_GTGT = GTGT, - PP_EQEQ = EQEQ, + PP_MINUS = MINUS, PP_NE = NE, - PP_LE = LE, - PP_GE = GE, - PP_ANDAND = ANDAND, + PP_NEWLINE = NEWLINE, + PP_NOTOKEN = NOTOKEN, + PP_NOT = NOT, + PP_OR = OR, PP_OROR = OROR, + PP_PERCENT = PERCENT, + PP_PLUS = PLUS, PP_QUESTION = QUESTION, - PP_COLON = COLON, - PP_FLOATING_LITERAL = FLOATING_LITERAL, PP_QUOTE = QUOTE, + PP_RANGLE = RANGLE, + PP_RPAREN = RPAREN, PP_SINGLEQUOTE = SINGLEQUOTE, - PP_DIGIT = DIGIT, - PP_CHARACTER = CHARACTER, + PP_SLASH = SLASH, + PP_STAR = STAR, + PP_STRING_LITERAL = STRING_LITERAL, + PP_TILDE = TILDE, PP_WHITESPACE = WHITESPACE, - PP_NEWLINE = NEWLINE, - PP_CPP_COMMENT = CPP_COMMENT, - PP_C_COMMENT = C_COMMENT, - PP_BACKSLASH = BACKSLASH + Q_META_TOKEN_BEGIN = Q_OBJECT_TOKEN, + Q_META_TOKEN_END = SPECIAL_TREATMENT_MARK }; // for debugging only diff --git a/src/widgets/Qt5WidgetsConfigExtras.cmake.in b/src/widgets/Qt5WidgetsConfigExtras.cmake.in index e5650ff362..99d87e2e46 100644 --- a/src/widgets/Qt5WidgetsConfigExtras.cmake.in +++ b/src/widgets/Qt5WidgetsConfigExtras.cmake.in @@ -14,4 +14,6 @@ if (NOT TARGET Qt5::uic) ) endif() +include(\"${CMAKE_CURRENT_LIST_DIR}/Qt5Widgets_AccessibleFactory.cmake\" OPTIONAL) + set(Qt5Widgets_UIC_EXECUTABLE Qt5::uic) diff --git a/src/widgets/graphicsview/qgraphicsproxywidget.cpp b/src/widgets/graphicsview/qgraphicsproxywidget.cpp index 68944817f6..f5db85b698 100644 --- a/src/widgets/graphicsview/qgraphicsproxywidget.cpp +++ b/src/widgets/graphicsview/qgraphicsproxywidget.cpp @@ -379,6 +379,10 @@ QWidget *QGraphicsProxyWidgetPrivate::findFocusChild(QWidget *child, bool next) void QGraphicsProxyWidgetPrivate::_q_removeWidgetSlot() { Q_Q(QGraphicsProxyWidget); + if (!widget.isNull()) { + if (QWExtra *extra = widget->d_func()->extra) + extra->proxyWidget = 0; + } widget = 0; delete q; } diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index ed376fe923..b4c4ffe7c7 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -336,6 +336,15 @@ QApplicationPrivate::~QApplicationPrivate() */ /*! + \fn QApplication::setGraphicsSystem(const QString &) + \obsolete + + This call has no effect. + + Use the QPA framework instead. +*/ + +/*! \fn QWidget *QApplication::topLevelAt(const QPoint &point) Returns the top-level widget at the given \a point; returns 0 if @@ -359,6 +368,7 @@ QApplicationPrivate::~QApplicationPrivate() void qt_init(QApplicationPrivate *priv, int type ); +void qt_init_tooltip_palette(); void qt_cleanup(); QStyle *QApplicationPrivate::app_style = 0; // default application style @@ -4016,6 +4026,7 @@ void QApplicationPrivate::notifyThemeChanged() QGuiApplicationPrivate::notifyThemeChanged(); clearSystemPalette(); initSystemPalette(); + qt_init_tooltip_palette(); } #ifndef QT_NO_DRAGANDDROP diff --git a/src/widgets/kernel/qapplication_qpa.cpp b/src/widgets/kernel/qapplication_qpa.cpp index c68bcc773f..5893c52e1b 100644 --- a/src/widgets/kernel/qapplication_qpa.cpp +++ b/src/widgets/kernel/qapplication_qpa.cpp @@ -442,6 +442,14 @@ void QApplication::alert(QWidget *widget, int duration) } } +void qt_init_tooltip_palette() +{ +#ifndef QT_NO_TOOLTIP + if (const QPalette *toolTipPalette = QGuiApplicationPrivate::platformTheme()->palette(QPlatformTheme::ToolTipPalette)) + QToolTip::setPalette(*toolTipPalette); +#endif +} + void qt_init(QApplicationPrivate *priv, int type) { Q_UNUSED(priv); @@ -449,10 +457,7 @@ void qt_init(QApplicationPrivate *priv, int type) QColormap::initialize(); -#ifndef QT_NO_TOOLTIP - if (const QPalette *toolTipPalette = QGuiApplicationPrivate::platformTheme()->palette(QPlatformTheme::ToolTipPalette)) - QToolTip::setPalette(*toolTipPalette); -#endif + qt_init_tooltip_palette(); QApplicationPrivate::initializeWidgetFontHash(); } diff --git a/src/widgets/kernel/qtooltip.cpp b/src/widgets/kernel/qtooltip.cpp index 5aea55e196..2b43fd7f6d 100644 --- a/src/widgets/kernel/qtooltip.cpp +++ b/src/widgets/kernel/qtooltip.cpp @@ -512,9 +512,9 @@ void QToolTip::showText(const QPoint &pos, const QString &text, QWidget *w, cons else if (QApplication::isEffectEnabled(Qt::UI_AnimateTooltip)) qScrollEffect(QTipLabel::instance); else - QTipLabel::instance->show(); + QTipLabel::instance->showNormal(); #else - QTipLabel::instance->show(); + QTipLabel::instance->showNormal(); #endif } } diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 7eecd3d84d..65e435fbdc 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -6002,10 +6002,8 @@ void QWidget::setFocus(Qt::FocusReason reason) if (!(testAttribute(Qt::WA_WState_Created) && window()->windowType() != Qt::Popup && internalWinId())) //setFocusWidget will already post a focus event for us (that the AT client receives) on Windows # endif -# ifdef Q_OS_UNIX // menus update the focus manually and this would create bogus events if (!(f->inherits("QMenuBar") || f->inherits("QMenu") || f->inherits("QMenuItem"))) -# endif { QAccessibleEvent event(f, QAccessible::Focus); QAccessible::updateAccessibility(&event); @@ -8525,6 +8523,8 @@ void QWidget::mouseReleaseEvent(QMouseEvent *event) This event handler, for event \a event, can be reimplemented in a subclass to receive mouse double click events for the widget. + The default implementation calls mousePressEvent(). + \note The widget will also receive mouse press and mouse release events in addition to the double click event. It is up to the developer to ensure that the application interprets these events @@ -8536,7 +8536,7 @@ void QWidget::mouseReleaseEvent(QMouseEvent *event) void QWidget::mouseDoubleClickEvent(QMouseEvent *event) { - event->ignore(); + mousePressEvent(event); } #ifndef QT_NO_WHEELEVENT diff --git a/src/widgets/widgets/qfontcombobox.cpp b/src/widgets/widgets/qfontcombobox.cpp index 2bbf3730db..40ca73904c 100644 --- a/src/widgets/widgets/qfontcombobox.cpp +++ b/src/widgets/widgets/qfontcombobox.cpp @@ -50,6 +50,7 @@ #include <qevent.h> #include <qapplication.h> #include <private/qcombobox_p.h> +#include <QDesktopWidget> #include <qdebug.h> QT_BEGIN_NAMESPACE @@ -546,8 +547,10 @@ bool QFontComboBox::event(QEvent *e) { if (e->type() == QEvent::Resize) { QListView *lview = qobject_cast<QListView*>(view()); - if (lview) - lview->window()->setFixedWidth(width() * 5 / 3); + if (lview) { + setFixedWidth(qMin(width() * 5 / 3, + QApplication::desktop()->availableGeometry(lview).width())); + } } return QComboBox::event(e); } diff --git a/src/widgets/widgets/qmacnativewidget_mac.mm b/src/widgets/widgets/qmacnativewidget_mac.mm index 66a1ed7ce7..d3f3515b04 100644 --- a/src/widgets/widgets/qmacnativewidget_mac.mm +++ b/src/widgets/widgets/qmacnativewidget_mac.mm @@ -128,6 +128,7 @@ QMacNativeWidget::QMacNativeWidget(NSView *parentView) setAttribute(Qt::WA_SetPalette, false); setAttribute(Qt::WA_LayoutUsesWidgetRect); setAttribute(Qt::WA_TranslucentBackground); + setAttribute(Qt::WA_NoSystemBackground, false); } /*! diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index eb93e461c0..403ebe7f49 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -50,6 +50,9 @@ #include "qlayout.h" #include "qpainter.h" #include <qpa/qplatformtheme.h> +#ifdef Q_OS_OSX +#include "qmacnativewidget_mac.h" +#endif #include "qapplication.h" #include "qdesktopwidget.h" #ifndef QT_NO_ACCESSIBILITY @@ -163,7 +166,7 @@ void QMenuPrivate::setPlatformMenu(QPlatformMenu *menu) platformMenu = menu; if (!platformMenu.isNull()) { - QObject::connect(platformMenu, SIGNAL(aboutToShow()), q, SIGNAL(aboutToShow())); + QObject::connect(platformMenu, SIGNAL(aboutToShow()), q, SLOT(_q_platformMenuAboutToShow())); QObject::connect(platformMenu, SIGNAL(aboutToHide()), q, SIGNAL(aboutToHide())); } } @@ -1091,9 +1094,6 @@ void QMenuPrivate::activateAction(QAction *action, QAction::ActionEvent action_e QAccessibleEvent focusEvent(q, QAccessible::Focus); focusEvent.setChild(actionIndex); QAccessible::updateAccessibility(&focusEvent); - QAccessibleEvent selectionEvent(q, QAccessible::Selection); - focusEvent.setChild(actionIndex); - QAccessible::updateAccessibility(&selectionEvent); } #endif action->showStatusText(topCausedWidget()); @@ -1107,6 +1107,8 @@ void QMenuPrivate::_q_actionTriggered() Q_Q(QMenu); if (QAction *action = qobject_cast<QAction *>(q->sender())) { QPointer<QAction> actionGuard = action; + if (platformMenu && widgetItems.value(action)) + platformMenu->dismiss(); emit q->triggered(action); if (!activationRecursionGuard && actionGuard) { //in case the action has not been activated by the mouse @@ -1137,6 +1139,24 @@ void QMenuPrivate::_q_actionHovered() } } +void QMenuPrivate::_q_platformMenuAboutToShow() +{ + Q_Q(QMenu); + +#ifdef Q_OS_OSX + if (platformMenu) + Q_FOREACH (QAction *action, q->actions()) + if (QWidget *widget = widgetItems.value(const_cast<QAction *>(action))) + if (widget->parent() == q) { + QPlatformMenuItem *menuItem = platformMenu->menuItemForTag(reinterpret_cast<quintptr>(action)); + moveWidgetToPlatformItem(widget, menuItem); + platformMenu->syncMenuItem(menuItem); + } +#endif + + emit q->aboutToShow(); +} + bool QMenuPrivate::hasMouseMoved(const QPoint &globalPos) { //determines if the mouse has moved (ie its initial position has @@ -2999,8 +3019,19 @@ void QMenu::actionEvent(QActionEvent *e) if (e->action() == d->currentAction) d->currentAction = 0; if (QWidgetAction *wa = qobject_cast<QWidgetAction *>(e->action())) { - if (QWidget *widget = d->widgetItems.value(wa)) + if (QWidget *widget = d->widgetItems.value(wa)) { +#ifdef Q_OS_OSX + QWidget *p = widget->parentWidget(); + if (p != this && qobject_cast<QMacNativeWidget *>(p)) { + // This widget was reparented into a native Mac view + // (see QMenuPrivate::moveWidgetToPlatformItem). + // Reset the parent and delete the native widget. + widget->setParent(this); + p->deleteLater(); + } +#endif wa->releaseWidget(widget); + } } d->widgetItems.remove(e->action()); } diff --git a/src/widgets/widgets/qmenu.h b/src/widgets/widgets/qmenu.h index 8a8eaf3bae..fef7903278 100644 --- a/src/widgets/widgets/qmenu.h +++ b/src/widgets/widgets/qmenu.h @@ -195,6 +195,7 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_actionTriggered()) Q_PRIVATE_SLOT(d_func(), void _q_actionHovered()) Q_PRIVATE_SLOT(d_func(), void _q_overrideMenuActionDestroyed()) + Q_PRIVATE_SLOT(d_func(), void _q_platformMenuAboutToShow()) protected: QMenu(QMenuPrivate &dd, QWidget* parent = 0); diff --git a/src/widgets/widgets/qmenu_mac.mm b/src/widgets/widgets/qmenu_mac.mm index 41c4481b74..5e304d058b 100644 --- a/src/widgets/widgets/qmenu_mac.mm +++ b/src/widgets/widgets/qmenu_mac.mm @@ -44,6 +44,8 @@ #include "qmenu.h" #include "qmenubar.h" +#include "qmenubar_p.h" +#include "qmacnativewidget_mac.h" #include <QtCore/QDebug> #include <QtGui/QGuiApplication> @@ -115,6 +117,23 @@ void QMenu::setAsDockMenu() \sa QMenu:setAsDockMenu() */ +void QMenuPrivate::moveWidgetToPlatformItem(QWidget *widget, QPlatformMenuItem* item) +{ + QMacNativeWidget *container = new QMacNativeWidget; + QObject::connect(platformMenu, SIGNAL(destroyed()), container, SLOT(deleteLater())); + container->resize(widget->sizeHint()); + widget->setParent(container); + + NSView *containerView = container->nativeView(); + QWindow *containerWindow = container->windowHandle(); + Qt::WindowFlags wf = containerWindow->flags(); + containerWindow->setFlags(wf | Qt::SubWindow); + [(NSView *)widget->winId() setAutoresizingMask:NSViewWidthSizable]; + + item->setNativeContents((WId)containerView); + container->show(); +} + #endif //QT_NO_MENU #ifndef QT_NO_MENUBAR diff --git a/src/widgets/widgets/qmenu_p.h b/src/widgets/widgets/qmenu_p.h index 9d9851af64..71bf33e1ce 100644 --- a/src/widgets/widgets/qmenu_p.h +++ b/src/widgets/widgets/qmenu_p.h @@ -110,6 +110,9 @@ public: void init(); void setPlatformMenu(QPlatformMenu *menu); void syncPlatformMenu(); +#ifdef Q_OS_OSX + void moveWidgetToPlatformItem(QWidget *w, QPlatformMenuItem* item); +#endif static QMenuPrivate *get(QMenu *m) { return m->d_func(); } int scrollerHeight() const; @@ -223,6 +226,7 @@ public: void _q_actionTriggered(); void _q_actionHovered(); + void _q_platformMenuAboutToShow(); bool hasMouseMoved(const QPoint &globalPos); diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp index 03ab490823..729e08c7a5 100644 --- a/src/widgets/widgets/qmenubar.cpp +++ b/src/widgets/widgets/qmenubar.cpp @@ -531,9 +531,6 @@ void QMenuBarPrivate::_q_actionHovered() QAccessibleEvent focusEvent(q, QAccessible::Focus); focusEvent.setChild(actionIndex); QAccessible::updateAccessibility(&focusEvent); - QAccessibleEvent selectionEvent(q, QAccessible::Selection); - selectionEvent.setChild(actionIndex); - QAccessible::updateAccessibility(&selectionEvent); } #endif //QT_NO_ACCESSIBILITY } diff --git a/src/xml/sax/qxml.cpp b/src/xml/sax/qxml.cpp index 4b434822b8..9d91ce42a5 100644 --- a/src/xml/sax/qxml.cpp +++ b/src/xml/sax/qxml.cpp @@ -3247,7 +3247,7 @@ void QXmlSimpleReader::setFeature(const QString& name, bool enable) || name == QLatin1String("http://qt-project.org/xml/features/report-whitespace-only-CharData")) { d->reportWhitespaceCharData = enable; } else if (name == QLatin1String("http://trolltech.com/xml/features/report-start-end-entity") // For compat with Qt 4 - || name == QLatin1String("http://trolltech.com/xml/features/report-start-end-entity")) { + || name == QLatin1String("http://qt-project.org/xml/features/report-start-end-entity")) { d->reportEntities = enable; } else { qWarning("Unknown feature %s", name.toLatin1().data()); diff --git a/tests/auto/corelib/codecs/utf8/tst_utf8.cpp b/tests/auto/corelib/codecs/utf8/tst_utf8.cpp index b00fd0dfd4..d1aadab7d8 100644 --- a/tests/auto/corelib/codecs/utf8/tst_utf8.cpp +++ b/tests/auto/corelib/codecs/utf8/tst_utf8.cpp @@ -53,11 +53,7 @@ public: // test data: QTextCodec *codec; QString (*from8BitPtr)(const char *, int); -#ifdef Q_COMPILER_REF_QUALIFIERS - QByteArray (QString:: *to8Bit)() const &; -#else - QByteArray (QString:: *to8Bit)() const; -#endif + static QByteArray to8Bit(const QString &); inline QString from8Bit(const QByteArray &ba) { return from8BitPtr(ba.constData(), ba.length()); } @@ -97,14 +93,21 @@ void tst_Utf8::init() if (useLocale) { codec = QTextCodec::codecForLocale(); from8BitPtr = &QString::fromLocal8Bit; - to8Bit = &QString::toLocal8Bit; } else { codec = QTextCodec::codecForMib(106); from8BitPtr = &QString::fromUtf8; - to8Bit = &QString::toUtf8; } } +QByteArray tst_Utf8::to8Bit(const QString &s) +{ + QFETCH_GLOBAL(bool, useLocale); + if (useLocale) + return s.toLocal8Bit(); + else + return s.toUtf8(); +} + void tst_Utf8::roundTrip_data() { QTest::addColumn<QByteArray>("utf8"); @@ -114,10 +117,10 @@ void tst_Utf8::roundTrip_data() QTest::newRow("nul") << QByteArray("", 1) << QString(QChar(QChar::Null)); static const char ascii[] = "This is a standard US-ASCII message"; - QTest::newRow("ascii") << QByteArray(ascii) << ascii; + QTest::newRow("ascii") << QByteArray(ascii) << QString::fromLatin1(ascii); static const char ascii2[] = "\1This\2is\3an\4US-ASCII\020 message interspersed with control chars"; - QTest::newRow("ascii2") << QByteArray(ascii2) << ascii2; + QTest::newRow("ascii2") << QByteArray(ascii2) << QString::fromLatin1(ascii2); static const char utf8_1[] = "\302\240"; // NBSP QTest::newRow("utf8_1") << QByteArray(utf8_1) << QString(QChar(QChar::Nbsp)); @@ -161,11 +164,20 @@ void tst_Utf8::roundTrip() QFETCH(QByteArray, utf8); QFETCH(QString, utf16); - QCOMPARE((utf16.*to8Bit)(), utf8); + QCOMPARE(to8Bit(utf16), utf8); + QCOMPARE(from8Bit(utf8), utf16); + + QCOMPARE(to8Bit(from8Bit(utf8)), utf8); + QCOMPARE(from8Bit(to8Bit(utf16)), utf16); + + // repeat with a longer message + utf8.prepend("12345678901234"); + utf16.prepend(QLatin1String("12345678901234")); + QCOMPARE(to8Bit(utf16), utf8); QCOMPARE(from8Bit(utf8), utf16); - QCOMPARE((from8Bit(utf8).*to8Bit)(), utf8); - QCOMPARE(from8Bit((utf16.*to8Bit)()), utf16); + QCOMPARE(to8Bit(from8Bit(utf8)), utf8); + QCOMPARE(from8Bit(to8Bit(utf16)), utf16); } void tst_Utf8::charByChar_data() diff --git a/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp b/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp index a58c7dfb4b..4f7ddce9c3 100644 --- a/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp +++ b/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.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. @@ -405,6 +405,13 @@ void tst_QFileSystemWatcher::removePaths() watcher.removePaths(paths); } +static QByteArray msgFileOperationFailed(const char *what, const QFile &f) +{ + return what + QByteArrayLiteral(" failed on \"") + + QDir::toNativeSeparators(f.fileName()).toLocal8Bit() + + QByteArrayLiteral("\": ") + f.errorString().toLocal8Bit(); +} + void tst_QFileSystemWatcher::watchFileAndItsDirectory() { QFETCH(QString, backend); @@ -420,14 +427,10 @@ void tst_QFileSystemWatcher::watchFileAndItsDirectory() QString testFileName = testDir.filePath("testFile.txt"); QString secondFileName = testDir.filePath("testFile2.txt"); - QFile::remove(secondFileName); QFile testFile(testFileName); - testFile.setPermissions(QFile::ReadOwner | QFile::WriteOwner); - testFile.remove(); - - QVERIFY(testFile.open(QIODevice::WriteOnly | QIODevice::Truncate)); - testFile.write(QByteArray("hello")); + QVERIFY2(testFile.open(QIODevice::WriteOnly | QIODevice::Truncate), msgFileOperationFailed("open", testFile)); + QVERIFY2(testFile.write(QByteArrayLiteral("hello")) > 0, msgFileOperationFailed("write", testFile)); testFile.close(); QFileSystemWatcher watcher; @@ -449,8 +452,8 @@ void tst_QFileSystemWatcher::watchFileAndItsDirectory() // wait before modifying the directory... QTest::qWait(2000); - QVERIFY(testFile.open(QIODevice::WriteOnly | QIODevice::Truncate)); - testFile.write(QByteArray("hello again")); + QVERIFY2(testFile.open(QIODevice::WriteOnly | QIODevice::Truncate), msgFileOperationFailed("open", testFile)); + QVERIFY2(testFile.write(QByteArrayLiteral("hello again")), msgFileOperationFailed("write", testFile)); testFile.close(); #ifdef Q_OS_MAC @@ -472,8 +475,8 @@ void tst_QFileSystemWatcher::watchFileAndItsDirectory() fileChangedSpy.clear(); dirChangedSpy.clear(); QFile secondFile(secondFileName); - secondFile.open(QIODevice::WriteOnly | QIODevice::Truncate); - secondFile.write("Foo"); + QVERIFY2(secondFile.open(QIODevice::WriteOnly | QIODevice::Truncate), msgFileOperationFailed("open", secondFile)); + QVERIFY2(secondFile.write(QByteArrayLiteral("Foo")) > 0, msgFileOperationFailed("write", secondFile)); secondFile.close(); timer.start(3000); @@ -491,17 +494,17 @@ void tst_QFileSystemWatcher::watchFileAndItsDirectory() dirChangedSpy.clear(); - QFile::remove(testFileName); + QVERIFY(QFile::remove(testFileName)); QTRY_VERIFY(fileChangedSpy.count() > 0); - QCOMPARE(dirChangedSpy.count(), 1); + QTRY_COMPARE(dirChangedSpy.count(), 1); fileChangedSpy.clear(); dirChangedSpy.clear(); // removing a deleted file should fail QVERIFY(!watcher.removePath(testFileName)); - QFile::remove(secondFileName); + QVERIFY(QFile::remove(secondFileName)); timer.start(3000); eventLoop.exec(); diff --git a/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp b/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp index 6e183f3212..cdcbd19ae8 100644 --- a/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp +++ b/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp @@ -1863,7 +1863,7 @@ void tst_QByteArray::reserve() QCOMPARE(qba.capacity(), capacity); QCOMPARE(copy.capacity(), capacity); - copy = qba; + qba = copy; qba.reserve(capacity * 2); QCOMPARE(qba.size(), capacity); QCOMPARE(qba.capacity(), capacity * 2); diff --git a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp index 6ef9957fa1..e551d99959 100644 --- a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp +++ b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp @@ -48,6 +48,10 @@ #include <qpa/qwindowsysteminterface.h> #include <qgenericplugin.h> +#if defined(Q_OS_QNX) +#include <QOpenGLContext> +#endif + #include <QDebug> #include "tst_qcoreapplication.h" @@ -124,6 +128,9 @@ void tst_QGuiApplication::focusObject() const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry(); DummyWindow window1; +#if defined(Q_OS_QNX) + window1.setSurfaceType(QSurface::OpenGLSurface); +#endif window1.resize(windowSize, windowSize); window1.setTitle(QStringLiteral("focusObject:window1")); window1.setFramePosition(QPoint(screenGeometry.left() + spacing, screenGeometry.top() + spacing)); @@ -134,6 +141,15 @@ void tst_QGuiApplication::focusObject() window1.show(); +#if defined(Q_OS_QNX) // We either need to create a eglSurface or a create a backing store + // and then post the window in order for screen to show the window + QOpenGLContext context; + context.create(); + context.makeCurrent(&window1); + QTest::qWaitForWindowExposed(&window1); // Buffer swap only succeeds with exposed window + context.swapBuffers(&window1); +#endif + QSignalSpy spy(&app, SIGNAL(focusObjectChanged(QObject*))); @@ -279,15 +295,35 @@ void tst_QGuiApplication::changeFocusWindow() // focus is changed between FocusAboutToChange and FocusChanged FocusChangeWindow window1; +#if defined(Q_OS_QNX) + window1.setSurfaceType(QSurface::OpenGLSurface); +#endif window1.resize(windowSize, windowSize); window1.setFramePosition(QPoint(screenGeometry.left() + spacing, screenGeometry.top() + spacing)); window1.setTitle(QStringLiteral("changeFocusWindow:window1")); window1.show(); +#if defined(Q_OS_QNX) // We either need to create a eglSurface or a create a backing store + // and then post the window in order for screen to show the window + QOpenGLContext context; + context.create(); + context.makeCurrent(&window1); + QTest::qWaitForWindowExposed(&window1); // Buffer swap only succeeds with exposed window + context.swapBuffers(&window1); +#endif FocusChangeWindow window2; +#if defined(Q_OS_QNX) + window2.setSurfaceType(QSurface::OpenGLSurface); +#endif window2.resize(windowSize, windowSize); window2.setFramePosition(QPoint(screenGeometry.left() + 2 * spacing + windowSize, screenGeometry.top() + spacing)); window2.setTitle(QStringLiteral("changeFocusWindow:window2")); window2.show(); +#if defined(Q_OS_QNX) // We either need to create a eglSurface or a create a backing store + // and then post the window in order for screen to show the window + context.makeCurrent(&window2); + QTest::qWaitForWindowExposed(&window2); // Buffer swap only succeeds with exposed window + context.swapBuffers(&window2); +#endif QVERIFY(QTest::qWaitForWindowExposed(&window1)); QVERIFY(QTest::qWaitForWindowExposed(&window2)); window1.requestActivate(); diff --git a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp index eefa85a745..589f3e66e1 100644 --- a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp +++ b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp @@ -88,6 +88,10 @@ private slots: void visibility(); void mask(); void initialSize(); + void modalDialog(); + void modalDialogClosingOneOfTwoModal(); + void modalWithChildWindow(); + void modalWindowModallity(); void initTestCase() { @@ -1316,6 +1320,115 @@ void tst_QWindow::initialSize() } } +void tst_QWindow::modalDialog() +{ + QWindow normalWindow; + normalWindow.resize(400, 400); + normalWindow.show(); + QVERIFY(QTest::qWaitForWindowExposed(&normalWindow)); + + QWindow dialog; + dialog.resize(200,200); + dialog.setModality(Qt::ApplicationModal); + dialog.setFlags(Qt::Dialog); + dialog.show(); + QVERIFY(QTest::qWaitForWindowExposed(&dialog)); + + normalWindow.requestActivate(); + + QGuiApplication::sync(); + QGuiApplication::processEvents(); + QTRY_COMPARE(QGuiApplication::focusWindow(), &dialog); +} + +void tst_QWindow::modalDialogClosingOneOfTwoModal() +{ + QWindow normalWindow; + normalWindow.resize(400, 400); + normalWindow.show(); + QVERIFY(QTest::qWaitForWindowExposed(&normalWindow)); + + QWindow first_dialog; + first_dialog.resize(200,200); + first_dialog.setModality(Qt::ApplicationModal); + first_dialog.setFlags(Qt::Dialog); + first_dialog.show(); + QVERIFY(QTest::qWaitForWindowExposed(&first_dialog)); + + { + QWindow second_dialog; + second_dialog.resize(200,200); + second_dialog.setModality(Qt::ApplicationModal); + second_dialog.setFlags(Qt::Dialog); + second_dialog.show(); + QVERIFY(QTest::qWaitForWindowExposed(&second_dialog)); + + QTRY_COMPARE(QGuiApplication::focusWindow(), &second_dialog); + + second_dialog.close(); + } + + QGuiApplication::sync(); + QGuiApplication::processEvents(); + QTRY_COMPARE(QGuiApplication::focusWindow(), &first_dialog); +} + +void tst_QWindow::modalWithChildWindow() +{ + QWindow normalWindow; + normalWindow.resize(400, 400); + normalWindow.show(); + QVERIFY(QTest::qWaitForWindowExposed(&normalWindow)); + + QWindow tlw_dialog; + tlw_dialog.resize(400,200); + tlw_dialog.setModality(Qt::ApplicationModal); + tlw_dialog.setFlags(Qt::Dialog); + tlw_dialog.create(); + + QWindow sub_window(&tlw_dialog); + sub_window.resize(200,300); + sub_window.show(); + + tlw_dialog.show(); + QVERIFY(QTest::qWaitForWindowExposed(&tlw_dialog)); + QVERIFY(QTest::qWaitForWindowExposed(&sub_window)); + + QTRY_COMPARE(QGuiApplication::focusWindow(), &tlw_dialog); + + sub_window.requestActivate(); + QGuiApplication::sync(); + QGuiApplication::processEvents(); + QTRY_COMPARE(QGuiApplication::focusWindow(), &sub_window); +} + +void tst_QWindow::modalWindowModallity() +{ + QWindow normal_window; + normal_window.resize(400, 400); + normal_window.show(); + QVERIFY(QTest::qWaitForWindowExposed(&normal_window)); + + QWindow parent_to_modal; + parent_to_modal.resize(400, 400); + parent_to_modal.show(); + QVERIFY(QTest::qWaitForWindowExposed(&parent_to_modal)); + QTRY_COMPARE(QGuiApplication::focusWindow(), &parent_to_modal); + + QWindow modal_dialog; + modal_dialog.resize(400,200); + modal_dialog.setModality(Qt::WindowModal); + modal_dialog.setFlags(Qt::Dialog); + modal_dialog.setTransientParent(&parent_to_modal); + modal_dialog.show(); + QVERIFY(QTest::qWaitForWindowExposed(&modal_dialog)); + QTRY_COMPARE(QGuiApplication::focusWindow(), &modal_dialog); + + normal_window.requestActivate(); + QTRY_COMPARE(QGuiApplication::focusWindow(), &normal_window); + +} + #include <tst_qwindow.moc> QTEST_MAIN(tst_QWindow) diff --git a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp index 56d6711dc6..d0482d77e2 100644 --- a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp +++ b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp @@ -309,9 +309,6 @@ void tst_QTextLayout::simpleBoundingRect() void tst_QTextLayout::threeLineBoundingRect() { -#if defined(Q_OS_MAC) - QSKIP("QTestFontEngine on the mac does not support logclusters at the moment"); -#endif /* stricter check. break text into three lines */ QString firstWord("hello"); @@ -430,9 +427,6 @@ void tst_QTextLayout::forcedBreaks() void tst_QTextLayout::breakAny() { -#if defined(Q_OS_MAC) - QSKIP("QTestFontEngine on the mac does not support logclusters at the moment"); -#endif QString text = "ABCD"; QTextLayout layout(text, testFont); @@ -473,9 +467,6 @@ void tst_QTextLayout::breakAny() void tst_QTextLayout::noWrap() { -#if defined(Q_OS_MAC) - QSKIP("QTestFontEngine on the mac does not support logclusters at the moment"); -#endif QString text = "AB CD"; QTextLayout layout(text, testFont); @@ -1048,9 +1039,6 @@ void tst_QTextLayout::charWordStopOnLineSeparator() void tst_QTextLayout::xToCursorAtEndOfLine() { -#if defined(Q_OS_MAC) - QSKIP("QTestFontEngine on the mac does not support logclusters at the moment"); -#endif QString text = "FirstLine SecondLine"; text.replace('\n', QChar::LineSeparator); @@ -1112,9 +1100,6 @@ void tst_QTextLayout::graphemeBoundaryForSurrogatePairs() void tst_QTextLayout::tabStops() { -#if defined(Q_OS_MAC) - QSKIP("QTestFontEngine on the mac does not support logclusters at the moment"); -#endif QString txt("Hello there\tworld"); QTextLayout layout(txt, testFont); layout.beginLayout(); @@ -1931,13 +1916,16 @@ void tst_QTextLayout::textWithSurrogates_qtbug15679() void tst_QTextLayout::textWidthWithStackedTextEngine() { QString text = QString::fromUtf8("คลิก ถัดไป เพื่อดำเนินการต่อ"); + QTextLayout layout(text); layout.setCacheEnabled(true); layout.beginLayout(); QTextLine line = layout.createLine(); layout.endLayout(); - QFontMetricsF fm(layout.font()); - QCOMPARE(line.naturalTextWidth(), fm.width(text)); + + QStackTextEngine layout2(text, layout.font()); + + QVERIFY(layout2.width(0, text.size()).toReal() >= line.naturalTextWidth()); } void tst_QTextLayout::textWidthWithLineSeparator() @@ -1958,27 +1946,24 @@ void tst_QTextLayout::textWidthWithLineSeparator() void tst_QTextLayout::cursorInLigatureWithMultipleLines() { -#if !defined(Q_OS_MAC) - QSKIP("This test can only be run on Mac"); -#endif QTextLayout layout("first line finish", QFont("Times", 20)); layout.setCacheEnabled(true); layout.beginLayout(); QTextLine line = layout.createLine(); - line.setLineWidth(70); - line = layout.createLine(); + line.setNumColumns(10); + QTextLine line2 = layout.createLine(); layout.endLayout(); - // The second line will be "finish", with "fi" as a ligature - QEXPECT_FAIL("", "QTBUG-26403", Abort); - QVERIFY(line.cursorToX(0) != line.cursorToX(1)); + // The second line will be "finish" + QCOMPARE(layout.text().mid(line2.textStart(), line2.textLength()), QString::fromLatin1("finish")); + + QVERIFY(line.cursorToX(1) != line.cursorToX(0)); + QCOMPARE(line2.cursorToX(line2.textStart()), line.cursorToX(0)); + QCOMPARE(line2.cursorToX(line2.textStart() + 1), line.cursorToX(1)); } void tst_QTextLayout::xToCursorForLigatures() { -#if !defined(Q_OS_MAC) - QSKIP("This test can only be run on Mac"); -#endif QTextLayout layout("fi", QFont("Times", 20)); layout.setCacheEnabled(true); layout.beginLayout(); @@ -2001,9 +1986,6 @@ void tst_QTextLayout::xToCursorForLigatures() void tst_QTextLayout::cursorInNonStopChars() { -#if defined(Q_OS_MAC) - QSKIP("This test can not be run on Mac"); -#endif QTextLayout layout(QString::fromUtf8("\xE0\xA4\xA4\xE0\xA5\x8D\xE0\xA4\xA8")); layout.setCacheEnabled(true); layout.beginLayout(); diff --git a/tests/auto/gui/text/qtextscriptengine/tst_qtextscriptengine.cpp b/tests/auto/gui/text/qtextscriptengine/tst_qtextscriptengine.cpp index c4db669695..74eb58670b 100644 --- a/tests/auto/gui/text/qtextscriptengine/tst_qtextscriptengine.cpp +++ b/tests/auto/gui/text/qtextscriptengine/tst_qtextscriptengine.cpp @@ -1105,6 +1105,9 @@ void tst_QTextScriptEngine::mirroredChars() void tst_QTextScriptEngine::controlInSyllable_qtbug14204() { +#ifdef Q_OS_MAC + QSKIP("Result differs for HarfBuzz-NG, skip test."); +#endif QFontDatabase db; if (!db.families().contains(QStringLiteral("Aparajita"))) QSKIP("couldn't find 'Aparajita' font"); @@ -1143,6 +1146,10 @@ void tst_QTextScriptEngine::combiningMarks_qtbug15675_data() QTest::addColumn<QFont>("font"); QTest::addColumn<QString>("string"); +#ifdef Q_OS_MAC + QSKIP("Result differs for HarfBuzz-NG, skip test."); +#endif + bool hasTests = false; QStringList families; @@ -1251,36 +1258,37 @@ void tst_QTextScriptEngine::thaiWithZWJ() QTextLayout layout(s, font); QTextEngine *e = layout.engine(); e->itemize(); - QCOMPARE(e->layoutData->items.size(), 11); + QCOMPARE(e->layoutData->items.size(), 3); for (int item = 0; item < e->layoutData->items.size(); ++item) e->shape(item); - QCOMPARE(e->layoutData->items[0].num_glyphs, ushort(7)); // Thai: The ZWJ and ZWNJ characters are inherited, so should be part of the thai script - QCOMPARE(e->layoutData->items[1].num_glyphs, ushort(1)); // Common: The smart quotes cannot be handled by thai, so should be a separate item - QCOMPARE(e->layoutData->items[2].num_glyphs, ushort(1)); // Thai: Thai character - QCOMPARE(e->layoutData->items[3].num_glyphs, ushort(1)); // Common: Ellipsis - QCOMPARE(e->layoutData->items[4].num_glyphs, ushort(1)); // Thai: Thai character - QCOMPARE(e->layoutData->items[5].num_glyphs, ushort(1)); // Common: Smart quote - QCOMPARE(e->layoutData->items[6].num_glyphs, ushort(1)); // Thai: Thai character - QCOMPARE(e->layoutData->items[7].num_glyphs, ushort(1)); // Common: \xA0 = non-breaking space. Could be useful to have in thai, but not currently implemented - QCOMPARE(e->layoutData->items[8].num_glyphs, ushort(1)); // Thai: Thai character - QCOMPARE(e->layoutData->items[9].num_glyphs, ushort(1)); // Japanese: Kanji for tree - QCOMPARE(e->layoutData->items[10].num_glyphs, ushort(2)); // Thai: Thai character followed by superscript "a" which is of inherited type + QCOMPARE(e->layoutData->items[0].num_glyphs, ushort(15)); // Thai: The ZWJ and ZWNJ characters are inherited, so should be part of the thai script + QCOMPARE(e->layoutData->items[1].num_glyphs, ushort(1)); // Han: Kanji for tree + QCOMPARE(e->layoutData->items[2].num_glyphs, ushort(2)); // Thai: Thai character followed by superscript "a" which is of inherited type //A quick sanity check - check all the characters are individual clusters unsigned short *logClusters = e->layoutData->logClustersPtr; - for (int i = 0; i < 7; i++) + for (int i = 0; i <= 14; i++) QCOMPARE(logClusters[i], ushort(i)); - for (int i = 0; i < 10; i++) - QCOMPARE(logClusters[i+7], ushort(0)); + QCOMPARE(logClusters[15], ushort(0)); + QCOMPARE(logClusters[16], ushort(0)); +#ifndef Q_OS_MAC + // ### Result differs for HarfBuzz-NG QCOMPARE(logClusters[17], ushort(1)); +#endif // A thai implementation could either remove the ZWJ and ZWNJ characters, or hide them. // The current implementation hides them, so we test for that. // The only characters that we should be hiding are the ZWJ and ZWNJ characters in position 1 and 3. const QGlyphLayout glyphLayout = e->layoutData->glyphLayout; for (int i = 0; i < 18; i++) { +#ifdef Q_OS_MAC + // ### Result differs for HarfBuzz-NG + if (i == 17) + QCOMPARE(glyphLayout.advances[i].toInt(), 0); + else +#endif if (i == 1 || i == 3) QCOMPARE(glyphLayout.advances[i].toInt(), 0); else diff --git a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp index e589d520cb..122ac63034 100644 --- a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp +++ b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp @@ -331,8 +331,8 @@ void tst_QTcpSocket::initTestCase_data() qDebug() << QtNetworkSettings::serverName(); QTest::newRow("WithoutProxy") << false << 0 << false; - QTest::newRow("WithSocks5Proxy") << true << int(Socks5Proxy) << false; - QTest::newRow("WithSocks5ProxyAuth") << true << int(Socks5Proxy | AuthBasic) << false; + //QTest::newRow("WithSocks5Proxy") << true << int(Socks5Proxy) << false; ### temporarily disabled, QTBUG-38385 + //QTest::newRow("WithSocks5ProxyAuth") << true << int(Socks5Proxy | AuthBasic) << false; ### temporarily disabled, QTBUG-38385 QTest::newRow("WithHttpProxy") << true << int(HttpProxy) << false; QTest::newRow("WithHttpProxyBasicAuth") << true << int(HttpProxy | AuthBasic) << false; @@ -340,8 +340,8 @@ void tst_QTcpSocket::initTestCase_data() #ifndef QT_NO_SSL QTest::newRow("WithoutProxy SSL") << false << 0 << true; - QTest::newRow("WithSocks5Proxy SSL") << true << int(Socks5Proxy) << true; - QTest::newRow("WithSocks5AuthProxy SSL") << true << int(Socks5Proxy | AuthBasic) << true; + //QTest::newRow("WithSocks5Proxy SSL") << true << int(Socks5Proxy) << true; ### temporarily disabled, QTBUG-38385 + //QTest::newRow("WithSocks5AuthProxy SSL") << true << int(Socks5Proxy | AuthBasic) << true; ### temporarily disabled, QTBUG-38385 QTest::newRow("WithHttpProxy SSL") << true << int(HttpProxy) << true; QTest::newRow("WithHttpProxyBasicAuth SSL") << true << int(HttpProxy | AuthBasic) << true; diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp index baaf21e6bb..30a9e19138 100644 --- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp @@ -273,10 +273,12 @@ void tst_QSslSocket::initTestCase_data() void tst_QSslSocket::initTestCase() { +#ifndef QT_NO_SSL qDebug("Using SSL library %s (%ld)", qPrintable(QSslSocket::sslLibraryVersionString()), QSslSocket::sslLibraryVersionNumber()); QVERIFY(QtNetworkSettings::verifyTestNetworkSettings()); +#endif } void tst_QSslSocket::init() diff --git a/tests/auto/opengl/qglbuffer/tst_qglbuffer.cpp b/tests/auto/opengl/qglbuffer/tst_qglbuffer.cpp index 915f503b3f..a8a9deb25f 100644 --- a/tests/auto/opengl/qglbuffer/tst_qglbuffer.cpp +++ b/tests/auto/opengl/qglbuffer/tst_qglbuffer.cpp @@ -207,6 +207,10 @@ void tst_QGLBuffer::bufferSharing() QSKIP("Unreproducible timeout on Windows (MSVC/MinGW) CI bots"); #endif +#if defined(Q_OS_QNX) + QSKIP("Crashes on QNX when destroying the second QGLWidget (see QTBUG-38275)"); +#endif + QGLWidget *w1 = new QGLWidget(); w1->makeCurrent(); diff --git a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp index d360a646f1..de8528216d 100644 --- a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp +++ b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp @@ -857,36 +857,38 @@ void tst_QFiledialog::selectFile() { QFETCH(QString, file); QFETCH(int, count); - QNonNativeFileDialog fd; - QFileSystemModel *model = fd.findChild<QFileSystemModel*>("qt_filesystem_model"); + QScopedPointer<QNonNativeFileDialog> fd(new QNonNativeFileDialog); + QFileSystemModel *model = fd->findChild<QFileSystemModel*>("qt_filesystem_model"); QVERIFY(model); - fd.setDirectory(QDir::currentPath()); + fd->setDirectory(QDir::currentPath()); // default value - QCOMPARE(fd.selectedFiles().count(), 1); + QCOMPARE(fd->selectedFiles().count(), 1); - QTemporaryFile tempFile(QDir::tempPath() + "/aXXXXXX"); - bool inTemp = (file == "temp"); - if (inTemp) { - tempFile.open(); - file = tempFile.fileName(); + QScopedPointer<QTemporaryFile> tempFile; + if (file == QLatin1String("temp")) { + tempFile.reset(new QTemporaryFile(QDir::tempPath() + QStringLiteral("/aXXXXXX"))); + QVERIFY(tempFile->open()); + file = tempFile->fileName(); } - fd.selectFile(file); - QCOMPARE(fd.selectedFiles().count(), count); - if (inTemp) { - QCOMPARE(model->index(fd.directory().path()), model->index(QDir::tempPath())); + fd->selectFile(file); + QCOMPARE(fd->selectedFiles().count(), count); + if (tempFile.isNull()) { + QCOMPARE(model->index(fd->directory().path()), model->index(QDir::currentPath())); } else { - QCOMPARE(model->index(fd.directory().path()), model->index(QDir::currentPath())); + QCOMPARE(model->index(fd->directory().path()), model->index(QDir::tempPath())); } + fd.reset(); // Ensure the file dialog let's go of the temporary file for "temp". } void tst_QFiledialog::selectFiles() { - QNonNativeFileDialog fd; - fd.setViewMode(QFileDialog::List); QTemporaryDir tempDir; QVERIFY(tempDir.isValid()); const QString tempPath = tempDir.path(); + { + QNonNativeFileDialog fd; + fd.setViewMode(QFileDialog::List); fd.setDirectory(tempPath); QSignalSpy spyCurrentChanged(&fd, SIGNAL(currentChanged(QString))); QSignalSpy spyDirectoryEntered(&fd, SIGNAL(directoryEntered(QString))); @@ -931,17 +933,20 @@ void tst_QFiledialog::selectFiles() QCOMPARE(spyFilesSelected.count(), 0); QCOMPARE(spyFilterSelected.count(), 0); - //If the selection is invalid then we fill the line edit but without the / - QNonNativeFileDialog * dialog = new QNonNativeFileDialog( 0, "Save" ); - dialog->setFileMode( QFileDialog::AnyFile ); - dialog->setAcceptMode( QFileDialog::AcceptSave ); - dialog->selectFile(tempPath + QStringLiteral("/blah")); - dialog->show(); - QVERIFY(QTest::qWaitForWindowExposed(dialog)); - QLineEdit *lineEdit = dialog->findChild<QLineEdit*>("fileNameEdit"); - QVERIFY(lineEdit); - QCOMPARE(lineEdit->text(),QLatin1String("blah")); - delete dialog; + } + + { + //If the selection is invalid then we fill the line edit but without the / + QNonNativeFileDialog dialog( 0, "Save" ); + dialog.setFileMode( QFileDialog::AnyFile ); + dialog.setAcceptMode( QFileDialog::AcceptSave ); + dialog.selectFile(tempPath + QStringLiteral("/blah")); + dialog.show(); + QVERIFY(QTest::qWaitForWindowExposed(&dialog)); + QLineEdit *lineEdit = dialog.findChild<QLineEdit*>("fileNameEdit"); + QVERIFY(lineEdit); + QCOMPARE(lineEdit->text(),QLatin1String("blah")); + } } void tst_QFiledialog::viewMode() diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp index 9e0446388e..3925090465 100644 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp +++ b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.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. @@ -476,13 +476,19 @@ void tst_QFileSystemModel::rowCount() void tst_QFileSystemModel::rowsInserted_data() { QTest::addColumn<int>("count"); - QTest::addColumn<int>("assending"); + QTest::addColumn<int>("ascending"); for (int i = 0; i < 4; ++i) { QTest::newRow(QString("Qt::AscendingOrder %1").arg(i).toLocal8Bit().constData()) << i << (int)Qt::AscendingOrder; QTest::newRow(QString("Qt::DescendingOrder %1").arg(i).toLocal8Bit().constData()) << i << (int)Qt::DescendingOrder; } } +static inline QString lastEntry(const QModelIndex &root) +{ + const QAbstractItemModel *model = root.model(); + return model->index(model->rowCount(root) - 1, 0, root).data().toString(); +} + void tst_QFileSystemModel::rowsInserted() { #if defined(Q_OS_WINCE) @@ -492,9 +498,9 @@ void tst_QFileSystemModel::rowsInserted() rowCount(); QModelIndex root = model->index(model->rootPath()); - QFETCH(int, assending); + QFETCH(int, ascending); QFETCH(int, count); - model->sort(0, (Qt::SortOrder)assending); + model->sort(0, (Qt::SortOrder)ascending); QSignalSpy spy0(model, SIGNAL(rowsInserted(QModelIndex,int,int))); QSignalSpy spy1(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int))); @@ -505,7 +511,6 @@ void tst_QFileSystemModel::rowsInserted() QVERIFY(createFiles(tmp, files, 5)); TRY_WAIT(model->rowCount(root) == oldCount + count); QTRY_COMPARE(model->rowCount(root), oldCount + count); - QTest::qWait(100); // Let the sort settle. int totalRowsInserted = 0; for (int i = 0; i < spy0.count(); ++i) { int start = spy0[i].value(1).toInt(); @@ -513,12 +518,9 @@ void tst_QFileSystemModel::rowsInserted() totalRowsInserted += end - start + 1; } QCOMPARE(totalRowsInserted, count); - if (assending == (Qt::SortOrder)Qt::AscendingOrder) { - QString letter = model->index(model->rowCount(root) - 1, 0, root).data().toString(); - QCOMPARE(letter, QString("j")); - } else { - QCOMPARE(model->index(model->rowCount(root) - 1, 0, root).data().toString(), QString("b")); - } + const QString expected = ascending == Qt::AscendingOrder ? QStringLiteral("j") : QStringLiteral("b"); + QTRY_COMPARE(lastEntry(root), expected); + if (spy0.count() > 0) { if (count == 0) QCOMPARE(spy0.count(), 0); @@ -548,8 +550,8 @@ void tst_QFileSystemModel::rowsRemoved() QModelIndex root = model->index(model->rootPath()); QFETCH(int, count); - QFETCH(int, assending); - model->sort(0, (Qt::SortOrder)assending); + QFETCH(int, ascending); + model->sort(0, (Qt::SortOrder)ascending); QTest::qWait(WAITTIME); QSignalSpy spy0(model, SIGNAL(rowsRemoved(QModelIndex,int,int))); diff --git a/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp b/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp index 4c07b48c00..a932a2e859 100644 --- a/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp +++ b/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp @@ -2605,6 +2605,9 @@ void tst_QWizard::task161658_alignments() void tst_QWizard::task177022_setFixedSize() { +#ifdef Q_OS_BLACKBERRY + QSKIP("Window is forced fullscreen"); +#endif int width = 300; int height = 200; QWizard wiz; @@ -2622,7 +2625,7 @@ void tst_QWizard::task177022_setFixedSize() QCOMPARE(wiz.maximumWidth(), width); QCOMPARE(wiz.maximumHeight(), height); - wiz.show(); + wiz.showNormal(); QVERIFY(QTest::qWaitForWindowExposed(&wiz)); QCOMPARE(wiz.size(), QSize(width, height)); diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp index 5b178903cf..8f57eca0a7 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp @@ -2502,9 +2502,6 @@ void tst_QGraphicsProxyWidget::popup_basic() void tst_QGraphicsProxyWidget::popup_subwidget() { -#ifdef Q_OS_WIN - QSKIP("This test crashes on Windows, QTBUG-33213"); -#endif QGroupBox *groupBox = new QGroupBox; groupBox->setTitle("GroupBox"); groupBox->setCheckable(true); @@ -3183,10 +3180,6 @@ void tst_QGraphicsProxyWidget::actionsContextMenu() void tst_QGraphicsProxyWidget::deleteProxyForChildWidget() { -#if defined(Q_OS_WIN) - QSKIP("This test is crashing on windows, it needs to be fixed. QTBUG-29684"); -#endif - QDialog dialog; dialog.resize(320, 120); dialog.move(80, 40); diff --git a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp index 0579914940..77690cc27a 100644 --- a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp +++ b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp @@ -2488,7 +2488,7 @@ void tst_QTreeView::extendedSelection_data() QTest::addColumn<int>("selectedCount"); QTest::newRow("select") << QPoint(10, 10) << 2; - QTest::newRow("unselect") << QPoint(10, 150) << 0; + QTest::newRow("unselect") << QPoint(10, 300) << 0; } void tst_QTreeView::extendedSelection() @@ -2499,7 +2499,7 @@ void tst_QTreeView::extendedSelection() QStandardItemModel model(5, 2); QWidget topLevel; QTreeView view(&topLevel); - view.resize(qMax(mousePressPos.x() * 2, 200), qMax(mousePressPos.y() * 2, 200)); + view.resize(qMax(mousePressPos.x() * 2, 300), qMax(mousePressPos.y() * 2, 350)); view.setModel(&model); view.setSelectionMode(QAbstractItemView::ExtendedSelection); topLevel.show(); diff --git a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp index 509ccc37b6..abc0129f8b 100644 --- a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp +++ b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp @@ -2064,7 +2064,7 @@ void tst_QComboBox::itemListPosition() topLevel.move(screen.width() - topLevel.sizeHint().width() - 10, 0); //puts the combo to the top-right corner - topLevel.show(); + topLevel.showNormal(); //wait because the window manager can move the window if there is a right panel QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); @@ -2232,7 +2232,7 @@ void tst_QComboBox::task190205_setModelAdjustToContents() box.move(100, 100); box.setSizeAdjustPolicy(QComboBox::AdjustToContents); box.addItems(initialContent); - box.show(); + box.showNormal(); //wait needed in order to get the combo initial size QTRY_VERIFY(box.isVisible()); @@ -2244,7 +2244,7 @@ void tst_QComboBox::task190205_setModelAdjustToContents() correctBox.move(400, 100); correctBox.addItems(finalContent); - correctBox.show(); + correctBox.showNormal(); QVERIFY(QTest::qWaitForWindowExposed(&box)); QVERIFY(QTest::qWaitForWindowExposed(&correctBox)); @@ -2266,7 +2266,7 @@ void tst_QComboBox::task248169_popupWithMinimalSize() comboBox.setGeometry(desktopSize.width() - (desktopSize.width() / 4), (desktopSize.width() / 4), (desktopSize.width() / 2), (desktopSize.width() / 4)); - comboBox.show(); + comboBox.showNormal(); QVERIFY(QTest::qWaitForWindowExposed(&comboBox)); QTRY_VERIFY(comboBox.isVisible()); comboBox.showPopup(); @@ -2274,7 +2274,7 @@ void tst_QComboBox::task248169_popupWithMinimalSize() QTest::qWaitForWindowExposed(comboBox.view()); QTRY_VERIFY(comboBox.view()->isVisible()); -#ifdef QT_BUILD_INTERNAL +#if defined QT_BUILD_INTERNAL && !defined Q_OS_BLACKBERRY QFrame *container = comboBox.findChild<QComboBoxPrivateContainer *>(); QVERIFY(container); QTRY_VERIFY(desktop.screenGeometry(container).contains(container->geometry())); @@ -2609,7 +2609,7 @@ void tst_QComboBox::keyBoardNavigationWithMouse() for (int i = 0; i < 80; i++) combo.addItem( QString::number(i)); - combo.show(); + combo.showNormal(); centerCursor(&combo); // QTBUG-33973, cursor needs to be within view from start on Mac. QApplication::setActiveWindow(&combo); QVERIFY(QTest::qWaitForWindowActive(&combo)); @@ -2629,7 +2629,7 @@ void tst_QComboBox::keyBoardNavigationWithMouse() QCOMPARE(combo.currentText(), QLatin1String("0")); // When calling cursor function, Windows CE responds with: This function is not supported on this system. -#ifndef Q_OS_WINCE +#if !defined Q_OS_WINCE && !defined Q_OS_QNX // Force cursor movement to prevent QCursor::setPos() from returning prematurely on QPA: centerCursor(combo.view()); QTest::qWait(200); diff --git a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp index 6551a88232..095fa3347d 100644 --- a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp +++ b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp @@ -801,13 +801,16 @@ void tst_QDockWidget::task237438_setFloatingCrash() void tst_QDockWidget::task248604_infiniteResize() { +#if defined Q_OS_BLACKBERRY + QSKIP("Top level window is stretched to fullscreen"); +#endif QDockWidget d; QTabWidget *t = new QTabWidget; t->addTab(new QWidget, "Foo"); d.setWidget(t); d.setContentsMargins(2, 2, 2, 2); d.setMinimumSize(320, 240); - d.show(); + d.showNormal(); QTest::qWait(400); QCOMPARE(d.size(), QSize(320, 240)); } diff --git a/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp b/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp index 6784ee477b..6b763f5a4c 100644 --- a/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp +++ b/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp @@ -825,6 +825,8 @@ void tst_QDoubleSpinBox::editingFinished() QCOMPARE(editingFinishedSpy1.count(), 4); QCOMPARE(editingFinishedSpy2.count(), 4); + testFocusWidget->show(); // On BlackBerry this is our root window we need to show it again + // otherwise subsequent tests will fail } void tst_QDoubleSpinBox::removeAll() diff --git a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp index ba9652a170..27a2a456e7 100644 --- a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp +++ b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp @@ -1007,7 +1007,7 @@ void tst_QMdiArea::activeSubWindow() qApp->setActiveWindow(&mainWindow); QCOMPARE(mdiArea->activeSubWindow(), subWindow); -#if !defined(Q_OS_MAC) && !defined(Q_OS_WIN) +#if !defined(Q_OS_MAC) && !defined(Q_OS_WIN) && !defined(Q_OS_QNX) qApp->setActiveWindow(0); QVERIFY(!mdiArea->activeSubWindow()); #endif @@ -1088,7 +1088,7 @@ void tst_QMdiArea::currentSubWindow() QVERIFY(mdiArea.activeSubWindow()); QVERIFY(mdiArea.currentSubWindow()); -#if !defined(Q_OS_MAC) && !defined(Q_OS_WIN) +#if !defined(Q_OS_MAC) && !defined(Q_OS_WIN) && !defined(Q_OS_QNX) qApp->setActiveWindow(0); QVERIFY(!mdiArea.activeSubWindow()); QVERIFY(mdiArea.currentSubWindow()); @@ -1701,7 +1701,7 @@ void tst_QMdiArea::tileSubWindows() qApp->processEvents(); QTRY_COMPARE(workspace.size(), QSize(350, 150)); - const QSize minSize(300, 100); + const QSize minSize(600, 130); foreach (QMdiSubWindow *subWindow, workspace.subWindowList()) subWindow->setMinimumSize(minSize); @@ -1908,6 +1908,9 @@ void tst_QMdiArea::dontMaximizeSubWindowOnActivation() for (int i = 0; i < 5; ++i) { QMdiSubWindow *window = mdiArea.addSubWindow(new QWidget); window->show(); +#if defined Q_OS_QNX + QEXPECT_FAIL("", "QTBUG-38231", Abort); +#endif QVERIFY(window->isMaximized()); qApp->processEvents(); } diff --git a/tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp b/tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp index 345b8d82ad..06dd623368 100644 --- a/tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp +++ b/tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp @@ -679,7 +679,8 @@ void tst_QTabBar::tabBarClicked() QCOMPARE(doubleClickSpy.count(), 0); QTest::mouseDClick(&tabBar, button, 0, tabPos); - QCOMPARE(clickSpy.count(), 0); + QCOMPARE(clickSpy.count(), 1); + QCOMPARE(clickSpy.takeFirst().takeFirst().toInt(), 0); QCOMPARE(doubleClickSpy.count(), 1); QCOMPARE(doubleClickSpy.takeFirst().takeFirst().toInt(), 0); @@ -691,7 +692,8 @@ void tst_QTabBar::tabBarClicked() QCOMPARE(doubleClickSpy.count(), 0); QTest::mouseDClick(&tabBar, button, 0, barPos); - QCOMPARE(clickSpy.count(), 0); + QCOMPARE(clickSpy.count(), 1); + QCOMPARE(clickSpy.takeFirst().takeFirst().toInt(), -1); QCOMPARE(doubleClickSpy.count(), 1); QCOMPARE(doubleClickSpy.takeFirst().takeFirst().toInt(), -1); diff --git a/tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp b/tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp index df11ea9b14..90af617e87 100644 --- a/tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp +++ b/tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp @@ -690,7 +690,8 @@ void tst_QTabWidget::tabBarClicked() QCOMPARE(doubleClickSpy.count(), 0); QTest::mouseDClick(&tabBar, button, 0, tabPos); - QCOMPARE(clickSpy.count(), 0); + QCOMPARE(clickSpy.count(), 1); + QCOMPARE(clickSpy.takeFirst().takeFirst().toInt(), 0); QCOMPARE(doubleClickSpy.count(), 1); QCOMPARE(doubleClickSpy.takeFirst().takeFirst().toInt(), 0); @@ -702,7 +703,8 @@ void tst_QTabWidget::tabBarClicked() QCOMPARE(doubleClickSpy.count(), 0); QTest::mouseDClick(&tabBar, button, 0, barPos); - QCOMPARE(clickSpy.count(), 0); + QCOMPARE(clickSpy.count(), 1); + QCOMPARE(clickSpy.takeFirst().takeFirst().toInt(), -1); QCOMPARE(doubleClickSpy.count(), 1); QCOMPARE(doubleClickSpy.takeFirst().takeFirst().toInt(), -1); diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index cff3f1bf0c..06f78b1116 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -3398,10 +3398,8 @@ void Configure::generateQConfigPri() if (!dictionary["QT_NAMESPACE"].isEmpty()) configStream << "#namespaces" << endl << "QT_NAMESPACE = " << dictionary["QT_NAMESPACE"] << endl; - if (dictionary[ "SHARED" ] == "no") { - configStream << "QT_DEFAULT_QPA_PLUGIN = q" << qpaPlatformName() << endl - << "QT_DEFAULT_PRINTSUPPORTPLUGIN = " << qpaPrintSupportPluginName() << endl; - } + if (dictionary[ "SHARED" ] == "no") + configStream << "QT_DEFAULT_QPA_PLUGIN = q" << qpaPlatformName() << endl; if (!configStream.flush()) dictionary[ "DONE" ] = "error"; @@ -3574,8 +3572,7 @@ void Configure::generateConfigfiles() for (int i = 0; i < qconfigList.count(); ++i) tmpStream << addDefine(qconfigList.at(i)); - tmpStream << "#define QT_QPA_DEFAULT_PLATFORM_NAME \"" << qpaPlatformName() << "\"" << endl - << "#define QT_QPA_DEFAULT_PRINTSUPPORTPLUGIN_NAME \"" << qpaPrintSupportPluginName() << "\"" << endl; + tmpStream<<"#define QT_QPA_DEFAULT_PLATFORM_NAME \"" << qpaPlatformName() << "\""<<endl; if (!tmpStream.flush()) dictionary[ "DONE" ] = "error"; @@ -4475,11 +4472,6 @@ QString Configure::qpaPlatformName() const } } -QString Configure::qpaPrintSupportPluginName() const -{ - return platform() == WINDOWS ? QStringLiteral("windowsprintersupport") : QString(); -} - int Configure::platform() const { const QString qMakeSpec = dictionary.value("QMAKESPEC"); diff --git a/tools/configure/configureapp.h b/tools/configure/configureapp.h index e8de10dcf7..98e4912eaa 100644 --- a/tools/configure/configureapp.h +++ b/tools/configure/configureapp.h @@ -100,7 +100,6 @@ public: int platform() const; QString platformName() const; QString qpaPlatformName() const; - QString qpaPrintSupportPluginName() const; private: bool checkAngleAvailability(QString *errorMessage = 0) const; |