diff --git a/.gitignore b/.gitignore index 7179340e204..1beec5c3ecb 100644 --- a/.gitignore +++ b/.gitignore @@ -53,6 +53,7 @@ wrapper.sh wrapper.bat core .qmake.cache +.qmake.stash .qmake.vars .device.vars *.prl @@ -118,6 +119,7 @@ mkspecs/default-host mkspecs/qconfig.pri mkspecs/qdevice.pri mkspecs/qfeatures.pri +mkspecs/qhost.pri moc_*.cpp qmake/qmake.exe qmake/Makefile.bak @@ -203,6 +205,7 @@ tools/qvfb/qwssignalhandler_p.h .rcc *.app config.status +config.tests/common/c++default/c++default.ii config.tests/unix/cups/cups config.tests/unix/getaddrinfo/getaddrinfo config.tests/unix/getifaddrs/getifaddrs diff --git a/LICENSE.GPLv3 b/LICENSE.GPLv3 index 4e49b122ae1..71c4ad49c37 100644 --- a/LICENSE.GPLv3 +++ b/LICENSE.GPLv3 @@ -3,7 +3,7 @@ The Qt Toolkit is Copyright (C) 2015 The Qt Company Ltd. Contact: http://www.qt.io/licensing/ - You may use, distribute and copy the Qt GUI Toolkit under the terms of + You may use, distribute and copy the Qt Toolkit under the terms of GNU Lesser General Public License version 3. That license references the General Public License version 3, that is displayed below. Other portions of the Qt Toolkit may be licensed directly under this license. diff --git a/LICENSE.LGPLv21 b/LICENSE.LGPLv21 index ca5adae7e91..15a208b486a 100644 --- a/LICENSE.LGPLv21 +++ b/LICENSE.LGPLv21 @@ -3,7 +3,7 @@ The Qt Toolkit is Copyright (C) 2016 The Qt Company Ltd. Contact: http://www.qt.io/licensing/ - You may use, distribute and copy the Qt GUI Toolkit under the terms of + You may use, distribute and copy the Qt Toolkit under the terms of GNU Lesser General Public License version 2.1, which is displayed below. ------------------------------------------------------------------------- diff --git a/LICENSE.LGPLv3 b/LICENSE.LGPLv3 index d3268e665e8..849103ad91d 100644 --- a/LICENSE.LGPLv3 +++ b/LICENSE.LGPLv3 @@ -3,7 +3,7 @@ The Qt Toolkit is Copyright (C) 2016 The Qt Company Ltd. Contact: http://www.qt.io/licensing/ - You may use, distribute and copy the Qt GUI Toolkit under the terms of + You may use, distribute and copy the Qt Toolkit under the terms of GNU Lesser General Public License version 3, which is displayed below. This license makes reference to the version 3 of the GNU General Public License, which you can find in the LICENSE.GPLv3 file. diff --git a/mkspecs/common/bsd/bsd.conf b/mkspecs/common/bsd/bsd.conf new file mode 100644 index 00000000000..390dfc58d2a --- /dev/null +++ b/mkspecs/common/bsd/bsd.conf @@ -0,0 +1,30 @@ +# +# common qmake configuration for *BSD +# + +MAKEFILE_GENERATOR = UNIX +QMAKE_PLATFORM += bsd + +include(../unix.conf) + +QMAKE_CFLAGS_THREAD = -pthread + +QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD + +QMAKE_LFLAGS_THREAD = -pthread +QMAKE_LFLAGS_GCSECTIONS = -Wl,--gc-sections + +QMAKE_LIBS = +QMAKE_LIBS_DYNLOAD = +QMAKE_LIBS_EXECINFO = -lexecinfo +QMAKE_LIBS_X11 = -lXext -lX11 -lm +QMAKE_LIBS_OPENGL = -lGL +QMAKE_LIBS_THREAD = + +QMAKE_AR = ar cqs +QMAKE_OBJCOPY = objcopy +QMAKE_NM = nm -P +QMAKE_RANLIB = + +QMAKE_STRIP = strip +QMAKE_STRIPFLAGS_LIB += --strip-unneeded diff --git a/mkspecs/common/bsd/qplatformdefs.h b/mkspecs/common/bsd/qplatformdefs.h new file mode 100644 index 00000000000..123155816f9 --- /dev/null +++ b/mkspecs/common/bsd/qplatformdefs.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the qmake spec of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef Q_BSD_PLATFORMDEFS_H +#define Q_BSD_PLATFORMDEFS_H + +// Get Qt defines/settings + +#include "qglobal.h" + +// Set any POSIX/XOPEN defines at the top of this file to turn on specific APIs + +#include + + +// We are hot - unistd.h should have turned on the specific APIs we requested + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef QT_NO_IPV6IFNAME +#include +#endif + +#include "../posix/qplatformdefs.h" + +#undef QT_OPEN_LARGEFILE +#define QT_OPEN_LARGEFILE 0 + +#define QT_SNPRINTF ::snprintf +#define QT_VSNPRINTF ::vsnprintf + +#endif // QPLATFORMDEFS_H diff --git a/mkspecs/common/macx.conf b/mkspecs/common/macx.conf index ad54612f22e..69d731b48ac 100644 --- a/mkspecs/common/macx.conf +++ b/mkspecs/common/macx.conf @@ -2,7 +2,7 @@ # qmake configuration for common OS X # -QMAKE_PLATFORM += osx macx +QMAKE_PLATFORM += macos osx macx QMAKE_MAC_SDK = macosx include(mac.conf) diff --git a/mkspecs/darwin-g++/qmake.conf b/mkspecs/darwin-g++/qmake.conf index 79f81a990f8..09c55456ec3 100644 --- a/mkspecs/darwin-g++/qmake.conf +++ b/mkspecs/darwin-g++/qmake.conf @@ -5,7 +5,7 @@ # MAKEFILE_GENERATOR = UNIX -QMAKE_PLATFORM = osx macx mac darwin +QMAKE_PLATFORM = macos osx macx mac darwin CONFIG += native_precompiled_headers DEFINES += __USE_WS_X11__ diff --git a/mkspecs/devices/linux-rpi3-g++/qmake.conf b/mkspecs/devices/linux-rpi3-g++/qmake.conf index 600d3e7dc1e..a6605775654 100644 --- a/mkspecs/devices/linux-rpi3-g++/qmake.conf +++ b/mkspecs/devices/linux-rpi3-g++/qmake.conf @@ -1,4 +1,4 @@ -# qmake configuration for the Raspberry Pi 3 +# qmake configuration for the Raspberry Pi 3 (32-bit) using the Broadcom graphics stack include(../common/linux_device_pre.conf) @@ -27,9 +27,8 @@ QMAKE_LIBS_OPENGL_ES2 = $${VC_LINK_LINE} -lGLESv2 # The official opt vc EGL references GLESv2 symbols: need to link it QMAKE_LIBS_EGL = $${VC_LINK_LINE} -lEGL -lGLESv2 -# We deliberately override the existing Qt CFLAGS as they might be problematic -QMAKE_CFLAGS = -march=armv8-a+crc -mtune=cortex-a53 -mfpu=crypto-neon-fp-armv8 -pipe -Os -mthumb -QMAKE_CXXFLAGS = $$QMAKE_CFLAGS -std=c++1z +QMAKE_CFLAGS = -march=armv8-a -mtune=cortex-a53 -mfpu=crypto-neon-fp-armv8 +QMAKE_CXXFLAGS = $$QMAKE_CFLAGS DISTRO_OPTS += hard-float DISTRO_OPTS += deb-multi-arch diff --git a/mkspecs/devices/linux-rpi3-vc4-g++/qmake.conf b/mkspecs/devices/linux-rpi3-vc4-g++/qmake.conf new file mode 100644 index 00000000000..75b6ad7db5a --- /dev/null +++ b/mkspecs/devices/linux-rpi3-vc4-g++/qmake.conf @@ -0,0 +1,44 @@ +# qmake configuration for the Raspberry Pi 3 (32-bit) using the +# *experimental* VC4 driver for Mesa and DRM. +# +# This should allow accelerated EGL and OpenGL with eglfs via +# KMS/DRM/GBM (instead of the Broadcom-specific backend), under X11 +# with xcb, and also enables (Qt)Wayland via the standard wayland-egl +# path. See https://dri.freedesktop.org/wiki/VC4 +# +# Note that this is not the same as the default, Broadcom proprietary +# driver. Some functionality and extensions may therefore be missing, +# in particular when it comes to accelerated multimedia (video, +# camera). +# +# At the time of writing Raspbian has to be switched explicitly to the +# experimental VC4 driver. To do this, run raspi-config and enable it +# in Advanced Options -> GL Driver. +# +# Example configure command below. We disable using the GNU gold +# linker as it apparently has issues with ARMv8. In the configure +# output check that "EGLFS GBM .......... yes" is present, otherwise +# eglfs will not be functional. +# +# ./configure -release -opengl es2 -device linux-rpi3-vc4-g++ \ +# -device-option CROSS_COMPILE=~/raspbian/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf- \ +# -sysroot ~/raspbian/sysroot \ +# -prefix /usr/local/qt5pi -extprefix ~/raspbian/qt5pi -hostprefix ~/raspbian/qt5 \ +# -v -nomake examples -nomake tests -no-use-gold-linker + +include(../common/linux_device_pre.conf) + +QMAKE_LIBS_EGL += -lEGL +QMAKE_LIBS_OPENGL_ES2 += -lGLESv2 -lEGL + +QMAKE_CFLAGS = -march=armv8-a -mtune=cortex-a53 -mfpu=crypto-neon-fp-armv8 +QMAKE_CXXFLAGS = $$QMAKE_CFLAGS + +DISTRO_OPTS += hard-float +DISTRO_OPTS += deb-multi-arch + +EGLFS_DEVICE_INTEGRATION = eglfs_kms + +include(../common/linux_arm_device_post.conf) + +load(qt_config) diff --git a/mkspecs/devices/linux-rpi3-vc4-g++/qplatformdefs.h b/mkspecs/devices/linux-rpi3-vc4-g++/qplatformdefs.h new file mode 100644 index 00000000000..6fe3b524549 --- /dev/null +++ b/mkspecs/devices/linux-rpi3-vc4-g++/qplatformdefs.h @@ -0,0 +1,34 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the qmake spec of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "../../linux-g++/qplatformdefs.h" diff --git a/mkspecs/features/spec_post.prf b/mkspecs/features/spec_post.prf index 4d398059b2e..234189fed1f 100644 --- a/mkspecs/features/spec_post.prf +++ b/mkspecs/features/spec_post.prf @@ -26,16 +26,23 @@ isEmpty(QMAKE_PLATFORM) { equals(TARGET_PLATFORM, unix): \ QMAKE_PLATFORM = unix else:equals(TARGET_PLATFORM, macx): \ - QMAKE_PLATFORM = osx macx mac darwin unix + QMAKE_PLATFORM = macos osx macx mac darwin unix else:equals(TARGET_PLATFORM, win32): \ QMAKE_PLATFORM = win32 else: \ error("Qmake spec sets an invalid TARGET_PLATFORM.") } -contains(QMAKE_PLATFORM, macx):!contains(QMAKE_PLATFORM, osx) { - warning("qmake spec specifies platform macx, but not osx.") - QMAKE_PLATFORM = osx $$QMAKE_PLATFORM +contains(QMAKE_PLATFORM, macx) { + !contains(QMAKE_PLATFORM, osx) { + warning("qmake spec specified platform macx, but not osx."); + QMAKE_PLATFORM = osx $$QMAKE_PLATFORM + } + + !contains(QMAKE_PLATFORM, macos) { + warning("qmake spec specifies platform macx, but not macos.") + QMAKE_PLATFORM = macos $$QMAKE_PLATFORM + } } CONFIG += $$QMAKE_PLATFORM diff --git a/mkspecs/freebsd-clang/qmake.conf b/mkspecs/freebsd-clang/qmake.conf index 0d6401f2f5f..10bb4a37235 100644 --- a/mkspecs/freebsd-clang/qmake.conf +++ b/mkspecs/freebsd-clang/qmake.conf @@ -3,34 +3,16 @@ # MAKEFILE_GENERATOR = UNIX -QMAKE_PLATFORM = freebsd bsd +QMAKE_PLATFORM = freebsd -include(../common/unix.conf) +include(../common/bsd/bsd.conf) -QMAKE_CFLAGS_THREAD = -pthread - -QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD - -# Addon software goes into /usr/local on the BSDs, by default we will look there +# Addon software goes into /usr/local on FreeBSD, by default we will look there QMAKE_INCDIR = /usr/local/include QMAKE_LIBDIR = /usr/local/lib QMAKE_LFLAGS_NOUNDEF = -Wl,--no-undefined -QMAKE_LFLAGS_THREAD = -pthread - -QMAKE_LIBS = -QMAKE_LIBS_DYNLOAD = -QMAKE_LIBS_EXECINFO = -lexecinfo -QMAKE_LIBS_X11 = -lXext -lX11 -lm -QMAKE_LIBS_OPENGL = -lGL -QMAKE_LIBS_THREAD = - -QMAKE_AR = ar cqs -QMAKE_OBJCOPY = objcopy -QMAKE_NM = nm -P -QMAKE_RANLIB = include(../common/gcc-base-unix.conf) include(../common/clang.conf) - load(qt_config) diff --git a/mkspecs/freebsd-clang/qplatformdefs.h b/mkspecs/freebsd-clang/qplatformdefs.h index d92eadd7e8c..0e3fd6b2b85 100644 --- a/mkspecs/freebsd-clang/qplatformdefs.h +++ b/mkspecs/freebsd-clang/qplatformdefs.h @@ -40,47 +40,6 @@ #ifndef QPLATFORMDEFS_H #define QPLATFORMDEFS_H -// Get Qt defines/settings - -#include "qglobal.h" - -// Set any POSIX/XOPEN defines at the top of this file to turn on specific APIs - -#include - - -// We are hot - unistd.h should have turned on the specific APIs we requested - - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef QT_NO_IPV6IFNAME -#include -#endif - -#include "../common/posix/qplatformdefs.h" - -#undef QT_OPEN_LARGEFILE - -#define QT_OPEN_LARGEFILE 0 - -#define QT_SNPRINTF ::snprintf -#define QT_VSNPRINTF ::vsnprintf +#include "../common/bsd/qplatformdefs.h" #endif // QPLATFORMDEFS_H diff --git a/mkspecs/freebsd-g++/qmake.conf b/mkspecs/freebsd-g++/qmake.conf index 56529389f65..1f4448889eb 100644 --- a/mkspecs/freebsd-g++/qmake.conf +++ b/mkspecs/freebsd-g++/qmake.conf @@ -3,32 +3,14 @@ # MAKEFILE_GENERATOR = UNIX -QMAKE_PLATFORM = freebsd bsd +QMAKE_PLATFORM = freebsd -include(../common/unix.conf) +include(../common/bsd/bsd.conf) -QMAKE_CFLAGS_THREAD = -pthread - -QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD - -# Addon software goes into /usr/local on the BSDs, by default we will look there +# Addon software goes into /usr/local on FreeBSD, by default we will look there QMAKE_INCDIR = /usr/local/include QMAKE_LIBDIR = /usr/local/lib -QMAKE_LFLAGS_THREAD = -pthread - -QMAKE_LIBS = -QMAKE_LIBS_DYNLOAD = -QMAKE_LIBS_EXECINFO = -lexecinfo -QMAKE_LIBS_X11 = -lXext -lX11 -lm -QMAKE_LIBS_OPENGL = -lGL -QMAKE_LIBS_THREAD = - -QMAKE_AR = ar cqs -QMAKE_OBJCOPY = objcopy -QMAKE_NM = nm -P -QMAKE_RANLIB = - include(../common/gcc-base-unix.conf) include(../common/g++-unix.conf) load(qt_config) diff --git a/mkspecs/freebsd-g++/qplatformdefs.h b/mkspecs/freebsd-g++/qplatformdefs.h index a7305fe8ea0..0e3fd6b2b85 100644 --- a/mkspecs/freebsd-g++/qplatformdefs.h +++ b/mkspecs/freebsd-g++/qplatformdefs.h @@ -37,4 +37,9 @@ ** ****************************************************************************/ -#include "../freebsd-clang/qplatformdefs.h" +#ifndef QPLATFORMDEFS_H +#define QPLATFORMDEFS_H + +#include "../common/bsd/qplatformdefs.h" + +#endif // QPLATFORMDEFS_H diff --git a/mkspecs/netbsd-g++/qmake.conf b/mkspecs/netbsd-g++/qmake.conf index ddd82326af8..31005d9134b 100644 --- a/mkspecs/netbsd-g++/qmake.conf +++ b/mkspecs/netbsd-g++/qmake.conf @@ -3,35 +3,20 @@ # MAKEFILE_GENERATOR = UNIX -QMAKE_PLATFORM = netbsd bsd +QMAKE_PLATFORM = netbsd -include(../common/unix.conf) -include(../common/gcc-base-unix.conf) -include(../common/g++-unix.conf) - -QMAKE_CFLAGS_THREAD = -pthread - -QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD +include(../common/bsd/bsd.conf) +# Addon software goes into /usr/pkg on NetBSD, by default we will look there QMAKE_INCDIR = /usr/pkg/include QMAKE_LIBDIR = /usr/pkg/lib + +# System provided X11 defaults to X11R7 path on NetBSD since 5.0 QMAKE_INCDIR_X11 = /usr/X11R7/include QMAKE_LIBDIR_X11 = /usr/X11R7/lib QMAKE_INCDIR_OPENGL = /usr/X11R7/include QMAKE_LIBDIR_OPENGL = /usr/X11R7/lib -QMAKE_LFLAGS_THREAD = -pthread - -QMAKE_LIBS = -QMAKE_LIBS_DYNLOAD = -QMAKE_LIBS_EXECINFO = -lexecinfo -QMAKE_LIBS_X11 = -lXext -lX11 -lm -QMAKE_LIBS_OPENGL = -lGL -QMAKE_LIBS_THREAD = - -QMAKE_AR = ar cqs -QMAKE_OBJCOPY = objcopy -QMAKE_NM = nm -P -QMAKE_RANLIB = - +include(../common/gcc-base-unix.conf) +include(../common/g++-unix.conf) load(qt_config) diff --git a/mkspecs/netbsd-g++/qplatformdefs.h b/mkspecs/netbsd-g++/qplatformdefs.h index f039ec70d11..0e3fd6b2b85 100644 --- a/mkspecs/netbsd-g++/qplatformdefs.h +++ b/mkspecs/netbsd-g++/qplatformdefs.h @@ -40,45 +40,6 @@ #ifndef QPLATFORMDEFS_H #define QPLATFORMDEFS_H -// Get Qt defines/settings - -#include "qglobal.h" - -// Set any POSIX/XOPEN defines at the top of this file to turn on specific APIs - -#include - - -// We are hot - unistd.h should have turned on the specific APIs we requested - - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef QT_NO_IPV6IFNAME -#include -#endif - -#include "../common/posix/qplatformdefs.h" - -#undef QT_OPEN_LARGEFILE -#define QT_OPEN_LARGEFILE 0 - -#define QT_SNPRINTF ::snprintf -#define QT_VSNPRINTF ::vsnprintf +#include "../common/bsd/qplatformdefs.h" #endif // QPLATFORMDEFS_H diff --git a/mkspecs/openbsd-g++/qmake.conf b/mkspecs/openbsd-g++/qmake.conf index 9b280891dfd..e7ac523486c 100644 --- a/mkspecs/openbsd-g++/qmake.conf +++ b/mkspecs/openbsd-g++/qmake.conf @@ -3,36 +3,24 @@ # MAKEFILE_GENERATOR = UNIX -QMAKE_PLATFORM = openbsd bsd +QMAKE_PLATFORM = openbsd -include(../common/unix.conf) -include(../common/gcc-base-unix.conf) -include(../common/g++-unix.conf) - -QMAKE_CFLAGS_THREAD = -pthread - -QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD +include(../common/bsd/bsd.conf) +# Addon software goes into /usr/local on OpenBSD, by default we will look there QMAKE_INCDIR = /usr/local/include QMAKE_LIBDIR = /usr/local/lib + +# System provided X11 defaults to X11R6 path on OpenBSD QMAKE_INCDIR_X11 = /usr/X11R6/include QMAKE_LIBDIR_X11 = /usr/X11R6/lib QMAKE_INCDIR_OPENGL = /usr/X11R6/include QMAKE_LIBDIR_OPENGL = /usr/X11R6/lib -QMAKE_LFLAGS_THREAD = -pthread +include(../common/gcc-base-unix.conf) +include(../common/g++-unix.conf) + +# Reset g++-unix.conf's NOUNDEF flags as OpenBSD libc can't handle environ QMAKE_LFLAGS_NOUNDEF = -QMAKE_LIBS = -QMAKE_LIBS_DYNLOAD = -QMAKE_LIBS_EXECINFO = -lexecinfo -QMAKE_LIBS_X11 = -lXext -lX11 -lm -QMAKE_LIBS_OPENGL = -lGL -QMAKE_LIBS_THREAD = - -QMAKE_AR = ar cqs -QMAKE_OBJCOPY = objcopy -QMAKE_NM = nm -P -QMAKE_RANLIB = - load(qt_config) diff --git a/mkspecs/openbsd-g++/qplatformdefs.h b/mkspecs/openbsd-g++/qplatformdefs.h index 4fe2eb8434f..0e3fd6b2b85 100644 --- a/mkspecs/openbsd-g++/qplatformdefs.h +++ b/mkspecs/openbsd-g++/qplatformdefs.h @@ -40,46 +40,6 @@ #ifndef QPLATFORMDEFS_H #define QPLATFORMDEFS_H -// Get Qt defines/settings - -#include "qglobal.h" - -// Set any POSIX/XOPEN defines at the top of this file to turn on specific APIs - -#include - - -// We are hot - unistd.h should have turned on the specific APIs we requested - - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef QT_NO_IPV6IFNAME -#include -#endif - -#include "../common/posix/qplatformdefs.h" - -#undef QT_OPEN_LARGEFILE -#define QT_OPEN_LARGEFILE 0 - -#define QT_SNPRINTF ::snprintf -#define QT_VSNPRINTF ::vsnprintf +#include "../common/bsd/qplatformdefs.h" #endif // QPLATFORMDEFS_H diff --git a/qmake/doc/snippets/code/doc_src_qmake-manual.pro b/qmake/doc/snippets/code/doc_src_qmake-manual.pro index d98085e5b23..c3b6e6595f9 100644 --- a/qmake/doc/snippets/code/doc_src_qmake-manual.pro +++ b/qmake/doc/snippets/code/doc_src_qmake-manual.pro @@ -421,7 +421,7 @@ This is a test. #! [71] -system(ls /bin):HAS_BIN=FALSE +system("ls /bin"): HAS_BIN = TRUE #! [71] diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index 12004c62c36..d356adada55 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -1953,7 +1953,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t) char buff[256]; QString dep_cmd = replaceExtraCompilerVariables(tmp_dep_cmd, inpf, tmp_out, LocalShell); dep_cmd = dep_cd_cmd + fixEnvVariables(dep_cmd); - if(FILE *proc = QT_POPEN(dep_cmd.toLatin1().constData(), "r")) { + if (FILE *proc = QT_POPEN(dep_cmd.toLatin1().constData(), QT_POPEN_READ)) { QString indeps; while(!feof(proc)) { int read_in = (int)fread(buff, 1, 255, proc); @@ -2045,7 +2045,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t) char buff[256]; QString dep_cmd = replaceExtraCompilerVariables(tmp_dep_cmd, inpf, out, LocalShell); dep_cmd = dep_cd_cmd + fixEnvVariables(dep_cmd); - if(FILE *proc = QT_POPEN(dep_cmd.toLatin1().constData(), "r")) { + if (FILE *proc = QT_POPEN(dep_cmd.toLatin1().constData(), QT_POPEN_READ)) { QString indeps; while(!feof(proc)) { int read_in = (int)fread(buff, 1, 255, proc); diff --git a/qmake/generators/makefile.h b/qmake/generators/makefile.h index 41b90eb5002..a67a0ec0fc0 100644 --- a/qmake/generators/makefile.h +++ b/qmake/generators/makefile.h @@ -41,9 +41,11 @@ QT_BEGIN_NAMESPACE #ifdef Q_OS_WIN32 #define QT_POPEN _popen +#define QT_POPEN_READ "rb" #define QT_PCLOSE _pclose #else #define QT_POPEN popen +#define QT_POPEN_READ "r" #define QT_PCLOSE pclose #endif diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp index 80a62a1cc28..b0f7593fbee 100644 --- a/qmake/generators/unix/unixmake.cpp +++ b/qmake/generators/unix/unixmake.cpp @@ -601,8 +601,11 @@ UnixMakefileGenerator::defaultInstall(const QString &t) } else if (project->first("TEMPLATE") == "lib" && project->isActiveConfig("staticlib")) { copy_cmd += "-$(INSTALL_FILE) " + src_targ + ' ' + dst_targ; } else if (!isAux) { - if (bundle == SlicedBundle) - ret += mkdir_p_asstring("\"`dirname " + dst_targ + "`\"", false) + "\n\t"; + if (bundle == SlicedBundle) { + if (!ret.isEmpty()) + ret += "\n\t"; + ret += mkdir_p_asstring("\"`dirname " + dst_targ + "`\"", false); + } copy_cmd += "-$(INSTALL_PROGRAM) " + src_targ + ' ' + dst_targ; } if(project->first("TEMPLATE") == "lib" && !project->isActiveConfig("staticlib") diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp index d8ac80f99d0..1e1a7ff2279 100644 --- a/qmake/generators/win32/msvc_nmake.cpp +++ b/qmake/generators/win32/msvc_nmake.cpp @@ -406,11 +406,14 @@ void NmakeMakefileGenerator::init() project->values("QMAKE_DISTCLEAN").append(tgt + ".lib"); } if (project->isActiveConfig("debug_info")) { - QString pdbfile = tgt + ".pdb"; + // Add the compiler's PDB file. + QString pdbfile = var("OBJECTS_DIR") + project->first("TARGET") + ".vc.pdb"; QString escapedPdbFile = escapeFilePath(pdbfile); project->values("QMAKE_CFLAGS").append("/Fd" + escapedPdbFile); project->values("QMAKE_CXXFLAGS").append("/Fd" + escapedPdbFile); - project->values("QMAKE_DISTCLEAN").append(pdbfile); + project->values("QMAKE_CLEAN").append(pdbfile); + // Add the linker's PDB file to the distclean target. + project->values("QMAKE_DISTCLEAN").append(tgt + ".pdb"); } if (project->isActiveConfig("debug")) { project->values("QMAKE_CLEAN").append(tgt + ".ilk"); diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp index 5e655464b71..39898567a78 100644 --- a/qmake/generators/win32/msvc_objectmodel.cpp +++ b/qmake/generators/win32/msvc_objectmodel.cpp @@ -2318,7 +2318,7 @@ bool VCFilter::addExtraCompiler(const VCFilterFile &info) dep_cmd.prepend(QLatin1String("cd ") + Project->escapeFilePath(Option::fixPathToLocalOS(Option::output_dir, false)) + QLatin1String(" && ")); - if(FILE *proc = QT_POPEN(dep_cmd.toLatin1().constData(), "r")) { + if (FILE *proc = QT_POPEN(dep_cmd.toLatin1().constData(), QT_POPEN_READ)) { QString indeps; while(!feof(proc)) { int read_in = (int)fread(buff, 1, 255, proc); diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp index d55e5bacf2e..7a713e1b65b 100644 --- a/qmake/generators/win32/msvc_vcproj.cpp +++ b/qmake/generators/win32/msvc_vcproj.cpp @@ -1610,7 +1610,7 @@ void VcprojGenerator::initResourceFiles() dep_cmd.prepend(QLatin1String("cd ") + escapeFilePath(Option::fixPathToLocalOS(Option::output_dir, false)) + QLatin1String(" && ")); - if(FILE *proc = QT_POPEN(dep_cmd.toLatin1().constData(), "r")) { + if (FILE *proc = QT_POPEN(dep_cmd.toLatin1().constData(), QT_POPEN_READ)) { QString indeps; while(!feof(proc)) { int read_in = (int)fread(buff, 1, 255, proc); diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp index 80569e503af..9717dccae1e 100644 --- a/qmake/library/qmakebuiltins.cpp +++ b/qmake/library/qmakebuiltins.cpp @@ -67,9 +67,11 @@ #ifdef Q_OS_WIN32 #define QT_POPEN _popen +#define QT_POPEN_READ "rb" #define QT_PCLOSE _pclose #else #define QT_POPEN popen +#define QT_POPEN_READ "r" #define QT_PCLOSE pclose #endif @@ -416,7 +418,7 @@ QByteArray QMakeEvaluator::getCommandOutput(const QString &args) const #else if (FILE *proc = QT_POPEN(QString(QLatin1String("cd ") + IoUtils::shellQuote(QDir::toNativeSeparators(currentDirectory())) - + QLatin1String(" && ") + args).toLocal8Bit().constData(), "r")) { + + QLatin1String(" && ") + args).toLocal8Bit().constData(), QT_POPEN_READ)) { while (!feof(proc)) { char buff[10 * 1024]; int read_in = int(fread(buff, 1, sizeof(buff), proc)); @@ -426,6 +428,9 @@ QByteArray QMakeEvaluator::getCommandOutput(const QString &args) const } QT_PCLOSE(proc); } +# ifdef Q_OS_WIN + out.replace("\r\n", "\n"); +# endif #endif return out; } diff --git a/qmake/library/qmakeglobals.cpp b/qmake/library/qmakeglobals.cpp index 6a648e9ecfb..82764e8732d 100644 --- a/qmake/library/qmakeglobals.cpp +++ b/qmake/library/qmakeglobals.cpp @@ -59,9 +59,11 @@ #ifdef Q_OS_WIN32 #define QT_POPEN _popen +#define QT_POPEN_READ "rb" #define QT_PCLOSE _pclose #else #define QT_POPEN popen +#define QT_POPEN_READ "r" #define QT_PCLOSE pclose #endif @@ -307,7 +309,7 @@ bool QMakeGlobals::initProperties() data = proc.readAll(); #else if (FILE *proc = QT_POPEN(QString(QMakeInternal::IoUtils::shellQuote(qmake_abslocation) - + QLatin1String(" -query")).toLocal8Bit(), "r")) { + + QLatin1String(" -query")).toLocal8Bit(), QT_POPEN_READ)) { char buff[1024]; while (!feof(proc)) data.append(buff, int(fread(buff, 1, 1023, proc))); diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java index 48510b3fdf8..04b8e6a06f7 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java @@ -93,6 +93,7 @@ public class QtNative private static final int m_moveThreshold = 0; private static ClipboardManager m_clipboardManager = null; private static Method m_checkSelfPermissionMethod = null; + private static Boolean m_tabletEventSupported = null; private static final Runnable runPendingCppRunnablesRunnable = new Runnable() { @Override public void run() { @@ -385,6 +386,9 @@ public class QtNative { int pointerType = 0; + if (m_tabletEventSupported == null) + m_tabletEventSupported = isTabletEventSupported(); + switch (event.getToolType(0)) { case MotionEvent.TOOL_TYPE_STYLUS: pointerType = 1; // QTabletEvent::Pen @@ -395,7 +399,7 @@ public class QtNative // TODO TOOL_TYPE_MOUSE } - if (pointerType != 0) { + if (m_tabletEventSupported && pointerType != 0) { tabletEvent(id, event.getDeviceId(), event.getEventTime(), event.getAction(), pointerType, event.getButtonState(), event.getX(), event.getY(), event.getPressure()); } else { @@ -762,6 +766,7 @@ public class QtNative // pointer methods // tablet methods + public static native boolean isTabletEventSupported(); public static native void tabletEvent(int winId, int deviceId, long time, int action, int pointerType, int buttonState, float x, float y, float pressure); // tablet methods diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 669ab136aca..33e42a944d0 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -1073,16 +1073,18 @@ # define Q_COMPILER_DEFAULT_DELETE_MEMBERS #endif -#if defined(__cpp_constexpr) && __cpp_constexpr-0 >= 201304 -# define Q_DECL_CONSTEXPR constexpr -# define Q_DECL_RELAXED_CONSTEXPR constexpr -# define Q_CONSTEXPR constexpr -# define Q_RELAXED_CONSTEXPR constexpr -#elif defined Q_COMPILER_CONSTEXPR -# define Q_DECL_CONSTEXPR constexpr -# define Q_DECL_RELAXED_CONSTEXPR -# define Q_CONSTEXPR constexpr -# define Q_RELAXED_CONSTEXPR const +#if defined Q_COMPILER_CONSTEXPR +# if defined(__cpp_constexpr) && __cpp_constexpr-0 >= 201304 +# define Q_DECL_CONSTEXPR constexpr +# define Q_DECL_RELAXED_CONSTEXPR constexpr +# define Q_CONSTEXPR constexpr +# define Q_RELAXED_CONSTEXPR constexpr +# else +# define Q_DECL_CONSTEXPR constexpr +# define Q_DECL_RELAXED_CONSTEXPR +# define Q_CONSTEXPR constexpr +# define Q_RELAXED_CONSTEXPR const +# endif #else # define Q_DECL_CONSTEXPR # define Q_DECL_RELAXED_CONSTEXPR diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 6ca2ecff91a..d87e4da9f7e 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -1187,6 +1187,7 @@ bool qSharedBuild() Q_DECL_NOTHROW \value MV_10_9 OS X 10.9 \value MV_10_10 OS X 10.10 \value MV_10_11 OS X 10.11 + \value MV_10_12 macOS 10.12 \value MV_Unknown An unknown and currently unsupported platform \value MV_CHEETAH Apple codename for MV_10_0 @@ -1201,6 +1202,7 @@ bool qSharedBuild() Q_DECL_NOTHROW \value MV_MAVERICKS Apple codename for MV_10_9 \value MV_YOSEMITE Apple codename for MV_10_10 \value MV_ELCAPITAN Apple codename for MV_10_11 + \value MV_SIERRA Apple codename for MV_10_12 \value MV_IOS iOS (any) \value MV_IOS_4_3 iOS 4.3 @@ -1216,6 +1218,10 @@ bool qSharedBuild() Q_DECL_NOTHROW \value MV_IOS_8_3 iOS 8.3 \value MV_IOS_8_4 iOS 8.4 \value MV_IOS_9_0 iOS 9.0 + \value MV_IOS_9_1 iOS 9.1 + \value MV_IOS_9_2 iOS 9.2 + \value MV_IOS_9_3 iOS 9.3 + \value MV_IOS_10_0 iOS 10.0 \value MV_None Not a Darwin operating system @@ -1229,11 +1235,25 @@ bool qSharedBuild() Q_DECL_NOTHROW Defined on Darwin-based operating systems such as OS X, iOS, watchOS, and tvOS. */ +/*! + \macro Q_OS_MAC + \relates + + Deprecated synonym for \c Q_OS_DARWIN. Do not use. + */ + /*! \macro Q_OS_OSX \relates - Defined on OS X. + Deprecated synonym for \c Q_OS_MACOS. Do not use. + */ + +/*! + \macro Q_OS_MACOS + \relates + + Defined on macOS. */ /*! @@ -2648,10 +2668,12 @@ QString QSysInfo::kernelVersion() to determine the distribution name and returns that. If determining the distribution name failed, it returns "unknown". - \b{Darwin, OS X and iOS note}: this function returns "osx" for OS X + \b{Darwin, OS X and iOS note}: this function returns "macos" for macOS systems, "ios" for iOS systems and "darwin" in case the system could not be determined. + \b{OS X note}: this function returns "osx" for versions of macOS prior to 10.12. + \b{FreeBSD note}: this function returns "debian" for Debian/kFreeBSD and "unknown" otherwise. @@ -2683,8 +2705,11 @@ QString QSysInfo::productType() #elif defined(Q_OS_IOS) return QStringLiteral("ios"); -#elif defined(Q_OS_OSX) - return QStringLiteral("osx"); +#elif defined(Q_OS_MACOS) + const QAppleOperatingSystemVersion version = qt_apple_os_version(); + if (version.major == 10 && version.minor < 12) + return QStringLiteral("osx"); + return QStringLiteral("macos"); #elif defined(Q_OS_DARWIN) return QStringLiteral("darwin"); @@ -2766,7 +2791,7 @@ QString QSysInfo::prettyProductName() { #if defined(Q_OS_IOS) return QLatin1String("iOS ") + productVersion(); -#elif defined(Q_OS_OSX) +#elif defined(Q_OS_MACOS) // get the known codenames const char *basename = 0; switch (int(MacintoshVersion)) { @@ -2800,12 +2825,15 @@ QString QSysInfo::prettyProductName() case MV_ELCAPITAN: basename = "OS X El Capitan ("; break; + case MV_SIERRA: + basename = "macOS Sierra ("; + break; } if (basename) return QLatin1String(basename) + productVersion() + QLatin1Char(')'); - // a future version of OS X - return QLatin1String("OS X ") + productVersion(); + // a future version of macOS + return QLatin1String("macOS ") + productVersion(); #elif defined(Q_OS_WINPHONE) return QLatin1String("Windows Phone ") + QLatin1String(winVer_helper()); #elif defined(Q_OS_WIN) diff --git a/src/corelib/global/qsysinfo.h b/src/corelib/global/qsysinfo.h index b74fc804682..d1a4102f291 100644 --- a/src/corelib/global/qsysinfo.h +++ b/src/corelib/global/qsysinfo.h @@ -145,6 +145,7 @@ public: MV_10_9 = Q_MV_OSX(10, 9), MV_10_10 = Q_MV_OSX(10, 10), MV_10_11 = Q_MV_OSX(10, 11), + MV_10_12 = Q_MV_OSX(10, 12), /* codenames */ MV_CHEETAH = MV_10_0, @@ -159,6 +160,7 @@ public: MV_MAVERICKS = MV_10_9, MV_YOSEMITE = MV_10_10, MV_ELCAPITAN = MV_10_11, + MV_SIERRA = MV_10_12, /* iOS */ MV_IOS = 1 << 8, @@ -174,7 +176,11 @@ public: MV_IOS_8_2 = Q_MV_IOS(8, 2), MV_IOS_8_3 = Q_MV_IOS(8, 3), MV_IOS_8_4 = Q_MV_IOS(8, 4), - MV_IOS_9_0 = Q_MV_IOS(9, 0) + MV_IOS_9_0 = Q_MV_IOS(9, 0), + MV_IOS_9_1 = Q_MV_IOS(9, 1), + MV_IOS_9_2 = Q_MV_IOS(9, 2), + MV_IOS_9_3 = Q_MV_IOS(9, 3), + MV_IOS_10_0 = Q_MV_IOS(10, 0) }; #if defined(Q_OS_MAC) static const MacVersion MacintoshVersion; diff --git a/src/corelib/global/qsystemdetection.h b/src/corelib/global/qsystemdetection.h index 1e95d1a2ec2..1e852ae538d 100644 --- a/src/corelib/global/qsystemdetection.h +++ b/src/corelib/global/qsystemdetection.h @@ -48,7 +48,7 @@ The operating system, must be one of: (Q_OS_x) DARWIN - Any Darwin system (OS X, iOS, watchOS, tvOS) - OSX - OS X + MACOS - macOS IOS - iOS WATCHOS - watchOS TVOS - tvOS @@ -115,7 +115,7 @@ # else # // there is no "real" OS X define (rdar://22640089), # // assume any non iOS-based platform is OS X for now -# define Q_OS_OSX +# define Q_OS_MACOS # endif # else # error "Qt has not been ported to this Apple platform - see http://www.qt.io/developers" @@ -229,15 +229,16 @@ #ifdef Q_OS_DARWIN64 #define Q_OS_MAC64 #endif -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS #define Q_OS_MACX +#define Q_OS_OSX #endif #ifdef Q_OS_DARWIN # include # include # -# ifdef Q_OS_OSX +# ifdef Q_OS_MACOS # if !defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_6 # undef __MAC_OS_X_VERSION_MIN_REQUIRED # define __MAC_OS_X_VERSION_MIN_REQUIRED __MAC_10_6 @@ -266,6 +267,9 @@ # if !defined(__MAC_10_11) # define __MAC_10_11 101100 # endif +# if !defined(__MAC_10_12) +# define __MAC_10_12 101200 +# endif # if !defined(MAC_OS_X_VERSION_10_7) # define MAC_OS_X_VERSION_10_7 1070 # endif @@ -281,6 +285,9 @@ # if !defined(MAC_OS_X_VERSION_10_11) # define MAC_OS_X_VERSION_10_11 101100 # endif +# if !defined(MAC_OS_X_VERSION_10_12) +# define MAC_OS_X_VERSION_10_12 101200 +# endif # # if !defined(__IPHONE_4_3) # define __IPHONE_4_3 40300 @@ -321,6 +328,18 @@ # if !defined(__IPHONE_9_0) # define __IPHONE_9_0 90000 # endif +# if !defined(__IPHONE_9_1) +# define __IPHONE_9_1 90100 +# endif +# if !defined(__IPHONE_9_2) +# define __IPHONE_9_2 90200 +# endif +# if !defined(__IPHONE_9_3) +# define __IPHONE_9_3 90300 +# endif +# if !defined(__IPHONE_10_0) +# define __IPHONE_10_0 100000 +# endif #endif #ifdef __LSB_VERSION__ diff --git a/src/corelib/io/qfileselector.cpp b/src/corelib/io/qfileselector.cpp index 4ac12fc9ea4..29ef0f937eb 100644 --- a/src/corelib/io/qfileselector.cpp +++ b/src/corelib/io/qfileselector.cpp @@ -386,8 +386,12 @@ QStringList QFileSelectorPrivate::platformSelectors() # endif # endif QString productName = QSysInfo::productType(); +# ifdef Q_OS_MACOS + if (productName != QStringLiteral("osx")) + ret << QStringLiteral("osx"); // compatibility +# endif if (productName != QLatin1String("unknown")) - ret << productName; // "opensuse", "fedora", "osx", "ios", "android" + ret << productName; // "opensuse", "fedora", "macos", "ios", "android" #endif return ret; } diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index fd204b00deb..f31ac754256 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -1186,8 +1186,6 @@ QByteArray QIODevice::read(qint64 maxSize) } /*! - \overload - Reads all remaining data from the device, and returns it as a byte array. diff --git a/src/corelib/kernel/qabstracteventdispatcher.h b/src/corelib/kernel/qabstracteventdispatcher.h index 6e59790d5c4..f92e418ebfe 100644 --- a/src/corelib/kernel/qabstracteventdispatcher.h +++ b/src/corelib/kernel/qabstracteventdispatcher.h @@ -111,7 +111,8 @@ public: void removeNativeEventFilter(QAbstractNativeEventFilter *filterObj); bool filterNativeEvent(const QByteArray &eventType, void *message, long *result); #if QT_DEPRECATED_SINCE(5, 0) - QT_DEPRECATED bool filterEvent(void *message) { return filterNativeEvent("", message, 0); } + QT_DEPRECATED bool filterEvent(void *message) + { return filterNativeEvent("", message, Q_NULLPTR); } #endif Q_SIGNALS: diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp index 601733b9395..0e2d4e23249 100644 --- a/src/corelib/kernel/qcoreapplication_win.cpp +++ b/src/corelib/kernel/qcoreapplication_win.cpp @@ -55,7 +55,10 @@ QT_BEGIN_NAMESPACE int appCmdShow = 0; -#if defined(Q_OS_WINRT) +// GetModuleFileName only exists for MSVC2015 and upwards for WinRT, meaning +// Windows 10 (Mobile). Hence take the first argument passed to the +// QCoreApplication contructor for older versions as a fallback on older platforms. +#if defined(Q_OS_WINRT) && _MSC_VER < 1900 Q_CORE_EXPORT QString qAppFileName() { @@ -67,31 +70,7 @@ QString QCoreApplicationPrivate::appName() const return QFileInfo(QCoreApplication::arguments().constFirst()).baseName(); } -#else - -Q_CORE_EXPORT HINSTANCE qWinAppInst() // get Windows app handle -{ - return GetModuleHandle(0); -} - -Q_CORE_EXPORT HINSTANCE qWinAppPrevInst() // get Windows prev app handle -{ - return 0; -} - -Q_CORE_EXPORT int qWinAppCmdShow() // get main window show command -{ -#if defined(Q_OS_WINCE) - return appCmdShow; -#else - STARTUPINFO startupInfo; - GetStartupInfo(&startupInfo); - - return (startupInfo.dwFlags & STARTF_USESHOWWINDOW) - ? startupInfo.wShowWindow - : SW_SHOWDEFAULT; -#endif -} +#else // !(defined(Q_OS_WINRT) && _MSC_VER < 1900) Q_CORE_EXPORT QString qAppFileName() // get application file name { @@ -139,6 +118,34 @@ QString QCoreApplicationPrivate::appName() const return QFileInfo(qAppFileName()).baseName(); } +#endif // !(defined(Q_OS_WINRT) && _MSC_VER < 1900) + +#ifndef Q_OS_WINRT + +Q_CORE_EXPORT HINSTANCE qWinAppInst() // get Windows app handle +{ + return GetModuleHandle(0); +} + +Q_CORE_EXPORT HINSTANCE qWinAppPrevInst() // get Windows prev app handle +{ + return 0; +} + +Q_CORE_EXPORT int qWinAppCmdShow() // get main window show command +{ +#if defined(Q_OS_WINCE) + return appCmdShow; +#else + STARTUPINFO startupInfo; + GetStartupInfo(&startupInfo); + + return (startupInfo.dwFlags & STARTF_USESHOWWINDOW) + ? startupInfo.wShowWindow + : SW_SHOWDEFAULT; +#endif +} + /***************************************************************************** qWinMain() - Initializes Windows. Called from WinMain() in qtmain_win.cpp *****************************************************************************/ diff --git a/src/corelib/kernel/qfunctions_winrt.h b/src/corelib/kernel/qfunctions_winrt.h index 4012f8019c4..e0777b8df82 100644 --- a/src/corelib/kernel/qfunctions_winrt.h +++ b/src/corelib/kernel/qfunctions_winrt.h @@ -209,6 +209,9 @@ static inline HRESULT _await_impl(const Microsoft::WRL::ComPtr &asyncOp, Awai if (FAILED(hr) || status != Completed) { HRESULT ec; hr = asyncInfo->get_ErrorCode(&ec); + if (FAILED(hr)) + return hr; + hr = asyncInfo->Close(); if (FAILED(hr)) return hr; return ec; diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h index f7c60cc3093..85ac7e77e45 100644 --- a/src/corelib/kernel/qmetaobject.h +++ b/src/corelib/kernel/qmetaobject.h @@ -187,7 +187,7 @@ private: // signature() has been renamed to methodSignature() in Qt 5. // Warning, that function returns a QByteArray; check the life time if // you convert to char*. - char *signature(struct renamedInQt5_warning_checkTheLifeTime * = 0) Q_DECL_EQ_DELETE; + char *signature(struct renamedInQt5_warning_checkTheLifeTime * = Q_NULLPTR) Q_DECL_EQ_DELETE; #endif static QMetaMethod fromSignalImpl(const QMetaObject *, void **); diff --git a/src/corelib/kernel/qppsobject.cpp b/src/corelib/kernel/qppsobject.cpp index dbff997c88d..30498a380d9 100644 --- a/src/corelib/kernel/qppsobject.cpp +++ b/src/corelib/kernel/qppsobject.cpp @@ -175,7 +175,7 @@ QPpsAttribute QPpsObjectPrivate::decodeNumber(pps_decoder_t *decoder) // In order to support more number types, we have to do something stupid because the PPS // library won't let us work any other way. Basically, we have to probe the encoded type in // order to try to get exactly what we want. - long long llValue; + int64_t llValue; double dValue; int iValue; QPpsAttribute::Flags flags; @@ -193,7 +193,7 @@ QPpsAttribute QPpsObjectPrivate::decodeNumber(pps_decoder_t *decoder) return QPpsAttribute(); } flags = readFlags(decoder); - return QPpsAttributePrivate::createPpsAttribute(llValue, flags); + return QPpsAttributePrivate::createPpsAttribute(static_cast(llValue), flags); default: qWarning("QPpsObjectPrivate::decodeNumber: pps_decoder_get_int failed"); return QPpsAttribute(); diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index e7a31e0b70d..deedd61c171 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -110,7 +110,7 @@ QT_BEGIN_NAMESPACE #ifndef QT_NO_THREAD -Q_STATIC_ASSERT(sizeof(pthread_t) == sizeof(Qt::HANDLE)); +Q_STATIC_ASSERT(sizeof(pthread_t) <= sizeof(Qt::HANDLE)); enum { ThreadPriorityResetFlag = 0x80000000 }; @@ -210,6 +210,30 @@ static void clear_thread_data() pthread_setspecific(current_thread_data_key, 0); } +template +static typename QtPrivate::QEnableIf::isIntegral, Qt::HANDLE>::Type to_HANDLE(T id) +{ + return reinterpret_cast(static_cast(id)); +} + +template +static typename QtPrivate::QEnableIf::isIntegral, T>::Type from_HANDLE(Qt::HANDLE id) +{ + return static_cast(reinterpret_cast(id)); +} + +template +static typename QtPrivate::QEnableIf::isPointer, Qt::HANDLE>::Type to_HANDLE(T id) +{ + return id; +} + +template +static typename QtPrivate::QEnableIf::isPointer, T>::Type from_HANDLE(Qt::HANDLE id) +{ + return static_cast(id); +} + void QThreadData::clearCurrentThreadData() { clear_thread_data(); @@ -231,7 +255,7 @@ QThreadData *QThreadData::current(bool createIfNecessary) } data->deref(); data->isAdopted = true; - data->threadId = (Qt::HANDLE)pthread_self(); + data->threadId = to_HANDLE(pthread_self()); if (!QCoreApplicationPrivate::theMainThread) QCoreApplicationPrivate::theMainThread = data->thread.load(); } @@ -311,7 +335,7 @@ void *QThreadPrivate::start(void *arg) thr->d_func()->setPriority(QThread::Priority(thr->d_func()->priority & ~ThreadPriorityResetFlag)); } - data->threadId = (Qt::HANDLE)pthread_self(); + data->threadId = to_HANDLE(pthread_self()); set_thread_data(data); data->ref(); @@ -328,7 +352,7 @@ void *QThreadPrivate::start(void *arg) // sets the name of the current thread. QString objectName = thr->objectName(); - pthread_t thread_id = reinterpret_cast(data->threadId); + pthread_t thread_id = from_HANDLE(data->threadId); if (Q_LIKELY(objectName.isEmpty())) setCurrentThreadName(thread_id, thr->metaObject()->className()); else @@ -391,7 +415,7 @@ void QThreadPrivate::finish(void *arg) Qt::HANDLE QThread::currentThreadId() Q_DECL_NOTHROW { // requires a C cast here otherwise we run into trouble on AIX - return (Qt::HANDLE)pthread_self(); + return to_HANDLE(pthread_self()); } #if defined(QT_LINUXBASE) && !defined(_SC_NPROCESSORS_ONLN) @@ -617,18 +641,17 @@ void QThread::start(Priority priority) } } - int code = - pthread_create(reinterpret_cast(&d->data->threadId), &attr, - QThreadPrivate::start, this); + pthread_t threadId; + int code = pthread_create(&threadId, &attr, QThreadPrivate::start, this); if (code == EPERM) { // caller does not have permission to set the scheduling // parameters/policy #if defined(QT_HAS_THREAD_PRIORITY_SCHEDULING) pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED); #endif - code = pthread_create(reinterpret_cast(&d->data->threadId), &attr, - QThreadPrivate::start, this); + code = pthread_create(&threadId, &attr, QThreadPrivate::start, this); } + d->data->threadId = to_HANDLE(threadId); pthread_attr_destroy(&attr); @@ -650,7 +673,7 @@ void QThread::terminate() if (!d->data->threadId) return; - int code = pthread_cancel(reinterpret_cast(d->data->threadId)); + int code = pthread_cancel(from_HANDLE(d->data->threadId)); if (code) { qWarning("QThread::start: Thread termination error: %s", qPrintable(qt_error_string((code)))); @@ -663,7 +686,7 @@ bool QThread::wait(unsigned long time) Q_D(QThread); QMutexLocker locker(&d->mutex); - if (reinterpret_cast(d->data->threadId) == pthread_self()) { + if (from_HANDLE(d->data->threadId) == pthread_self()) { qWarning("QThread::wait: Thread tried to wait on itself"); return false; } @@ -705,7 +728,7 @@ void QThreadPrivate::setPriority(QThread::Priority threadPriority) int sched_policy; sched_param param; - if (pthread_getschedparam(reinterpret_cast(data->threadId), &sched_policy, ¶m) != 0) { + if (pthread_getschedparam(from_HANDLE(data->threadId), &sched_policy, ¶m) != 0) { // failed to get the scheduling policy, don't bother setting // the priority qWarning("QThread::setPriority: Cannot get scheduler parameters"); @@ -721,15 +744,15 @@ void QThreadPrivate::setPriority(QThread::Priority threadPriority) } param.sched_priority = prio; - int status = pthread_setschedparam(reinterpret_cast(data->threadId), sched_policy, ¶m); + int status = pthread_setschedparam(from_HANDLE(data->threadId), sched_policy, ¶m); # ifdef SCHED_IDLE // were we trying to set to idle priority and failed? if (status == -1 && sched_policy == SCHED_IDLE && errno == EINVAL) { // reset to lowest priority possible - pthread_getschedparam(reinterpret_cast(data->threadId), &sched_policy, ¶m); + pthread_getschedparam(from_HANDLE(data->threadId), &sched_policy, ¶m); param.sched_priority = sched_get_priority_min(sched_policy); - pthread_setschedparam(reinterpret_cast(data->threadId), sched_policy, ¶m); + pthread_setschedparam(from_HANDLE(data->threadId), sched_policy, ¶m); } # else Q_UNUSED(status); diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 85da1743660..629a0bc744c 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -601,6 +601,7 @@ static int ucstrncmp(const QChar *a, const uchar *c, int l) } # else // 32-bit, we can't do MOVQ to load 8 bytes + Q_UNUSED(nullmask); enum { MaxTailLength = 15 }; # endif diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp index 2f24165069e..0233ccbf87a 100644 --- a/src/gui/image/qiconloader.cpp +++ b/src/gui/image/qiconloader.cpp @@ -563,7 +563,7 @@ static bool directoryMatchesSize(const QIconDirInfo &dir, int iconsize) return dir.size == iconsize; } else if (dir.type == QIconDirInfo::Scalable) { - return dir.size <= dir.maxSize && + return iconsize <= dir.maxSize && iconsize >= dir.minSize; } else if (dir.type == QIconDirInfo::Threshold) { diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 36595025f52..d33e1053c8b 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -3134,6 +3134,8 @@ void QImage::mirrored_inplace(bool horizontal, bool vertical) return; detach(); + if (!d->own_data) + *this = copy(); do_mirror(d, d, horizontal, vertical); } @@ -3280,6 +3282,8 @@ void QImage::rgbSwapped_inplace() return; detach(); + if (!d->own_data) + *this = copy(); switch (d->format) { case Format_Invalid: @@ -4763,7 +4767,7 @@ bool QImageData::convertInPlace(QImage::Format newFormat, Qt::ImageConversionFla return true; // No in-place conversion if we have to detach - if (ref.load() > 1 || ro_data) + if (ref.load() > 1 || !own_data) return false; InPlace_Image_Converter converter = qimage_inplace_converter_map[format][newFormat]; diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h index 2aa19a8465a..6f8e214b112 100644 --- a/src/gui/image/qimage.h +++ b/src/gui/image/qimage.h @@ -321,7 +321,7 @@ public: static QImage::Format toImageFormat(QPixelFormat format) Q_DECL_NOTHROW; #if QT_DEPRECATED_SINCE(5, 0) - QT_DEPRECATED inline QString text(const char* key, const char* lang=0) const; + QT_DEPRECATED inline QString text(const char *key, const char *lang = Q_NULLPTR) const; QT_DEPRECATED inline QList textList() const; QT_DEPRECATED inline QStringList textLanguages() const; QT_DEPRECATED inline QString text(const QImageTextKeyLang&) const; diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index 3c80b070e3b..bb0b76d55f0 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -769,8 +769,8 @@ static bool convert_A2RGB30_PM_to_ARGB_inplace(QImageData *data, Qt::ImageConver static bool convert_indexed8_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConversionFlags) { Q_ASSERT(data->format == QImage::Format_Indexed8); - if (!data->own_data) - return false; + Q_ASSERT(data->own_data); + const int depth = 32; const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2; @@ -823,8 +823,8 @@ static bool convert_indexed8_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConve static bool convert_indexed8_to_ARGB_inplace(QImageData *data, Qt::ImageConversionFlags) { Q_ASSERT(data->format == QImage::Format_Indexed8); - if (!data->own_data) - return false; + Q_ASSERT(data->own_data); + const int depth = 32; const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2; @@ -874,8 +874,7 @@ static bool convert_indexed8_to_ARGB_inplace(QImageData *data, Qt::ImageConversi static bool convert_indexed8_to_RGB_inplace(QImageData *data, Qt::ImageConversionFlags flags) { Q_ASSERT(data->format == QImage::Format_Indexed8); - if (!data->own_data) - return false; + Q_ASSERT(data->own_data); if (data->has_alpha_clut) { for (int i = 0; i < data->colortable.size(); ++i) @@ -892,8 +891,8 @@ static bool convert_indexed8_to_RGB_inplace(QImageData *data, Qt::ImageConversio static bool convert_indexed8_to_RGB16_inplace(QImageData *data, Qt::ImageConversionFlags) { Q_ASSERT(data->format == QImage::Format_Indexed8); - if (!data->own_data) - return false; + Q_ASSERT(data->own_data); + const int depth = 16; const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2; @@ -949,8 +948,8 @@ static bool convert_indexed8_to_RGB16_inplace(QImageData *data, Qt::ImageConvers static bool convert_RGB_to_RGB16_inplace(QImageData *data, Qt::ImageConversionFlags) { Q_ASSERT(data->format == QImage::Format_RGB32); - if (!data->own_data) - return false; + Q_ASSERT(data->own_data); + const int depth = 16; const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2; diff --git a/src/gui/text/qdistancefield.cpp b/src/gui/text/qdistancefield.cpp index d90134482dc..5a696807b4a 100644 --- a/src/gui/text/qdistancefield.cpp +++ b/src/gui/text/qdistancefield.cpp @@ -550,7 +550,9 @@ static void makeDistanceField(QDistanceFieldData *data, const QPainterPath &path QPoint n(to.y() - from.y(), from.x() - to.x()); if (n.x() == 0 && n.y() == 0) continue; - int scale = qRound((offs << 16) / qSqrt(qreal(n.x() * n.x() + n.y() * n.y()))); // 8:16 + int scale = qRound((offs << 16) / qSqrt(qreal(n.x()) * n.x() + qreal(n.y()) * n.y())); // 8:16 + Q_ASSERT(scale != 0); + n.rx() = n.x() * scale >> 8; n.ry() = n.y() * scale >> 8; normals.append(n); @@ -805,8 +807,9 @@ QDistanceFieldData *QDistanceFieldData::create(const QPainterPath &path, bool do { int dfMargin = QT_DISTANCEFIELD_RADIUS(doubleResolution) / QT_DISTANCEFIELD_SCALE(doubleResolution); int glyphWidth = qCeil(path.boundingRect().width() / QT_DISTANCEFIELD_SCALE(doubleResolution)) + dfMargin * 2; + int glyphHeight = qCeil(path.boundingRect().height() / QT_DISTANCEFIELD_SCALE(doubleResolution)) + dfMargin * 2; - QDistanceFieldData *data = create(QSize(glyphWidth, QT_DISTANCEFIELD_TILESIZE(doubleResolution))); + QDistanceFieldData *data = create(QSize(glyphWidth, glyphHeight)); makeDistanceField(data, path, diff --git a/src/gui/text/qdistancefield_p.h b/src/gui/text/qdistancefield_p.h index 7cd385587b9..c6c5e6b6501 100644 --- a/src/gui/text/qdistancefield_p.h +++ b/src/gui/text/qdistancefield_p.h @@ -58,7 +58,6 @@ QT_BEGIN_NAMESPACE #define QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE 54 -#define QT_DISTANCEFIELD_DEFAULT_TILESIZE 64 #define QT_DISTANCEFIELD_DEFAULT_SCALE 16 #define QT_DISTANCEFIELD_DEFAULT_RADIUS 80 #define QT_DISTANCEFIELD_HIGHGLYPHCOUNT 2000 @@ -66,9 +65,6 @@ QT_BEGIN_NAMESPACE #define QT_DISTANCEFIELD_BASEFONTSIZE(NarrowOutlineFont) \ (NarrowOutlineFont ? QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE * 2 : \ QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE) -#define QT_DISTANCEFIELD_TILESIZE(NarrowOutlineFont) \ - (NarrowOutlineFont ? QT_DISTANCEFIELD_DEFAULT_TILESIZE * 2 : \ - QT_DISTANCEFIELD_DEFAULT_TILESIZE) #define QT_DISTANCEFIELD_SCALE(NarrowOutlineFont) \ (NarrowOutlineFont ? QT_DISTANCEFIELD_DEFAULT_SCALE / 2 : \ QT_DISTANCEFIELD_DEFAULT_SCALE) diff --git a/src/network/network.pro b/src/network/network.pro index 7a05f927c52..256d718df6f 100644 --- a/src/network/network.pro +++ b/src/network/network.pro @@ -34,7 +34,8 @@ ANDROID_PERMISSIONS += \ MODULE_WINRT_CAPABILITIES = \ internetClient \ - internetClientServer + internetClientServer \ + privateNetworkClientServer MODULE_PLUGIN_TYPES = \ bearer diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index dd43615f98d..9817d4c57d1 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -259,31 +259,23 @@ bool QNativeSocketEngine::initialize(qintptr socketDescriptor, QAbstractSocket:: // Start processing incoming data if (d->socketType == QAbstractSocket::TcpSocket) { HRESULT hr; - hr = QEventDispatcherWinRT::runOnXamlThread([d, socket, this]() { + QEventDispatcherWinRT::runOnXamlThread([d, &hr, socket, this]() { ComPtr buffer; HRESULT hr = g->bufferFactory->Create(READ_BUFFER_SIZE, &buffer); - RETURN_HR_IF_FAILED("initialize(): Could not create buffer"); - + RETURN_OK_IF_FAILED("initialize(): Could not create buffer"); ComPtr stream; hr = socket->get_InputStream(&stream); - RETURN_HR_IF_FAILED("initialize(): Could not obtain input stream"); + RETURN_OK_IF_FAILED("initialize(): Could not obtain input stream"); hr = stream->ReadAsync(buffer.Get(), READ_BUFFER_SIZE, InputStreamOptions_Partial, d->readOp.GetAddressOf()); - if (FAILED(hr)) { - qErrnoWarning(hr, "initialize(): Failed to read from the socket buffer (%s).", + RETURN_OK_IF_FAILED_WITH_ARGS("initialize(): Failed to read from the socket buffer (%s).", socketDescription(this).constData()); - return E_FAIL; - } hr = d->readOp->put_Completed(Callback(d, &QNativeSocketEnginePrivate::handleReadyRead).Get()); - if (FAILED(hr)) { - qErrnoWarning(hr, "initialize(): Failed to set socket read callback (%s).", + RETURN_OK_IF_FAILED_WITH_ARGS("initialize(): Failed to set socket read callback (%s).", socketDescription(this).constData()); - return E_FAIL; - } return S_OK; }); - if (hr == E_FAIL) + if (FAILED(hr)) return false; - Q_ASSERT_SUCCEEDED(hr); } d->socketState = socketState; @@ -335,11 +327,14 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port) Q_ASSERT_SUCCEEDED(hr); d->socketState = QAbstractSocket::ConnectingState; - hr = QEventDispatcherWinRT::runOnXamlThread([d]() { - return d->connectOp->put_Completed(Callback( + QEventDispatcherWinRT::runOnXamlThread([d, &hr]() { + hr = d->connectOp->put_Completed(Callback( d, &QNativeSocketEnginePrivate::handleConnectOpFinished).Get()); + RETURN_OK_IF_FAILED("connectToHostByName: Could not register \"connectOp\" callback"); + return S_OK; }); - Q_ASSERT_SUCCEEDED(hr); + if (FAILED(hr)) + return false; return d->socketState == QAbstractSocket::ConnectedState; } @@ -348,19 +343,21 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port) { Q_D(QNativeSocketEngine); HRESULT hr; - hr = QEventDispatcherWinRT::runOnXamlThread([address, d, port, this]() { - HRESULT hr; + // runOnXamlThread may only return S_OK (will assert otherwise) so no need to check its result. + // hr is set inside the lambda though. If an error occurred hr will point that out. + bool specificErrorSet = false; + QEventDispatcherWinRT::runOnXamlThread([address, d, &hr, port, &specificErrorSet, this]() { ComPtr hostAddress; if (address != QHostAddress::Any && address != QHostAddress::AnyIPv4 && address != QHostAddress::AnyIPv6) { ComPtr hostNameFactory; hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(), &hostNameFactory); - RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Could not obtain hostname factory"); + RETURN_OK_IF_FAILED("QNativeSocketEngine::bind: Could not obtain hostname factory"); const QString addressString = address.toString(); HStringReference addressRef(reinterpret_cast(addressString.utf16())); hr = hostNameFactory->CreateHostName(addressRef.Get(), &hostAddress); - RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Could not create hostname."); + RETURN_OK_IF_FAILED("QNativeSocketEngine::bind: Could not create hostname."); } QString portQString = port ? QString::number(port) : QString(); @@ -371,13 +368,13 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port) if (!d->tcpListener) { hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_StreamSocketListener).Get(), &d->tcpListener); - RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Could not create tcp listener"); + RETURN_OK_IF_FAILED("QNativeSocketEngine::bind: Could not create tcp listener"); } hr = d->tcpListener->add_ConnectionReceived( Callback(d, &QNativeSocketEnginePrivate::handleClientConnection).Get(), &d->connectionToken); - RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Could not register client connection callback"); + RETURN_OK_IF_FAILED("QNativeSocketEngine::bind: Could not register client connection callback"); hr = d->tcpListener->BindEndpointAsync(hostAddress.Get(), portString.Get(), &op); } else if (d->socketType == QAbstractSocket::UdpSocket) { hr = d->udpSocket()->BindEndpointAsync(hostAddress.Get(), portString.Get(), &op); @@ -385,15 +382,40 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port) if (hr == E_ACCESSDENIED) { qErrnoWarning(hr, "Unable to bind socket (%s:%hu/%s). Please check your manifest capabilities.", qPrintable(address.toString()), port, socketDescription(this).constData()); - return hr; + d->setError(QAbstractSocket::SocketAccessError, + QNativeSocketEnginePrivate::AccessErrorString); + d->socketState = QAbstractSocket::UnconnectedState; + specificErrorSet = true; + return S_OK; } - RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Unable to bind socket"); + RETURN_OK_IF_FAILED("QNativeSocketEngine::bind: Unable to bind socket"); hr = QWinRTFunctions::await(op); - RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Could not wait for bind to finish"); + if (hr == 0x80072741) { // The requested address is not valid in its context + d->setError(QAbstractSocket::SocketAddressNotAvailableError, + QNativeSocketEnginePrivate::AddressNotAvailableErrorString); + d->socketState = QAbstractSocket::UnconnectedState; + specificErrorSet = true; + return S_OK; + // Only one usage of each socket address (protocol/network address/port) is normally permitted + } else if (hr == 0x80072740) { + d->setError(QAbstractSocket::AddressInUseError, + QNativeSocketEnginePrivate::AddressInuseErrorString); + d->socketState = QAbstractSocket::UnconnectedState; + specificErrorSet = true; + return S_OK; + } + RETURN_OK_IF_FAILED("QNativeSocketEngine::bind: Could not wait for bind to finish"); return S_OK; }); - Q_ASSERT_SUCCEEDED(hr); + if (FAILED(hr)) { + if (!specificErrorSet) { + d->setError(QAbstractSocket::UnknownSocketError, + QNativeSocketEnginePrivate::UnknownSocketErrorString); + d->socketState = QAbstractSocket::UnconnectedState; + } + return false; + } d->socketState = QAbstractSocket::BoundState; return d->fetchConnectionParameters(); @@ -853,20 +875,22 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc case QAbstractSocket::TcpSocket: { ComPtr socket; hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_StreamSocket).Get(), &socket); - Q_ASSERT_SUCCEEDED(hr); + RETURN_FALSE_IF_FAILED("createNewSocket: Could not create socket instance"); socketDescriptor = qintptr(socket.Detach()); break; } case QAbstractSocket::UdpSocket: { ComPtr socket; hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_DatagramSocket).Get(), &socket); - Q_ASSERT_SUCCEEDED(hr); + RETURN_FALSE_IF_FAILED("createNewSocket: Could not create socket instance"); socketDescriptor = qintptr(socket.Detach()); - hr = QEventDispatcherWinRT::runOnXamlThread([this]() { - HRESULT hr = udpSocket()->add_MessageReceived(Callback(this, &QNativeSocketEnginePrivate::handleNewDatagram).Get(), &connectionToken); - return hr; + QEventDispatcherWinRT::runOnXamlThread([&hr, this]() { + hr = udpSocket()->add_MessageReceived(Callback(this, &QNativeSocketEnginePrivate::handleNewDatagram).Get(), &connectionToken); + RETURN_OK_IF_FAILED("createNewSocket: Could not add \"message received\" callback") + return S_OK; }); - Q_ASSERT_SUCCEEDED(hr); + if (FAILED(hr)) + return false; break; } default: diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index c7b4875134b..b3820aea977 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -1192,6 +1192,11 @@ bool QSslSocketBackendPrivate::startHandshake() #endif if (!checkSslErrors()) return false; + // A slot, attached to sslErrors signal can call + // abort/close/disconnetFromHost/etc; no need to + // continue handshake then. + if (q->state() != QAbstractSocket::ConnectedState) + return false; } else { sslErrors.clear(); } diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index 533e0e2d5b5..e1f4ddd360a 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -212,6 +212,12 @@ void QCoreTextFontDatabase::populateFontDatabase() if (familyName.startsWith(QLatin1Char('.')) || familyName == QLatin1String("LastResort")) continue; +#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) + // Skip font families with no corresponding fonts + if (![UIFont fontNamesForFamilyName:(NSString*)familyNameRef].count) + continue; +#endif + QPlatformFontDatabase::registerFontFamily(familyName); #if defined(Q_OS_OSX) diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.mm b/src/plugins/bearer/corewlan/qcorewlanengine.mm index 3f8f80fc857..52e76219e66 100644 --- a/src/plugins/bearer/corewlan/qcorewlanengine.mm +++ b/src/plugins/bearer/corewlan/qcorewlanengine.mm @@ -85,7 +85,7 @@ extern "C" { // Otherwise it won't find CWKeychain* symbols at link time [locker lock]; QMacAutoReleasePool pool; notificationCenter = [NSNotificationCenter defaultCenter]; - currentInterface = [CWInterface interfaceWithName:nil]; + currentInterface = [CWInterface interface]; [notificationCenter addObserver:self selector:@selector(notificationHandler:) name:CWPowerDidChangeNotification object:nil]; [locker unlock]; return self; diff --git a/src/plugins/generic/tuiotouch/qtuiohandler.cpp b/src/plugins/generic/tuiotouch/qtuiohandler.cpp index 6026e06b558..5d34e0ea38b 100644 --- a/src/plugins/generic/tuiotouch/qtuiohandler.cpp +++ b/src/plugins/generic/tuiotouch/qtuiohandler.cpp @@ -306,7 +306,6 @@ QWindowSystemInterface::TouchPoint QTuioHandler::cursorToTouchPoint(const QTuioC tp.normalPosition = m_transform.map(tp.normalPosition); tp.state = tc.state(); - tp.area = QRectF(0, 0, 1, 1); // we map the touch to the size of the window. we do this, because frankly, // trying to figure out which part of the screen to hit in order to press an diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp index 064a0c095c1..5be128a0c5a 100644 --- a/src/plugins/platforms/android/androidjniinput.cpp +++ b/src/plugins/platforms/android/androidjniinput.cpp @@ -252,9 +252,19 @@ namespace QtAndroidInput QWindowSystemInterface::handleTouchEvent(window, touchDevice, m_touchPoints); } + static bool isTabletEventSupported(JNIEnv */*env*/, jobject /*thiz*/) + { +#ifdef QT_NO_TABLETEVENT + return false; +#else + return true; +#endif // QT_NO_TABLETEVENT + } + static void tabletEvent(JNIEnv */*env*/, jobject /*thiz*/, jint /*winId*/, jint deviceId, jlong time, jint action, jint pointerType, jint buttonState, jfloat x, jfloat y, jfloat pressure) { +#ifndef QT_NO_TABLETEVENT QPointF globalPosF(x, y); QPoint globalPos((int)x, (int)y); QWindow *tlw = topLevelWindowAt(globalPos); @@ -296,6 +306,7 @@ namespace QtAndroidInput QWindowSystemInterface::handleTabletEvent(tlw, ulong(time), localPos, globalPosF, QTabletEvent::Stylus, pointerType, buttons, pressure, 0, 0, 0., 0., 0, deviceId, Qt::NoModifier); +#endif // QT_NO_TABLETEVENT } static int mapAndroidKey(int key) @@ -783,6 +794,7 @@ namespace QtAndroidInput {"mouseUp", "(III)V", (void *)mouseUp}, {"mouseMove", "(III)V", (void *)mouseMove}, {"longPress", "(III)V", (void *)longPress}, + {"isTabletEventSupported", "()Z", (void *)isTabletEventSupported}, {"tabletEvent", "(IIJIIIFFF)V", (void *)tabletEvent}, {"keyDown", "(IIIZ)V", (void *)keyDown}, {"keyUp", "(IIIZ)V", (void *)keyUp}, diff --git a/src/plugins/platforms/ios/qiosapplicationstate.h b/src/plugins/platforms/ios/qiosapplicationstate.h index e487407d7b8..1c77b26da12 100644 --- a/src/plugins/platforms/ios/qiosapplicationstate.h +++ b/src/plugins/platforms/ios/qiosapplicationstate.h @@ -41,18 +41,19 @@ #define QIOSAPPLICATIONSTATE_H #include +#include + +Q_FORWARD_DECLARE_OBJC_CLASS(NSObject); QT_BEGIN_NAMESPACE -@class QIOSApplicationStateListener; - class QIOSApplicationState { public: QIOSApplicationState(); ~QIOSApplicationState(); private: - QIOSApplicationStateListener *m_listener; + QVector m_observers; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qiosapplicationstate.mm b/src/plugins/platforms/ios/qiosapplicationstate.mm index afb61a134b2..7b923e4692e 100644 --- a/src/plugins/platforms/ios/qiosapplicationstate.mm +++ b/src/plugins/platforms/ios/qiosapplicationstate.mm @@ -42,100 +42,21 @@ #include #include +#include + #import -@interface QIOSApplicationStateListener : NSObject -@end - -@implementation QIOSApplicationStateListener - -- (id)init +static Qt::ApplicationState qtApplicationState(UIApplicationState uiApplicationState) { - self = [super init]; - if (self) { - // Listen for application state changes. - // Note: We use notifications rather than application delegate callbacks to - // also support hybrid applications were QIOSApplicationDelegate is not in use. - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(applicationDidBecomeActive) - name:UIApplicationDidBecomeActiveNotification - object:nil]; - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(applicationWillResignActive) - name:UIApplicationWillResignActiveNotification - object:nil]; - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(applicationDidEnterBackground) - name:UIApplicationDidEnterBackgroundNotification - object:nil]; - - // Update the current state now, since we have missed all the updates - // posted from AppKit so far. But let QPA finish initialization first. - dispatch_async(dispatch_get_main_queue(), ^{ - [self handleApplicationStateChanged:[UIApplication sharedApplication].applicationState]; - }); - } - return self; -} - -- (void)dealloc -{ - [[NSNotificationCenter defaultCenter] - removeObserver:self - name:UIApplicationDidBecomeActiveNotification - object:nil]; - [[NSNotificationCenter defaultCenter] - removeObserver:self - name:UIApplicationWillResignActiveNotification - object:nil]; - [[NSNotificationCenter defaultCenter] - removeObserver:self - name:UIApplicationDidEnterBackgroundNotification - object:nil]; - [super dealloc]; -} - -- (void)applicationDidBecomeActive -{ - [self handleApplicationStateChanged:UIApplicationStateActive]; -} - -- (void)applicationWillResignActive -{ - // Note that UIApplication is still UIApplicationStateActive at this - // point, but since there is no separate notification for the inactive - // state, we report UIApplicationStateInactive now: - [self handleApplicationStateChanged:UIApplicationStateInactive]; -} - -- (void)applicationDidEnterBackground -{ - [self handleApplicationStateChanged:UIApplicationStateBackground]; -} - -- (void)handleApplicationStateChanged:(UIApplicationState)uiApplicationState -{ - // We may receive application state changes after QCoreApplication has - // gone down, as the block we schedule on the main queue keeps the - // listener alive. In that case we just ignore the notification. - if (!qApp) - return; - - Qt::ApplicationState state; switch (uiApplicationState) { case UIApplicationStateActive: - // The application is visible in front, and receiving events: - state = Qt::ApplicationActive; - break; + // The application is visible in front, and receiving events + return Qt::ApplicationActive; case UIApplicationStateInactive: // The app is running in the foreground but is not receiving events. This // typically happens while transitioning to/from active/background, like - // upon app launch or when receiving incoming calls: - state = Qt::ApplicationInactive; - break; + // upon app launch or when receiving incoming calls. + return Qt::ApplicationInactive; case UIApplicationStateBackground: // Normally the app would enter this state briefly before it gets // suspeded (you have five seconds, according to Apple). @@ -144,25 +65,54 @@ // API for doing that yet, we handle this state as "about to be suspended". // Note: A screen-shot for the SpringBoard will also be taken after this // call returns. - state = Qt::ApplicationSuspended; - break; + return Qt::ApplicationSuspended; } +} + +static void handleApplicationStateChanged(UIApplicationState uiApplicationState) +{ + Qt::ApplicationState state = qtApplicationState(uiApplicationState); QWindowSystemInterface::handleApplicationStateChanged(state); QWindowSystemInterface::flushWindowSystemEvents(); } -@end - QT_BEGIN_NAMESPACE QIOSApplicationState::QIOSApplicationState() - : m_listener([[QIOSApplicationStateListener alloc] init]) { + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + + m_observers.push_back([notificationCenter addObserverForName:UIApplicationDidBecomeActiveNotification + object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *) { + handleApplicationStateChanged(UIApplicationStateActive); + } + ]); + + m_observers.push_back([notificationCenter addObserverForName:UIApplicationWillResignActiveNotification + object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *) { + // Note: UIApplication is still UIApplicationStateActive at this point, + // but since there is no separate notification for the inactive state, + // we report UIApplicationStateInactive now. + handleApplicationStateChanged(UIApplicationStateInactive); + } + ]); + + m_observers.push_back([notificationCenter addObserverForName:UIApplicationDidEnterBackgroundNotification + object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *) { + handleApplicationStateChanged(UIApplicationStateBackground); + } + ]); + + // Initialize correct startup state, which may not be the Qt default (inactive) + UIApplicationState startupState = [UIApplication sharedApplication].applicationState; + QGuiApplicationPrivate::applicationState = qtApplicationState(startupState); } QIOSApplicationState::~QIOSApplicationState() { - [m_listener release]; + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + foreach (const NSObject* observer, m_observers) + [notificationCenter removeObserver:observer]; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qioscontext.h b/src/plugins/platforms/ios/qioscontext.h index c8a4fae20ca..5b7917f7b45 100644 --- a/src/plugins/platforms/ios/qioscontext.h +++ b/src/plugins/platforms/ios/qioscontext.h @@ -40,6 +40,7 @@ #ifndef QIOSCONTEXT_H #define QIOSCONTEXT_H +#include #include @class EAGLContext; @@ -89,7 +90,9 @@ private: static void deleteBuffers(const FramebufferObject &framebufferObject); FramebufferObject &backingFramebufferObjectFor(QPlatformSurface *) const; - mutable QHash m_framebufferObjects; + mutable QHash m_framebufferObjects; + + bool needsRenderbufferResize(QPlatformSurface *) const; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm index 546b003d14e..d18e317bfbf 100644 --- a/src/plugins/platforms/ios/qioscontext.mm +++ b/src/plugins/platforms/ios/qioscontext.mm @@ -48,6 +48,8 @@ #import #import +Q_LOGGING_CATEGORY(lcQpaGLContext, "qt.qpa.glcontext"); + QIOSContext::QIOSContext(QOpenGLContext *context) : QPlatformOpenGLContext() , m_sharedContext(static_cast(context->shareHandle())) @@ -81,6 +83,8 @@ QIOSContext::QIOSContext(QOpenGLContext *context) // could take advantage of the unchanged buffer, but this means clients (and Qt) // will also assume that swapBufferes() is not needed, which is _not_ the case. m_format.setSwapBehavior(QSurfaceFormat::DoubleBuffer); + + qCDebug(lcQpaGLContext) << "created context with format" << m_format << "shared with" << m_sharedContext; } QIOSContext::~QIOSContext() @@ -123,10 +127,12 @@ static QString fboStatusString(GLenum status) } } +#define Q_ASSERT_IS_GL_SURFACE(surface) \ + Q_ASSERT(surface && (surface->surface()->surfaceType() & (QSurface::OpenGLSurface | QSurface::RasterGLSurface))) + bool QIOSContext::makeCurrent(QPlatformSurface *surface) { - Q_ASSERT(surface && (surface->surface()->surfaceType() == QSurface::OpenGLSurface - || surface->surface()->surfaceType() == QSurface::RasterGLSurface)); + Q_ASSERT_IS_GL_SURFACE(surface); [EAGLContext setCurrentContext:m_eaglContext]; @@ -134,54 +140,11 @@ bool QIOSContext::makeCurrent(QPlatformSurface *surface) if (surface->surface()->surfaceClass() == QSurface::Offscreen) return true; + Q_ASSERT(surface->surface()->surfaceClass() == QSurface::Window); FramebufferObject &framebufferObject = backingFramebufferObjectFor(surface); - // We bind the default FBO even if it's incomplete, so that clients who - // call glCheckFramebufferStatus as a result of this function returning - // false will get a matching error code. - glBindFramebuffer(GL_FRAMEBUFFER, framebufferObject.handle); - - return framebufferObject.isComplete; -} - -void QIOSContext::doneCurrent() -{ - [EAGLContext setCurrentContext:nil]; -} - -void QIOSContext::swapBuffers(QPlatformSurface *surface) -{ - Q_ASSERT(surface && (surface->surface()->surfaceType() == QSurface::OpenGLSurface - || surface->surface()->surfaceType() == QSurface::RasterGLSurface)); - - if (surface->surface()->surfaceClass() == QSurface::Offscreen) - return; // Nothing to do - - FramebufferObject &framebufferObject = backingFramebufferObjectFor(surface); - - [EAGLContext setCurrentContext:m_eaglContext]; - glBindRenderbuffer(GL_RENDERBUFFER, framebufferObject.colorRenderbuffer); - [m_eaglContext presentRenderbuffer:GL_RENDERBUFFER]; -} - -QIOSContext::FramebufferObject &QIOSContext::backingFramebufferObjectFor(QPlatformSurface *surface) const -{ - // We keep track of default-FBOs in the root context of a share-group. This assumes - // that the contexts form a tree, where leaf nodes are always destroyed before their - // parents. If that assumption (based on the current implementation) doesn't hold we - // should probably use QOpenGLMultiGroupSharedResource to track the shared default-FBOs. - if (m_sharedContext) - return m_sharedContext->backingFramebufferObjectFor(surface); - - Q_ASSERT(surface && surface->surface()->surfaceClass() == QSurface::Window); - QIOSWindow *window = static_cast(surface); - - FramebufferObject &framebufferObject = m_framebufferObjects[window]; - - // Set up an FBO for the window if it hasn't been created yet if (!framebufferObject.handle) { - [EAGLContext setCurrentContext:m_eaglContext]; - + // Set up an FBO for the window if it hasn't been created yet glGenFramebuffers(1, &framebufferObject.handle); glBindFramebuffer(GL_FRAMEBUFFER, framebufferObject.handle); @@ -201,17 +164,17 @@ QIOSContext::FramebufferObject &QIOSContext::backingFramebufferObjectFor(QPlatfo framebufferObject.depthRenderbuffer); } - connect(window, SIGNAL(destroyed(QObject*)), this, SLOT(windowDestroyed(QObject*))); + connect(static_cast(surface), SIGNAL(destroyed(QObject*)), this, SLOT(windowDestroyed(QObject*))); + } else { + glBindFramebuffer(GL_FRAMEBUFFER, framebufferObject.handle); } - // Ensure that the FBO's buffers match the size of the layer - UIView *view = reinterpret_cast(window->winId()); - CAEAGLLayer *layer = static_cast(view.layer); - if (framebufferObject.renderbufferWidth != (layer.frame.size.width * layer.contentsScale) || - framebufferObject.renderbufferHeight != (layer.frame.size.height * layer.contentsScale)) { - - [EAGLContext setCurrentContext:m_eaglContext]; - glBindFramebuffer(GL_FRAMEBUFFER, framebufferObject.handle); + if (needsRenderbufferResize(surface)) { + // Ensure that the FBO's buffers match the size of the layer + CAEAGLLayer *layer = static_cast(surface)->eaglLayer(); + qCDebug(lcQpaGLContext, "Reallocating renderbuffer storage - current: %dx%d, layer: %gx%g", + framebufferObject.renderbufferWidth, framebufferObject.renderbufferHeight, + layer.frame.size.width * layer.contentsScale, layer.frame.size.height * layer.contentsScale); glBindRenderbuffer(GL_RENDERBUFFER, framebufferObject.colorRenderbuffer); [m_eaglContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer]; @@ -234,12 +197,54 @@ QIOSContext::FramebufferObject &QIOSContext::backingFramebufferObjectFor(QPlatfo framebufferObject.isComplete = glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE; if (!framebufferObject.isComplete) { - qWarning("QIOSContext failed to make complete framebuffer object (%s)", + qCWarning(lcQpaGLContext, "QIOSContext failed to make complete framebuffer object (%s)", qPrintable(fboStatusString(glCheckFramebufferStatus(GL_FRAMEBUFFER)))); } } - return framebufferObject; + return framebufferObject.isComplete; +} + +void QIOSContext::doneCurrent() +{ + [EAGLContext setCurrentContext:nil]; +} + +void QIOSContext::swapBuffers(QPlatformSurface *surface) +{ + Q_ASSERT_IS_GL_SURFACE(surface); + + if (surface->surface()->surfaceClass() == QSurface::Offscreen) + return; // Nothing to do + + if (!static_cast(surface)->isExposed()) { + qCWarning(lcQpaGLContext, "Detected swapBuffers on a non-exposed window, skipping flush"); + return; + } + + FramebufferObject &framebufferObject = backingFramebufferObjectFor(surface); + Q_ASSERT_X(framebufferObject.isComplete, "QIOSContext", "swapBuffers on incomplete FBO"); + + if (needsRenderbufferResize(surface)) { + qCWarning(lcQpaGLContext, "CAEAGLLayer was resized between makeCurrent and swapBuffers, skipping flush"); + return; + } + + [EAGLContext setCurrentContext:m_eaglContext]; + glBindRenderbuffer(GL_RENDERBUFFER, framebufferObject.colorRenderbuffer); + [m_eaglContext presentRenderbuffer:GL_RENDERBUFFER]; +} + +QIOSContext::FramebufferObject &QIOSContext::backingFramebufferObjectFor(QPlatformSurface *surface) const +{ + // We keep track of default-FBOs in the root context of a share-group. This assumes + // that the contexts form a tree, where leaf nodes are always destroyed before their + // parents. If that assumption (based on the current implementation) doesn't hold we + // should probably use QOpenGLMultiGroupSharedResource to track the shared default-FBOs. + if (m_sharedContext) + return m_sharedContext->backingFramebufferObjectFor(surface); + else + return m_framebufferObjects[surface]; } GLuint QIOSContext::defaultFramebufferObject(QPlatformSurface *surface) const @@ -251,19 +256,41 @@ GLuint QIOSContext::defaultFramebufferObject(QPlatformSurface *surface) const return 0; } - return backingFramebufferObjectFor(surface).handle; + FramebufferObject &framebufferObject = backingFramebufferObjectFor(surface); + Q_ASSERT_X(framebufferObject.handle, "QIOSContext", "can't resolve default FBO before makeCurrent"); + + return framebufferObject.handle; +} + +bool QIOSContext::needsRenderbufferResize(QPlatformSurface *surface) const +{ + Q_ASSERT(surface->surface()->surfaceClass() == QSurface::Window); + + FramebufferObject &framebufferObject = backingFramebufferObjectFor(surface); + CAEAGLLayer *layer = static_cast(surface)->eaglLayer(); + + if (framebufferObject.renderbufferWidth != (layer.frame.size.width * layer.contentsScale)) + return true; + + if (framebufferObject.renderbufferHeight != (layer.frame.size.height * layer.contentsScale)) + return true; + + return false; } void QIOSContext::windowDestroyed(QObject *object) { QIOSWindow *window = static_cast(object); - if (m_framebufferObjects.contains(window)) { - EAGLContext *originalContext = [EAGLContext currentContext]; - [EAGLContext setCurrentContext:m_eaglContext]; - deleteBuffers(m_framebufferObjects[window]); - m_framebufferObjects.remove(window); - [EAGLContext setCurrentContext:originalContext]; - } + if (!m_framebufferObjects.contains(window)) + return; + + qCDebug(lcQpaGLContext) << object << "destroyed, deleting corresponding FBO"; + + EAGLContext *originalContext = [EAGLContext currentContext]; + [EAGLContext setCurrentContext:m_eaglContext]; + deleteBuffers(m_framebufferObjects[window]); + m_framebufferObjects.remove(window); + [EAGLContext setCurrentContext:originalContext]; } QFunctionPointer QIOSContext::getProcAddress(const char *functionName) diff --git a/src/plugins/platforms/ios/qiosscreen.h b/src/plugins/platforms/ios/qiosscreen.h index 56a0874bb4d..cc83e7f3d29 100644 --- a/src/plugins/platforms/ios/qiosscreen.h +++ b/src/plugins/platforms/ios/qiosscreen.h @@ -71,9 +71,13 @@ public: UIScreen *uiScreen() const; UIWindow *uiWindow() const; + void setUpdatesPaused(bool); + void updateProperties(); private: + void deliverUpdateRequests() const; + UIScreen *m_uiScreen; UIWindow *m_uiWindow; QRect m_geometry; @@ -82,6 +86,7 @@ private: uint m_physicalDpi; QSizeF m_physicalSize; QIOSOrientationListener *m_orientationListener; + CADisplayLink *m_displayLink; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index bfd22abaa43..d53f0df8464 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -46,8 +46,31 @@ #include "qiosviewcontroller.h" #include "quiview.h" +#include + #include +// ------------------------------------------------------------------------- + +typedef void (^DisplayLinkBlock)(CADisplayLink *displayLink); + +@implementation UIScreen (DisplayLinkBlock) +- (CADisplayLink*)displayLinkWithBlock:(DisplayLinkBlock)block +{ + return [self displayLinkWithTarget:[[block copy] autorelease] + selector:@selector(invokeDisplayLinkBlock:)]; +} +@end + +@implementation NSObject (DisplayLinkBlock) +- (void)invokeDisplayLinkBlock:(CADisplayLink *)sender +{ + DisplayLinkBlock block = static_cast(self); + block(sender); +} +@end + + // ------------------------------------------------------------------------- static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen) @@ -214,10 +237,16 @@ QIOSScreen::QIOSScreen(UIScreen *screen) } updateProperties(); + + m_displayLink = [m_uiScreen displayLinkWithBlock:^(CADisplayLink *) { deliverUpdateRequests(); }]; + m_displayLink.paused = YES; // Enabled when clients call QWindow::requestUpdate() + [m_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; } QIOSScreen::~QIOSScreen() { + [m_displayLink invalidate]; + [m_orientationListener release]; [m_uiWindow release]; } @@ -297,6 +326,35 @@ void QIOSScreen::updateProperties() QWindowSystemInterface::handleScreenGeometryChange(screen(), m_geometry, m_availableGeometry); } +void QIOSScreen::setUpdatesPaused(bool paused) +{ + m_displayLink.paused = paused; +} + +void QIOSScreen::deliverUpdateRequests() const +{ + bool pauseUpdates = true; + + QList windows = QGuiApplication::allWindows(); + for (int i = 0; i < windows.size(); ++i) { + if (platformScreenForWindow(windows.at(i)) != this) + continue; + + QWindowPrivate *wp = static_cast(QObjectPrivate::get(windows.at(i))); + if (!wp->updateRequestPending) + continue; + + wp->deliverUpdateRequest(); + + // Another update request was triggered, keep the display link running + if (wp->updateRequestPending) + pauseUpdates = false; + } + + // Pause the display link if there are no pending update requests + m_displayLink.paused = pauseUpdates; +} + QRect QIOSScreen::geometry() const { return m_geometry; diff --git a/src/plugins/platforms/ios/qioswindow.h b/src/plugins/platforms/ios/qioswindow.h index 6005d6dae36..afc2f0f89d8 100644 --- a/src/plugins/platforms/ios/qioswindow.h +++ b/src/plugins/platforms/ios/qioswindow.h @@ -88,6 +88,10 @@ public: QSurfaceFormat format() const Q_DECL_OVERRIDE; + void requestUpdate() Q_DECL_OVERRIDE; + + CAEAGLLayer *eaglLayer() const; + private: void applicationStateChanged(Qt::ApplicationState state); void applyGeometry(const QRect &rect); diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm index 481d4a06abb..fb2fd2b946d 100644 --- a/src/plugins/platforms/ios/qioswindow.mm +++ b/src/plugins/platforms/ios/qioswindow.mm @@ -377,6 +377,17 @@ void QIOSWindow::clearAccessibleCache() [m_view clearAccessibleCache]; } +void QIOSWindow::requestUpdate() +{ + static_cast(screen())->setUpdatesPaused(false); +} + +CAEAGLLayer *QIOSWindow::eaglLayer() const +{ + Q_ASSERT([m_view.layer isKindOfClass:[CAEAGLLayer class]]); + return static_cast(m_view.layer); +} + #include "moc_qioswindow.cpp" QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri b/src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri index e8598656878..c2d3849d8e9 100644 --- a/src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri +++ b/src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri @@ -31,7 +31,7 @@ contains(QT_CONFIG, xcb-qt) { DEFINES += XCB_USE_RENDER XCB_DIR = $$clean_path($$PWD/../../../../3rdparty/xcb) INCLUDEPATH += $$XCB_DIR/include $$XCB_DIR/include/xcb $$XCB_DIR/sysinclude - LIBS += -lxcb -L$$OUT_PWD/xcb-static -lxcb-static + LIBS += -lxcb -L$$MODULE_BASE_OUTDIR/lib -lxcb-static$$qtPlatformTargetSuffix() } else { LIBS += -lxcb -lxcb-image -lxcb-icccm -lxcb-sync -lxcb-xfixes -lxcb-shm -lxcb-randr -lxcb-shape -lxcb-keysyms !contains(DEFINES, QT_NO_XKB):LIBS += -lxcb-xkb diff --git a/src/plugins/platforms/xcb/xcb_qpa_lib.pro b/src/plugins/platforms/xcb/xcb_qpa_lib.pro index f4a4e5a78a8..db9ea32cd88 100644 --- a/src/plugins/platforms/xcb/xcb_qpa_lib.pro +++ b/src/plugins/platforms/xcb/xcb_qpa_lib.pro @@ -88,7 +88,7 @@ contains(QT_CONFIG, xcb-qt) { DEFINES += XCB_USE_RENDER XCB_DIR = ../../../3rdparty/xcb INCLUDEPATH += $$XCB_DIR/include $$XCB_DIR/sysinclude - LIBS += -lxcb -L$$OUT_PWD/xcb-static -lxcb-static + LIBS += -lxcb -L$$MODULE_BASE_OUTDIR/lib -lxcb-static$$qtPlatformTargetSuffix() } else { LIBS += -lxcb -lxcb-image -lxcb-icccm -lxcb-sync -lxcb-xfixes -lxcb-shm -lxcb-randr -lxcb-shape -lxcb-keysyms -lxcb-xinerama !contains(DEFINES, QT_NO_XKB):LIBS += -lxcb-xkb diff --git a/src/sql/drivers/mysql/qsql_mysql.cpp b/src/sql/drivers/mysql/qsql_mysql.cpp index 56caf52dcb0..b13e10e3a5f 100644 --- a/src/sql/drivers/mysql/qsql_mysql.cpp +++ b/src/sql/drivers/mysql/qsql_mysql.cpp @@ -428,6 +428,7 @@ bool QMYSQLResultPrivate::bindInValues() bind->buffer_length = f.bufLength = fieldInfo->length + 1; bind->is_null = &f.nullIndicator; bind->length = &f.bufLength; + bind->is_unsigned = fieldInfo->flags & UNSIGNED_FLAG ? 1 : 0; f.outField=field; ++i; diff --git a/src/widgets/graphicsview/qgraphicsscene.h b/src/widgets/graphicsview/qgraphicsscene.h index f0940b1611b..55352956760 100644 --- a/src/widgets/graphicsview/qgraphicsscene.h +++ b/src/widgets/graphicsview/qgraphicsscene.h @@ -159,7 +159,7 @@ public: #if QT_DEPRECATED_SINCE(5, 0) QT_DEPRECATED inline QGraphicsItem *itemAt(const QPointF &position) const { QList itemsAtPoint = items(position); - return itemsAtPoint.isEmpty() ? 0 : itemsAtPoint.first(); + return itemsAtPoint.isEmpty() ? Q_NULLPTR : itemsAtPoint.first(); } #endif QGraphicsItem *itemAt(const QPointF &pos, const QTransform &deviceTransform) const; @@ -173,7 +173,7 @@ public: #if QT_DEPRECATED_SINCE(5, 0) QT_DEPRECATED inline QGraphicsItem *itemAt(qreal x, qreal y) const { QList itemsAtPoint = items(QPointF(x, y)); - return itemsAtPoint.isEmpty() ? 0 : itemsAtPoint.first(); + return itemsAtPoint.isEmpty() ? Q_NULLPTR : itemsAtPoint.first(); } #endif inline QGraphicsItem *itemAt(qreal x, qreal y, const QTransform &deviceTransform) const diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp index d2e1a10566f..b6fd9f8ba8c 100644 --- a/src/widgets/itemviews/qtreeview.cpp +++ b/src/widgets/itemviews/qtreeview.cpp @@ -2303,8 +2303,8 @@ QModelIndex QTreeView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie int visualColumn = d->header->visualIndex(current.column()) + 1; while (visualColumn < d->model->columnCount(current.parent()) && isColumnHidden(d->header->logicalIndex(visualColumn))) visualColumn++; - - QModelIndex next = current.sibling(current.row(), visualColumn); + const int newColumn = d->header->logicalIndex(visualColumn); + const QModelIndex next = current.sibling(current.row(), newColumn); if (next.isValid()) return next; } diff --git a/src/widgets/util/qsystemtrayicon_win.cpp b/src/widgets/util/qsystemtrayicon_win.cpp index f34714c0161..7cbf9799019 100644 --- a/src/widgets/util/qsystemtrayicon_win.cpp +++ b/src/widgets/util/qsystemtrayicon_win.cpp @@ -236,22 +236,9 @@ void QSystemTrayIconSys::setIconContents(NOTIFYICONDATA &tnd) qStringToLimitedWCharArray(tip, tnd.szTip, sizeof(tnd.szTip)/sizeof(wchar_t)); } -static int iconFlag( QSystemTrayIcon::MessageIcon icon ) -{ - switch (icon) { - case QSystemTrayIcon::Information: - return NIIF_INFO; - case QSystemTrayIcon::Warning: - return NIIF_WARNING; - case QSystemTrayIcon::Critical: - return NIIF_ERROR; - case QSystemTrayIcon::NoIcon: - return NIIF_NONE; - default: - Q_ASSERT_X(false, "QSystemTrayIconSys::showMessage", "Invalid QSystemTrayIcon::MessageIcon value"); - return NIIF_NONE; - } -} +#ifndef NIIF_LARGE_ICON +# define NIIF_LARGE_ICON 0x00000020 +#endif bool QSystemTrayIconSys::showMessage(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs) { @@ -261,7 +248,22 @@ bool QSystemTrayIconSys::showMessage(const QString &title, const QString &messag qStringToLimitedWCharArray(title, tnd.szInfoTitle, 64); tnd.uID = q_uNOTIFYICONID; - tnd.dwInfoFlags = iconFlag(type); + switch (type) { + case QSystemTrayIcon::Information: + tnd.dwInfoFlags = NIIF_INFO; + break; + case QSystemTrayIcon::Warning: + tnd.dwInfoFlags = NIIF_WARNING; + break; + case QSystemTrayIcon::Critical: + tnd.dwInfoFlags = NIIF_ERROR; + break; + case QSystemTrayIcon::NoIcon: + tnd.dwInfoFlags = hIcon ? NIIF_USER : NIIF_NONE; + break; + } + if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA) + tnd.dwInfoFlags |= NIIF_LARGE_ICON; tnd.cbSize = notifyIconSize; tnd.hWnd = m_hwnd; tnd.uTimeout = uSecs; @@ -302,9 +304,10 @@ HICON QSystemTrayIconSys::createIcon() const QIcon icon = q->icon(); if (icon.isNull()) return oldIcon; - const int iconSizeX = GetSystemMetrics(SM_CXSMICON); - const int iconSizeY = GetSystemMetrics(SM_CYSMICON); - const QSize size = icon.actualSize(QSize(iconSizeX, iconSizeY)); + const QSize requestedSize = QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA + ? QSize(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)) + : QSize(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)); + const QSize size = icon.actualSize(requestedSize); const QPixmap pm = icon.pixmap(size); if (pm.isNull()) return oldIcon; diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp index 16cbebeed5c..9e4a1abbb18 100644 --- a/tests/auto/gui/image/qimage/tst_qimage.cpp +++ b/tests/auto/gui/image/qimage/tst_qimage.cpp @@ -2493,6 +2493,35 @@ void tst_QImage::inplaceRgbSwapped() } QCOMPARE(imageSwapped.constScanLine(0), orginalPtr); + + for (int rw = 0; rw <= 1; rw++) { + // Test attempted inplace conversion of images created on existing buffer + uchar *volatileData = 0; + QImage orig = imageSwapped; + QImage dataSwapped; + { + QVERIFY(!orig.isNull()); + volatileData = new uchar[orig.byteCount()]; + memcpy(volatileData, orig.constBits(), orig.byteCount()); + + QImage dataImage; + if (rw) + dataImage = QImage(volatileData, orig.width(), orig.height(), orig.format()); + else + dataImage = QImage((const uchar *)volatileData, orig.width(), orig.height(), orig.format()); + + if (orig.colorCount()) + dataImage.setColorTable(orig.colorTable()); + + dataSwapped = std::move(dataImage).rgbSwapped(); + QVERIFY(!dataSwapped.isNull()); + delete[] volatileData; + } + + QVERIFY2(dataSwapped.constBits() != volatileData, rw ? "non-const" : "const"); + QCOMPARE(dataSwapped, orig.rgbSwapped()); + } + #endif } @@ -2575,6 +2604,35 @@ void tst_QImage::inplaceMirrored() } } QCOMPARE(imageMirrored.constScanLine(0), originalPtr); + + for (int rw = 0; rw <= 1; rw++) { + // Test attempted inplace conversion of images created on existing buffer + uchar *volatileData = 0; + QImage orig = imageMirrored; + QImage dataSwapped; + { + QVERIFY(!orig.isNull()); + volatileData = new uchar[orig.byteCount()]; + memcpy(volatileData, orig.constBits(), orig.byteCount()); + + QImage dataImage; + if (rw) + dataImage = QImage(volatileData, orig.width(), orig.height(), orig.format()); + else + dataImage = QImage((const uchar *)volatileData, orig.width(), orig.height(), orig.format()); + + if (orig.colorCount()) + dataImage.setColorTable(orig.colorTable()); + + dataSwapped = std::move(dataImage).mirrored(swap_horizontal, swap_vertical); + QVERIFY(!dataSwapped.isNull()); + delete[] volatileData; + } + + QVERIFY2(dataSwapped.constBits() != volatileData, rw ? "non-const" : "const"); + QCOMPARE(dataSwapped, orig.mirrored(swap_horizontal, swap_vertical)); + } + #endif } @@ -2727,16 +2785,24 @@ void tst_QImage::inplaceRgbConversion() static const quint32 readOnlyData[] = { 0xff0102ffU, 0xff0506ffU, 0xff0910ffU, 0xff1314ffU }; quint32 readWriteData[] = { 0xff0102ffU, 0xff0506ffU, 0xff0910ffU, 0xff1314ffU }; - QImage roImage((const uchar *)readOnlyData, 2, 2, format); - QImage roInplaceConverted = std::move(roImage).convertToFormat(dest_format); + QImage roInplaceConverted; + QImage rwInplaceConverted; - QImage rwImage((uchar *)readWriteData, 2, 2, format); - QImage rwInplaceConverted = std::move(rwImage).convertToFormat(dest_format); + { + QImage roImage((const uchar *)readOnlyData, 2, 2, format); + roInplaceConverted = std::move(roImage).convertToFormat(dest_format); + + QImage rwImage((uchar *)readWriteData, 2, 2, format); + rwInplaceConverted = std::move(rwImage).convertToFormat(dest_format); + } QImage roImage2((const uchar *)readOnlyData, 2, 2, format); QImage normalConverted = roImage2.convertToFormat(dest_format); + QVERIFY(roInplaceConverted.constBits() != (const uchar *)readOnlyData); QCOMPARE(normalConverted, roInplaceConverted); + + QVERIFY(rwInplaceConverted.constBits() != (const uchar *)readWriteData); QCOMPARE(normalConverted, rwInplaceConverted); } #endif diff --git a/tests/auto/network/socket/qtcpsocket/BLACKLIST b/tests/auto/network/socket/qtcpsocket/BLACKLIST new file mode 100644 index 00000000000..5fc2589323c --- /dev/null +++ b/tests/auto/network/socket/qtcpsocket/BLACKLIST @@ -0,0 +1,13 @@ +[bindThenResolveHost:first-fail] +windows +[bind:[::]] +windows +[bind:[::]:randomport] +windows +[invalidProxy:socks5-on-http] +windows +[disconnectWhileLookingUp] +windows +[timeoutConnect:ip] +windows +] diff --git a/tests/auto/network/socket/qtcpsocket/test/test.pro b/tests/auto/network/socket/qtcpsocket/test/test.pro index 325abcaab81..3e64b87b53a 100644 --- a/tests/auto/network/socket/qtcpsocket/test/test.pro +++ b/tests/auto/network/socket/qtcpsocket/test/test.pro @@ -21,5 +21,3 @@ win32 { } else { DESTDIR = ../ } - -win32: CONFIG += insignificant_test # Hangs in release builds diff --git a/tests/auto/network/socket/qudpsocket/BLACKLIST b/tests/auto/network/socket/qudpsocket/BLACKLIST index 3e936aebf69..6669b094ce1 100644 --- a/tests/auto/network/socket/qudpsocket/BLACKLIST +++ b/tests/auto/network/socket/qudpsocket/BLACKLIST @@ -1,8 +1,28 @@ [multicast:same bind, group ipv6 address] * -[multicast:valid bind, group ipv6 address] +[multicast] osx -[multicast:dual bind, group ipv6 address] +[writeDatagramToNonExistingPeer] +windows osx -[multicast:same bind, group ipv4 address] +[asyncReadDatagram] +windows osx +[multicastLeaveAfterClose] +osx +[readyRead] +osx +[readyReadForEmptyDatagram] +osx +[echo] +linux +osx +[ipv6Loop] +osx +[loop] +osx +[broadcasting] +osx +[zeroLengthDatagram] +osx + diff --git a/tests/auto/network/socket/qudpsocket/test/test.pro b/tests/auto/network/socket/qudpsocket/test/test.pro index 8ad16c652d0..e4812416dc7 100644 --- a/tests/auto/network/socket/qudpsocket/test/test.pro +++ b/tests/auto/network/socket/qudpsocket/test/test.pro @@ -22,5 +22,3 @@ wince* { } TARGET = tst_qudpsocket - -CONFIG+=insignificant_test # QTBUG-25367, QTBUG-25368 diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp index 17a3f3a4d00..e85c6b99221 100644 --- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp @@ -206,6 +206,7 @@ private slots: void ignoreSslErrorsList(); void ignoreSslErrorsListWithSlot_data(); void ignoreSslErrorsListWithSlot(); + void abortOnSslErrors(); void readFromClosedSocket(); void writeBigChunk(); void blacklistedCertificates(); @@ -248,6 +249,11 @@ protected slots: { socket->ignoreSslErrors(); } + void abortOnErrorSlot() + { + QSslSocket *sock = static_cast(sender()); + sock->abort(); + } void untrustedWorkaroundSlot(const QList &errors) { if (errors.size() == 1 && @@ -2305,6 +2311,27 @@ void tst_QSslSocket::ignoreSslErrorsListWithSlot() QSKIP("Skipping flaky test - See QTBUG-29941"); } +void tst_QSslSocket::abortOnSslErrors() +{ + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; + + SslServer server; + QVERIFY(server.listen()); + + QSslSocket clientSocket; + connect(&clientSocket, SIGNAL(sslErrors(QList)), this, SLOT(abortOnErrorSlot())); + clientSocket.connectToHostEncrypted("127.0.0.1", server.serverPort()); + clientSocket.ignoreSslErrors(); + + QEventLoop loop; + QTimer::singleShot(1000, &loop, SLOT(quit())); + loop.exec(); + + QCOMPARE(clientSocket.state(), QAbstractSocket::UnconnectedState); +} + // make sure a closed socket has no bytesAvailable() // related to https://bugs.webkit.org/show_bug.cgi?id=28016 void tst_QSslSocket::readFromClosedSocket() diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp index be3a86f4de9..078a629df55 100644 --- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp +++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp @@ -228,6 +228,9 @@ private slots: void QTBUG_36211_data() { generic_data("QPSQL"); } void QTBUG_36211(); + void QTBUG_53969_data() { generic_data("QMYSQL"); } + void QTBUG_53969(); + void sqlite_constraint_data() { generic_data("QSQLITE"); } void sqlite_constraint(); @@ -3647,6 +3650,42 @@ void tst_QSqlQuery::QTBUG_36211() } } +void tst_QSqlQuery::QTBUG_53969() +{ + QFETCH( QString, dbName ); + QVector values = QVector() << 10 << 20 << 127 << 128 << 1, tableValues; + QSqlDatabase db = QSqlDatabase::database( dbName ); + CHECK_DATABASE( db ); + tableValues.reserve(values.size()); + if (tst_Databases::getDatabaseType(db) == QSqlDriver::MySqlServer) { + const QString tableName(qTableName("bug53969", __FILE__, db)); + tst_Databases::safeDropTable( db, tableName ); + + QSqlQuery q(db); + QVERIFY_SQL(q, exec(QString("CREATE TABLE %1 (id INT AUTO_INCREMENT PRIMARY KEY, " + "test_number TINYINT(3) UNSIGNED)") + .arg(tableName))); + + QVERIFY_SQL(q, prepare("INSERT INTO " + tableName + " (test_number) VALUES (:value)")); + + QVector::iterator begin = values.begin(), end = values.end(), it; + for (it = begin; it != end; ++it) { + q.bindValue(":value", *it); + QVERIFY_SQL(q, exec()); + } + + QVERIFY_SQL(q, prepare("SELECT test_number FROM " + tableName)); + QVERIFY_SQL(q, exec()); + + while (q.next()) { + bool ok; + tableValues.push_back(q.value(0).toUInt(&ok)); + QVERIFY(ok); + } + QCOMPARE(values, tableValues); + } +} + void tst_QSqlQuery::oraOCINumber() { QFETCH( QString, dbName );