diff options
59 files changed, 876 insertions, 548 deletions
diff --git a/config.tests/unix/compile.test b/config.tests/unix/compile.test index 22064b85e9..f99237cb50 100755 --- a/config.tests/unix/compile.test +++ b/config.tests/unix/compile.test @@ -69,15 +69,11 @@ rm -f "$EXE" "${EXE}.exe" set -- "$OUTDIR/bin/qmake" -nocache -spec "$QMKSPEC" "CONFIG+=$QMAKE_CONFIG" "CONFIG+=android_app" "CONFIG-=debug_and_release app_bundle lib_bundle" "LIBS*=$LFLAGS" "LIBS+=$MAC_ARCH_LFLAGS" "INCLUDEPATH*=$INCLUDEPATH" "QMAKE_CXXFLAGS*=$CXXFLAGS" "QMAKE_CXXFLAGS+=$MAC_ARCH_CXXFLAGS" "QT_BUILD_TREE=$OUTDIR" "$SRCDIR/$TEST/$EXE.pro" -o "$OUTDIR/$TEST/Makefile" if [ "$VERBOSE" = "yes" ]; then - OUTDIR=$OUTDIR "$@" - $MAKE + OUTDIR=$OUTDIR "$@" && $MAKE && SUCCESS=yes else - OUTDIR=$OUTDIR "$@" >/dev/null 2>&1 - $MAKE >/dev/null 2>&1 + OUTDIR=$OUTDIR "$@" >/dev/null 2>&1 && $MAKE >/dev/null 2>&1 && SUCCESS=yes fi -( [ -f "$EXE" ] || [ -f "${EXE}.exe" ] ) && SUCCESS=yes - # done if [ "$SUCCESS" != "yes" ]; then [ "$VERBOSE" = "yes" ] && echo "$DESCRIPTION disabled." diff --git a/config.tests/unix/objcopy.test b/config.tests/unix/objcopy.test deleted file mode 100755 index 9eb6e22ab0..0000000000 --- a/config.tests/unix/objcopy.test +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/sh - -TEST_PATH=`dirname "$0"` -SEP_DEBUG_SUPPORT=no -COMPILER=$1 -QMAKE_OBJCOPY=$2 -VERBOSE=$3 - -if [ -n "$QMAKE_OBJCOPY" ]; then - echo "int main() { return 0; }" > objcopy_test.cpp - if $TEST_PATH/which.test "$QMAKE_OBJCOPY" >/dev/null 2>&1 && $COMPILER $SYSROOT_FLAG -g -o objcopy_test objcopy_test.cpp >/dev/null 2>&1; then - "$QMAKE_OBJCOPY" --only-keep-debug objcopy_test objcopy_test.debug >/dev/null 2>&1 \ - && "$QMAKE_OBJCOPY" --strip-debug objcopy_test >/dev/null 2>&1 \ - && "$QMAKE_OBJCOPY" --add-gnu-debuglink=objcopy_test.debug objcopy_test >/dev/null 2>&1 \ - && SEP_DEBUG_SUPPORT=yes - fi - rm -f objcopy_test objcopy_test.debug objcopy_test.cpp -else - [ "$VERBOSE" = "yes" ] && echo "Separate debug info check skipped, QMAKE_OBJCOPY is unset."; -fi - -# done -if [ "$SEP_DEBUG_SUPPORT" != "yes" ]; then - [ "$VERBOSE" = "yes" ] && echo "Separate debug info support disabled." - exit 0 -else - [ "$VERBOSE" = "yes" ] && echo "Separate debug info support enabled." - exit 1 -fi diff --git a/config.tests/unix/objcopy/objcopy.cpp b/config.tests/unix/objcopy/objcopy.cpp new file mode 100644 index 0000000000..66b261bd6d --- /dev/null +++ b/config.tests/unix/objcopy/objcopy.cpp @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2014 BlackBerry Limited. All rights reserved. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the config.tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +int main() +{ + return 0; +} diff --git a/config.tests/unix/objcopy/objcopy.pro b/config.tests/unix/objcopy/objcopy.pro new file mode 100644 index 0000000000..3c28b89ef3 --- /dev/null +++ b/config.tests/unix/objcopy/objcopy.pro @@ -0,0 +1,4 @@ +SOURCES = objcopy.cpp +CONFIG -= qt + +QMAKE_POST_LINK += $$QMAKE_OBJCOPY --only-keep-debug objcopy objcopy.debug && $$QMAKE_OBJCOPY --strip-debug objcopy && $$QMAKE_OBJCOPY --add-gnu-debuglink=objcopy.debug objcopy @@ -1803,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" @@ -2367,6 +2381,12 @@ 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. + Additional options: -make <part> ....... Add part to the list of parts to be built at make time. @@ -3176,7 +3196,7 @@ if [ "$CFG_PRECOMPILE" = "auto" ]; then fi fi -# auto-detect support for separate debug info in objcopy +# sanity-check for separate debug info if [ "$CFG_SEPARATE_DEBUG_INFO" = "yes" ]; then if [ "$CFG_SHARED" = "no" ]; then echo "ERROR: -separate-debug-info is incompatible with -static" @@ -3186,13 +3206,6 @@ if [ "$CFG_SEPARATE_DEBUG_INFO" = "yes" ]; then echo "ERROR: -separate-debug-info needs -debug, -debug-and-release, or -force-debug-info" exit 1 fi - TEST_OBJCOPY=`getXQMakeConf QMAKE_OBJCOPY` - COMPILER_WITH_FLAGS="$TEST_COMPILER $TEST_COMPILER_CXXFLAGS" - if "$unixtests/objcopy.test" "$COMPILER_WITH_FLAGS" "$TEST_OBJCOPY" "$OPT_VERBOSE"; then - echo "ERROR: -separate-debug-info was requested but this binutils does not support it." - echo "Re-run configure with -v for more information" - exit 1 - fi fi # auto-detect -fvisibility support @@ -3934,6 +3947,15 @@ fi # functionality tests #------------------------------------------------------------------------------- +# Detect objcopy support +if [ "$CFG_SEPARATE_DEBUG_INFO" = "yes" ]; then + if ! compileTest unix/objcopy "objcopy"; then + echo "ERROR: -separate-debug-info was requested but this binutils does not support it." + echo "Re-run configure with -v for more information" + exit 1 + fi +fi + # Detect C++11 support if [ "$CFG_CXX11" != "no" ]; then # Configure detects compiler features based on cross compiler, so we need 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_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/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/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/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/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/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/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/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/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/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 1b3928fdfb..f9f7d0b35d 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -1438,8 +1438,10 @@ void QSslSocketBackendPrivate::continueHandshake() if (readBufferMaxSize) plainSocket->setReadBufferSize(readBufferMaxSize); +#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT) if (q_SSL_ctrl((ssl), SSL_CTRL_GET_SESSION_REUSED, 0, NULL)) configuration.peerSessionShared = true; +#endif #ifdef QT_DECRYPT_SSL_TRAFFIC if (ssl->session && ssl->s3) { 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 93462e7ea1..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]; diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp index d8f34fc3ed..86f78a35d5 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. @@ -92,51 +92,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 +222,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 +232,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 +260,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 +281,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 +291,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])); - - sink->EndFigure(D2D1_FIGURE_END_OPEN); - } + writer.lineTo(QPointF(points[0], points[1])); - sink->Close(); - - return pathGeometry; + writer.close(); + return writer.geometry(); } class QWindowsDirect2DPaintEnginePrivate : public QPaintEngineExPrivate @@ -375,7 +393,7 @@ public: { popClip(); - ComPtr<ID2D1PathGeometry1> geometry = painterPathToPathGeometry(clipPath); + ComPtr<ID2D1PathGeometry1> geometry = painterPathToID2D1PathGeometry(clipPath, antialiasMode() == D2D1_ANTIALIAS_MODE_ALIASED); if (!geometry) return; @@ -658,7 +676,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 +808,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 +834,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; @@ -796,7 +891,7 @@ void QWindowsDirect2DPaintEngine::fill(const QVectorPath &path, const QBrush &br 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 + // We natively support only linear and radial gradients that have pad reflect due to D2D limitations QImage img(d->bitmap->size(), QImage::Format_ARGB32); img.fill(Qt::transparent); @@ -820,13 +915,25 @@ void QWindowsDirect2DPaintEngine::fill(const QVectorPath &path, const QBrush &br 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; - } + if (path.hints() & QVectorPath::RectangleShapeMask) { + const qreal * const points = path.points(); + D2D_RECT_F rect = { + points[0], // left + points[1], // top + points[2], // right, + points[5] // bottom + }; - d->dc()->FillGeometry(geometry.Get(), d->brush.brush.Get()); + 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; + } + + d->dc()->FillGeometry(geometry.Get(), d->brush.brush.Get()); + } } // For clipping we convert everything to painter paths since it allows @@ -1036,7 +1143,7 @@ void QWindowsDirect2DPaintEngine::drawStaticTextItem(QStaticTextItem *staticText Q_D(QWindowsDirect2DPaintEngine); D2D_TAG(D2DDebugDrawStaticTextItemTag); - if (qpen_style(d->pen.qpen) == Qt::NoPen) + if (qpen_style(d->pen.qpen) == Qt::NoPen && qbrush_style(d->brush.qbrush) == Qt::NoBrush) return; if (staticTextItem->numGlyphs == 0) @@ -1086,7 +1193,7 @@ void QWindowsDirect2DPaintEngine::drawTextItem(const QPointF &p, const QTextItem Q_D(QWindowsDirect2DPaintEngine); D2D_TAG(D2DDebugDrawTextItemTag); - if (qpen_style(d->pen.qpen) == Qt::NoPen) + if (qpen_style(d->pen.qpen) == Qt::NoPen && qbrush_style(d->brush.qbrush) == Qt::NoBrush) return; const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem); diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 6462cb8d3e..af7713ba6f 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -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 @@ -213,7 +213,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; } /*! @@ -1025,6 +1025,12 @@ 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; + } nextActiveWindow = platformWindow->window(); } else { // Focus out: Is the next window known and different 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/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/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index ad7e99bd49..fb9c03b66d 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -485,7 +485,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)); @@ -554,7 +554,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; @@ -671,6 +671,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(); @@ -694,6 +697,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; @@ -1514,6 +1579,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; @@ -1549,8 +1616,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)) { @@ -1868,41 +1934,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/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/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/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/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/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/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/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index fe2caa2efa..06f78b1116 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -164,6 +164,7 @@ Configure::Configure(int& argc, char** argv) dictionary[ "GUI" ] = "yes"; dictionary[ "RTTI" ] = "yes"; dictionary[ "STRIP" ] = "yes"; + dictionary[ "SEPARATE_DEBUG_INFO" ] = "no"; dictionary[ "SSE2" ] = "auto"; dictionary[ "SSE3" ] = "auto"; dictionary[ "SSSE3" ] = "auto"; @@ -445,6 +446,10 @@ void Configure::parseCmdLine() dictionary[ "BUILDALL" ] = "yes"; else if (configCmdLine.at(i) == "-force-debug-info") dictionary[ "FORCEDEBUGINFO" ] = "yes"; + else if (configCmdLine.at(i) == "-no-separate-debug-info") + dictionary[ "SEPARATE_DEBUG_INFO" ] = "no"; + else if (configCmdLine.at(i) == "-separate-debug-info") + dictionary[ "SEPARATE_DEBUG_INFO" ] = "yes"; else if (configCmdLine.at(i) == "-compile-examples") { dictionary[ "COMPILE_EXAMPLES" ] = "yes"; @@ -1765,7 +1770,8 @@ bool Configure::displayHelp() desc("BUILD", "debug", "-debug", "Compile and link Qt with debugging turned on."); desc("BUILDALL", "yes", "-debug-and-release", "Compile and link two Qt libraries, with and without debugging turned on.\n"); - desc("FORCEDEBUGINFO", "yes","-force-debug-info", "Create symbol files for release builds.\n"); + desc("FORCEDEBUGINFO", "yes","-force-debug-info", "Create symbol files for release builds."); + desc("SEPARATE_DEBUG_INFO", "yes","-separate-debug-info", "Strip debug information into a separate file.\n"); desc("BUILDDEV", "yes", "-developer-build", "Compile and link Qt with Qt developer options (including auto-tests exporting)\n"); @@ -2165,6 +2171,9 @@ bool Configure::checkAvailability(const QString &part) if (part == "STYLE_WINDOWSXP") available = (platform() == WINDOWS) && findFile("uxtheme.h"); + else if (part == "OBJCOPY") + available = tryCompileProject("unix/objcopy"); + else if (part == "ZLIB") available = findFile("zlib.h"); @@ -2489,6 +2498,21 @@ bool Configure::verifyConfiguration() dictionary["C++11"] = "auto"; } + if (dictionary["SEPARATE_DEBUG_INFO"] == "yes") { + if (dictionary[ "SHARED" ] == "no") { + cout << "ERROR: -separate-debug-info is incompatible with -static" << endl << endl; + dictionary[ "DONE" ] = "error"; + } else if (dictionary[ "BUILD" ] != "debug" + && dictionary[ "BUILDALL" ] == "no" + && dictionary[ "FORCEDEBUGINFO" ] == "no") { + cout << "ERROR: -separate-debug-info needs -debug, -debug-and-release, or -force-debug-info" << endl << endl; + dictionary[ "DONE" ] = "error"; + } else if (dictionary["SEPARATE_DEBUG_INFO"] == "yes" && !checkAvailability("OBJCOPY")) { + cout << "ERROR: -separate-debug-info was requested but this binutils does not support it." << endl; + dictionary[ "DONE" ] = "error"; + } + } + if (dictionary["SQL_SQLITE_LIB"] == "no" && dictionary["SQL_SQLITE"] != "no") { cout << "WARNING: Configure could not detect the presence of a system SQLite3 lib." << endl << "Configure will therefore continue with the SQLite3 lib bundled with Qt." << endl; @@ -2752,6 +2776,8 @@ void Configure::generateOutputVars() if (dictionary[ "BUILDALL" ] == "yes") { qtConfig += "build_all"; } + if (dictionary[ "SEPARATE_DEBUG_INFO" ] == "yes") + qtConfig += "separate_debug_info"; if (dictionary[ "FORCEDEBUGINFO" ] == "yes") qmakeConfig += "force_debug_info"; qmakeConfig += dictionary[ "BUILD" ]; |