Merge remote-tracking branch 'origin/5.6' into 5.7
Conflicts: .qmake.conf config.tests/unix/nis/nis.cpp mkspecs/unsupported/freebsd-g++/qplatformdefs.h src/corelib/tools/qdatetime.cpp src/corelib/tools/qsimd.cpp src/corelib/tools/qsimd_p.h src/network/access/access.pri src/network/access/qnetworkreplynsurlconnectionimpl.mm src/network/access/qnetworkreplynsurlconnectionimpl_p.h src/plugins/platforms/cocoa/qnsview.mm src/plugins/printsupport/windows/qwindowsprintdevice.cpp tests/auto/corelib/kernel/qobject/tst_qobject.cpp tests/auto/network/access/qnetworkreply/BLACKLIST tests/auto/widgets/widgets/qopenglwidget/BLACKLIST Change-Id: I4b32055bbf922392ef0264fd403405416fffee57
This commit is contained in:
commit
57057f76ad
@ -6,7 +6,10 @@ for(p, QMAKE_LIBDIR_EGL) {
|
||||
|
||||
INCLUDEPATH += $$QMAKE_INCDIR_EGL
|
||||
LIBS += $$QMAKE_LIBS_EGL
|
||||
|
||||
LIBS += -ldrm
|
||||
|
||||
CONFIG += link_pkgconfig
|
||||
!contains(QT_CONFIG, no-pkg-config) {
|
||||
PKGCONFIG += libdrm
|
||||
} else {
|
||||
LIBS += -ldrm
|
||||
}
|
||||
CONFIG -= qt
|
||||
|
2
config.tests/unix/dlopen/dlopen.pro
Normal file
2
config.tests/unix/dlopen/dlopen.pro
Normal file
@ -0,0 +1,2 @@
|
||||
SOURCES = $$PWD/dlopen.cpp
|
||||
CONFIG -= qt dylib
|
@ -1,3 +1,3 @@
|
||||
SOURCES = iconv.cpp
|
||||
CONFIG -= qt dylib
|
||||
mac|mingw|qnx|haiku:LIBS += -liconv
|
||||
mac|mingw|openbsd|qnx|haiku:LIBS += -liconv
|
||||
|
@ -1,3 +1,2 @@
|
||||
SOURCES = libdl.cpp
|
||||
CONFIG -= qt dylib
|
||||
!qnx: LIBS += -ldl
|
||||
include(../dlopen/dlopen.pro)
|
||||
LIBS += -ldl
|
||||
|
@ -41,5 +41,6 @@
|
||||
|
||||
int main(int, char **)
|
||||
{
|
||||
mysql_get_client_version();
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,50 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the config.tests of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://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 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpcsvc/ypclnt.h>
|
||||
#include <rpcsvc/yp_prot.h>
|
||||
|
||||
int main(int, char **)
|
||||
{
|
||||
char *d;
|
||||
yp_get_default_domain(&d);
|
||||
return 0;
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
SOURCES = nis.cpp
|
||||
CONFIG -= qt dylib
|
||||
solaris-*:LIBS += -lnsl
|
||||
else:LIBS += $$QMAKE_LIBS_NIS
|
@ -1,4 +1,7 @@
|
||||
SOURCES = objcopy.cpp
|
||||
CONFIG -= qt
|
||||
TARGET = objcopytest
|
||||
|
||||
QMAKE_POST_LINK += $$QMAKE_OBJCOPY --only-keep-debug objcopy objcopy.debug && $$QMAKE_OBJCOPY --strip-debug objcopy && $$QMAKE_OBJCOPY --add-gnu-debuglink=objcopy.debug objcopy
|
||||
load(resolve_target)
|
||||
|
||||
QMAKE_POST_LINK += $$QMAKE_OBJCOPY --only-keep-debug $$QMAKE_RESOLVED_TARGET objcopytest.debug && $$QMAKE_OBJCOPY --strip-debug $$QMAKE_RESOLVED_TARGET && $$QMAKE_OBJCOPY --add-gnu-debuglink=objcopytest.debug $$QMAKE_RESOLVED_TARGET
|
||||
|
@ -43,6 +43,12 @@
|
||||
# error "OpenSSL >= 0.9.7 is required"
|
||||
#endif
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER-0 >= 0x10002000L && !defined(OPENSSL_NO_EC) && !defined(SSL_CTRL_SET_CURVES)
|
||||
# error "OpenSSL was reported as >= 1.0.2 but is missing required features, possibly it's libressl which is unsupported"
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
}
|
||||
|
57
configure
vendored
57
configure
vendored
@ -719,7 +719,6 @@ CFG_LIBINPUT=auto
|
||||
CFG_OBSOLETE_WAYLAND=no
|
||||
CFG_EVDEV=auto
|
||||
CFG_TSLIB=auto
|
||||
CFG_NIS=auto
|
||||
CFG_CUPS=auto
|
||||
CFG_ICONV=auto
|
||||
CFG_DBUS=auto
|
||||
@ -2052,13 +2051,6 @@ while [ "$#" -gt 0 ]; do
|
||||
UNKNOWN_OPT=yes
|
||||
fi
|
||||
;;
|
||||
nis)
|
||||
if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
|
||||
CFG_NIS="$VAL"
|
||||
else
|
||||
UNKNOWN_OPT=yes
|
||||
fi
|
||||
;;
|
||||
largefile)
|
||||
if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
|
||||
CFG_LARGEFILE="$VAL"
|
||||
@ -2655,9 +2647,6 @@ Additional options:
|
||||
-silent ............ Reduce the build output so that warnings and errors
|
||||
can be seen more easily.
|
||||
|
||||
-no-nis ............ Do not compile NIS support.
|
||||
* -nis ............... Compile NIS support.
|
||||
|
||||
-no-cups ........... Do not compile CUPS support.
|
||||
* -cups .............. Compile CUPS support.
|
||||
Requires cups/cups.h and libcups.so.2.
|
||||
@ -2891,10 +2880,17 @@ if [ -z "$PLATFORM" ]; then
|
||||
PLATFORM=ultrix-g++
|
||||
;;
|
||||
FreeBSD:*)
|
||||
PLATFORM=freebsd-clang
|
||||
PLATFORM_NOTES="
|
||||
- Also available for FreeBSD: freebsd-icc
|
||||
"
|
||||
if [ "$(uname -r | cut -d. -f1)" -ge 10 ]; then
|
||||
PLATFORM=freebsd-clang
|
||||
PLATFORM_NOTES="
|
||||
- Also available for FreeBSD: freebsd-g++
|
||||
"
|
||||
else
|
||||
PLATFORM=freebsd-g++
|
||||
PLATFORM_NOTES="
|
||||
- Also available for FreeBSD: freebsd-clang
|
||||
"
|
||||
fi
|
||||
;;
|
||||
OpenBSD:*)
|
||||
PLATFORM=openbsd-g++
|
||||
@ -3244,6 +3240,9 @@ if [ "$XPLATFORM_ANDROID" = "yes" ]; then
|
||||
if [ "$CFG_DBUS" = "auto" ]; then
|
||||
CFG_DBUS="no"
|
||||
fi
|
||||
if [ "$CFG_EGLFS" = "auto" ]; then
|
||||
CFG_EGLFS="no"
|
||||
fi
|
||||
if [ -z "$CFG_DEFAULT_ANDROID_NDK_HOST" ]; then
|
||||
case $PLATFORM in
|
||||
linux-*)
|
||||
@ -4829,9 +4828,13 @@ if [ "$CFG_LIBPNG" = "auto" ]; then
|
||||
fi
|
||||
|
||||
# detect dl
|
||||
if ! compileTest unix/libdl "libdl"; then
|
||||
QMakeVar add DEFINES QT_NO_DYNAMIC_LIBRARY
|
||||
if compileTest unix/dlopen "dlopen"; then
|
||||
QMAKE_CONFIG="$QMAKE_CONFIG no-libdl"
|
||||
else
|
||||
if ! compileTest unix/libdl "libdl"; then
|
||||
QMAKE_CONFIG="$QMAKE_CONFIG no-libdl"
|
||||
QMakeVar add DEFINES QT_NO_DYNAMIC_LIBRARY
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$CFG_EGLFS" = "yes" ]; then
|
||||
@ -5097,23 +5100,6 @@ for _SQLDR in $CFG_SQL_AVAILABLE; do
|
||||
esac
|
||||
done
|
||||
|
||||
# auto-detect NIS support
|
||||
if [ "$CFG_NIS" != "no" ]; then
|
||||
if compileTest unix/nis "NIS"; then
|
||||
CFG_NIS=yes
|
||||
else
|
||||
if [ "$CFG_NIS" = "yes" ] && [ "$CFG_CONFIGURE_EXIT_ON_ERROR" = "yes" ]; then
|
||||
echo "NIS support cannot be enabled due to functionality tests!"
|
||||
echo " Turn on verbose messaging (-v) to $0 to see the final report."
|
||||
echo " If you believe this message is in error you may use the continue"
|
||||
echo " switch (-continue) to $0 to continue."
|
||||
exit 101
|
||||
else
|
||||
CFG_NIS=no
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# auto-detect CUPS support
|
||||
if [ "$CFG_CUPS" != "no" ]; then
|
||||
if compileTest unix/cups "Cups"; then
|
||||
@ -6585,7 +6571,6 @@ elif [ "$CFG_ZLIB" = "system" ]; then
|
||||
fi
|
||||
|
||||
[ "$CFG_MTDEV" = "yes" ] && QT_CONFIG="$QT_CONFIG mtdev"
|
||||
[ "$CFG_NIS" = "yes" ] && QT_CONFIG="$QT_CONFIG nis"
|
||||
[ "$CFG_CUPS" = "yes" ] && QT_CONFIG="$QT_CONFIG cups"
|
||||
[ "$CFG_ICONV" = "yes" ] && QT_CONFIG="$QT_CONFIG iconv"
|
||||
[ "$CFG_ICONV" = "sun" ] && QT_CONFIG="$QT_CONFIG sun-libiconv"
|
||||
@ -7013,7 +6998,6 @@ QMakeVar set sql-plugins "$SQL_PLUGINS"
|
||||
[ "$CFG_INOTIFY" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_INOTIFY"
|
||||
[ "$CFG_EVENTFD" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_EVENTFD"
|
||||
[ "$CFG_CLOEXEC" = "yes" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_THREADSAFE_CLOEXEC=1"
|
||||
[ "$CFG_NIS" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_NIS"
|
||||
[ "$CFG_OPENSSL" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_OPENSSL"
|
||||
[ "$CFG_OPENSSL" = "linked" ]&& QCONFIG_FLAGS="$QCONFIG_FLAGS QT_LINKED_OPENSSL"
|
||||
[ "$CFG_OPENSSL" = "no" ] && [ "$CFG_SECURETRANSPORT" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_SSL"
|
||||
@ -7480,7 +7464,6 @@ report_support " libproxy.............." "$CFG_LIBPROXY"
|
||||
report_support " OpenSSL .............." "$CFG_OPENSSL" yes "loading libraries at run-time" linked "linked to the libraries"
|
||||
[ "$XPLATFORM_MAC" = "yes" ] && \
|
||||
report_support " SecureTransport ......" "$CFG_SECURETRANSPORT"
|
||||
report_support " NIS ...................." "$CFG_NIS"
|
||||
report_support " OpenGL / OpenVG:"
|
||||
report_support " EGL .................." "$CFG_EGL"
|
||||
report_support " OpenGL ..............." "$CFG_OPENGL" yes "Desktop OpenGL" es2 "OpenGL ES 2.0+"
|
||||
|
165
dist/changes-5.6.1
vendored
Normal file
165
dist/changes-5.6.1
vendored
Normal file
@ -0,0 +1,165 @@
|
||||
Qt 5.6.1 is a bug-fix release. It maintains both forward and backward
|
||||
compatibility (source and binary) with Qt 5.6.0.
|
||||
|
||||
For more details, refer to the online documentation included in this
|
||||
distribution. The documentation is also available online:
|
||||
|
||||
https://doc.qt.io/qt-5/
|
||||
|
||||
The Qt version 5.6 series is binary compatible with the 5.5.x series.
|
||||
Applications compiled for 5.5 will continue to run with 5.6.
|
||||
|
||||
Some of the changes listed in this file include issue tracking numbers
|
||||
corresponding to tasks in the Qt Bug Tracker:
|
||||
|
||||
https://bugreports.qt.io/
|
||||
|
||||
Each of these identifiers can be entered in the bug tracker to obtain more
|
||||
information about a particular change.
|
||||
|
||||
****************************************************************************
|
||||
* Important Behavior Changes *
|
||||
****************************************************************************
|
||||
|
||||
- Support for DirectFB is disabled by default, due to lack of
|
||||
development in upstream. To enable the platform plugin, pass the
|
||||
-directfb option to configure.
|
||||
- [QTBUG-44964] The new X event compression feature that was added in 5.6.0
|
||||
no longer applies to motion events from drawing tablets.
|
||||
|
||||
configure & build system
|
||||
------------------------
|
||||
|
||||
- The configure -D/-I/-L/-l/-R options do not affect the build of Qt's
|
||||
host tools any more when cross-building. While this usually improves
|
||||
the chances of a build succeeding, it may also require adjustments.
|
||||
|
||||
qmake
|
||||
-----
|
||||
|
||||
- [Unix] Paths passed to configure -R are not automatically used by 3rd
|
||||
party projects any more. Use QMAKE_RPATHDIR if your project explicitly
|
||||
depends on external libraries. Note that this is not needed for Qt or
|
||||
its transitive dependencies.
|
||||
- Expansions of ${QMAKE_FILE_IN_BASE} and ${QMAKE_FILE_OUT_BASE} in extra
|
||||
compilers are now automatically quoted.
|
||||
|
||||
****************************************************************************
|
||||
* Library *
|
||||
****************************************************************************
|
||||
|
||||
QtCore
|
||||
------
|
||||
|
||||
- QObject:
|
||||
* [QTBUG-52542] If the compiler supports variadic templates, functors
|
||||
connected to signals will no longer be copied each time the signal is
|
||||
emitted.
|
||||
|
||||
- QRect:
|
||||
* Fixed integer overflow in center(). This fixes the result for some
|
||||
corner-cases such as a 1x1 rectangle at (INT_MIN, INT_MIN), for which the
|
||||
previous implementation could return anything (due to invoking undefined
|
||||
behavior), but commonly returned (0, 0).
|
||||
|
||||
- QStringRef:
|
||||
* Fixed relational operators against (const char*) to return the correct
|
||||
result.
|
||||
|
||||
QtGui
|
||||
-----
|
||||
|
||||
- [QTBUG-50199] QWheelEvent::phase() now returns zero rather than
|
||||
Qt::ScrollUpdate when the wheel event comes from an actual non-emulated
|
||||
mouse wheel, and the QT_ENABLE_MOUSE_WHEEL_TRACKING environment variable
|
||||
is set.
|
||||
|
||||
- Image:
|
||||
* [QTBUG-50745] Fixed possible crash in QImage::pixel() for mono or indexed
|
||||
images.
|
||||
|
||||
QtWidgets
|
||||
---------
|
||||
|
||||
- Dialogs:
|
||||
* [QTBUG-51148] Fixed font dialog support for fonts with a non-existent
|
||||
family name and/or pixel size.
|
||||
|
||||
- QHeaderView:
|
||||
* [QTBUG-50171] Fixed a repainting issue when items had been reordered.
|
||||
|
||||
- QListWidget:
|
||||
* [QTBUG-15741] Fixed a bug that caused the default drop action to be
|
||||
ignored when using icon mode.
|
||||
|
||||
|
||||
****************************************************************************
|
||||
* Platform-specific Changes *
|
||||
****************************************************************************
|
||||
|
||||
Android
|
||||
-------
|
||||
|
||||
- The navigation bar is now hidden only on Android API level 19 and above.
|
||||
|
||||
OS X
|
||||
----
|
||||
- [QTBUG-50262] QStandardPaths now returns the correct display name for the
|
||||
download folder.
|
||||
- [QTBUG-7000] QMacPrintEngine now really sets the printer resolution.
|
||||
- [QTBUG-48138] QPinchGesture on OS X now behaves like on other platforms:
|
||||
totalScaleFactor is the magnitude of the pinch and scaleFactor is the delta
|
||||
for the current event.
|
||||
|
||||
Windows
|
||||
-------
|
||||
|
||||
- Text:
|
||||
* [QTBUG-18711] Fixed disabling hints for application fonts.
|
||||
For example, when automatic scaling by device pixel ratio is in effect.
|
||||
* [QTBUG-47141] Made it possible to disable antialiasing for text when
|
||||
drawing into images.
|
||||
|
||||
X11/XCB
|
||||
-------
|
||||
|
||||
- [QTBUG-49071] Fixed failure to deliver focusIn events on hide/show.
|
||||
|
||||
****************************************************************************
|
||||
* Tools *
|
||||
****************************************************************************
|
||||
|
||||
configure & build system
|
||||
------------------------
|
||||
|
||||
- [QTBUG-11545][Windows] Added missing -pch/-no-pch options to configure.exe.
|
||||
- [QTBUG-37952][Apple] configure -separate-debug-info is now supported.
|
||||
- [QTBUG-47313][QTBUG-47639] Fixed builds with "debug" and/or "release" in
|
||||
the build path's name.
|
||||
- [QTBUG-51621][Unix] Fixed transitive dependencies on non-Qt libraries.
|
||||
- [QTBUG-51644][QTBUG-53017] Fixed cross-builds which use a host compiler
|
||||
which is significantly different from the target compiler.
|
||||
- [QTBUG-52578][QNX] Unified some defaults between the Unix and Windows
|
||||
configures.
|
||||
- [Unix] configure -R now supports paths relative to -libdir.
|
||||
- [Android@Windows] Added missing -android-ndk-host option to configure.exe.
|
||||
- [MinGW] Fixed -release -force-debug-info builds actually being neither.
|
||||
- [WinCE] Fixed (Open)SSL detection.
|
||||
- Fixed builds with static libc.
|
||||
|
||||
qmake
|
||||
-----
|
||||
|
||||
- [QTBUG-34182] Fixed UTF-8 BOM breaking dependency calculation.
|
||||
- [QTBUG-38802][WinRT] Capabilities needed by Qt are now automatically
|
||||
added to the manifest.
|
||||
- [QTBUG-50924][WEC7][VS] Fixed deployment of Qt.
|
||||
- [QTBUG-51775][Unix@Windows] Fixed installation of target.targets when
|
||||
cross-building.
|
||||
- [QTBUG-51782] Fixed simultaneous use of the separate_debug_info and
|
||||
no_plugin_name_prefix CONFIG flags.
|
||||
- [QTBUG-52008] qmake-generated Visual Studio projects now automatically
|
||||
invoke windeployqt by default.
|
||||
- [QTBUG-52998] Restored use of -P option when invoking lex.
|
||||
- The expansions ${QMAKE_FILE_IN_EXT}, ${QMAKE_FILE_IN_NAME}, and
|
||||
${QMAKE_FILE_OUT_PATH} are now understood in extra compilers.
|
@ -56,9 +56,9 @@
|
||||
#include "ui_authenticationdialog.h"
|
||||
|
||||
#ifndef QT_NO_SSL
|
||||
static const char defaultUrl[] = "https://qt-project.org/";
|
||||
static const char defaultUrl[] = "https://www.qt.io/";
|
||||
#else
|
||||
static const char defaultUrl[] = "http://qt-project.org/";
|
||||
static const char defaultUrl[] = "http://www.qt.io/";
|
||||
#endif
|
||||
static const char defaultFileName[] = "index.html";
|
||||
|
||||
@ -106,7 +106,7 @@ HttpWindow::HttpWindow(QWidget *parent)
|
||||
connect(urlLineEdit, &QLineEdit::textChanged,
|
||||
this, &HttpWindow::enableDownloadButton);
|
||||
formLayout->addRow(tr("&URL:"), urlLineEdit);
|
||||
QString downloadDirectory = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
|
||||
QString downloadDirectory = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
|
||||
if (downloadDirectory.isEmpty() || !QFileInfo(downloadDirectory).isDir())
|
||||
downloadDirectory = QDir::currentPath();
|
||||
downloadDirectoryLineEdit->setText(QDir::toNativeSeparators(downloadDirectory));
|
||||
|
@ -54,7 +54,8 @@
|
||||
#include <QObject>
|
||||
#include <QColor>
|
||||
|
||||
class QOpenGLFunctions_1_1;
|
||||
QT_FORWARD_DECLARE_CLASS(QOpenGLFunctions_1_1)
|
||||
|
||||
class Patch;
|
||||
struct Geometry;
|
||||
|
||||
|
@ -5,3 +5,6 @@ LIBS += -framework AppKit
|
||||
|
||||
QT += widgets
|
||||
|
||||
# install
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/mac/qmaccocoaviewcontainer
|
||||
INSTALLS += target
|
||||
|
@ -5,3 +5,7 @@ LIBS += -framework AppKit
|
||||
|
||||
QT += widgets
|
||||
#QT += widgets-private gui-private core-private
|
||||
|
||||
# install
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/mac/qmacnativewidget
|
||||
INSTALLS += target
|
||||
|
@ -168,13 +168,6 @@ QMAKE_STRIP =
|
||||
|
||||
QMAKE_RANLIB = $$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-ranlib
|
||||
|
||||
QMAKE_INCDIR = $$ANDROID_SOURCES_CXX_STL_INCDIR $$QMAKE_ANDROID_PLATFORM_INCDIR
|
||||
QMAKE_LIBDIR = $$ANDROID_SOURCES_CXX_STL_LIBDIR $$QMAKE_ANDROID_PLATFORM_LIBDIR $$LIBGCC_PATH
|
||||
QMAKE_INCDIR_X11 =
|
||||
QMAKE_LIBDIR_X11 =
|
||||
QMAKE_INCDIR_OPENGL = $$QMAKE_ANDROID_PLATFORM_INCDIR
|
||||
QMAKE_LIBDIR_OPENGL = $$QMAKE_ANDROID_PLATFORM_LIBDIR
|
||||
|
||||
equals(ANDROID_TARGET_ARCH, armeabi)|equals(ANDROID_TARGET_ARCH, armeabi-v7a): \
|
||||
LIBGCC_PATH_FULL = $$system("$$QMAKE_CC -mthumb-interwork -print-libgcc-file-name")
|
||||
else: \
|
||||
@ -182,20 +175,19 @@ else: \
|
||||
|
||||
LIBGCC_PATH = $$dirname(LIBGCC_PATH_FULL)
|
||||
|
||||
QMAKE_INCDIR = $$ANDROID_SOURCES_CXX_STL_INCDIR $$QMAKE_ANDROID_PLATFORM_INCDIR
|
||||
QMAKE_LIBDIR = $$ANDROID_SOURCES_CXX_STL_LIBDIR $$QMAKE_ANDROID_PLATFORM_LIBDIR $$LIBGCC_PATH
|
||||
QMAKE_INCDIR_X11 =
|
||||
QMAKE_LIBDIR_X11 =
|
||||
QMAKE_INCDIR_OPENGL = $$QMAKE_ANDROID_PLATFORM_INCDIR
|
||||
QMAKE_LIBDIR_OPENGL = $$QMAKE_ANDROID_PLATFORM_LIBDIR
|
||||
|
||||
QMAKE_LINK = $$QMAKE_CXX
|
||||
QMAKE_LINK_SHLIB = $$QMAKE_CXX
|
||||
QMAKE_LFLAGS = --sysroot=$$ANDROID_PLATFORM_ROOT_PATH
|
||||
QMAKE_RPATHLINK = $$QMAKE_ANDROID_PLATFORM_LIBDIR
|
||||
QMAKE_LFLAGS_APP = -Wl,--no-undefined -Wl,-z,noexecstack -shared
|
||||
QMAKE_LFLAGS_SHLIB = -Wl,--no-undefined -Wl,-z,noexecstack -shared
|
||||
|
||||
contains(NDK_ROOT, ".*r6")|contains(NDK_ROOT, ".*r5.*") {
|
||||
!equals(ANDROID_PLATFORM, android-4):!equals(ANDROID_PLATFORM, android-5):!equals(ANDROID_PLATFORM, android-8) {
|
||||
warning("Your NDK version is outdated. A workaround is enabled. Consider updating your NDK (workarounds are required until r6(a))")
|
||||
QMAKE_LFLAGS_SHLIB += $$QMAKE_ANDROID_PLATFORM_LIBDIR/crtbegin_so.o $$QMAKE_ANDROID_PLATFORM_LIBDIR/crtend_so.o
|
||||
}
|
||||
}
|
||||
|
||||
QMAKE_LFLAGS_PLUGIN = $$QMAKE_LFLAGS_SHLIB
|
||||
QMAKE_LFLAGS_NOUNDEF = -Wl,--no-undefined
|
||||
QMAKE_LFLAGS_RPATH = -Wl,-rpath=
|
||||
|
@ -1,3 +1,3 @@
|
||||
contains(QT_CONFIG, system-freetype) {
|
||||
LIBS += -lfreetype
|
||||
LIBS_PRIVATE += -lfreetype
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
CONFIG += qpa/basicunixfontdatabase
|
||||
contains(QT_CONFIG, fontconfig) {
|
||||
DEFINES += Q_FONTCONFIGDATABASE
|
||||
LIBS += -lfontconfig
|
||||
LIBS_PRIVATE += -lfontconfig
|
||||
} else:!android {
|
||||
fonts.path = $$[QT_INSTALL_LIBS]/fonts
|
||||
fonts.files = $$QT_SOURCE_TREE/lib/fonts/*
|
||||
|
18
mkspecs/features/win32/separate_debug_info.prf
Normal file
18
mkspecs/features/win32/separate_debug_info.prf
Normal file
@ -0,0 +1,18 @@
|
||||
have_target:!static:!isEmpty(QMAKE_OBJCOPY) {
|
||||
load(resolve_target)
|
||||
QMAKE_TARGET_DEBUG_INFO = $${QMAKE_RESOLVED_TARGET}.debug
|
||||
|
||||
shell_target = $$shell_quote($$relative_path($$QMAKE_RESOLVED_TARGET, $$OUT_PWD))
|
||||
shell_target_debug_info = $$shell_quote($$relative_path($$QMAKE_TARGET_DEBUG_INFO, $$OUT_PWD))
|
||||
copy_debug_info = $$QMAKE_OBJCOPY --only-keep-debug $$shell_target $$shell_target_debug_info
|
||||
link_debug_info = $$QMAKE_OBJCOPY --add-gnu-debuglink=$$shell_target_debug_info $$shell_target
|
||||
strip_debug_info = $$QMAKE_OBJCOPY --strip-debug $$shell_target
|
||||
|
||||
!isEmpty(QMAKE_POST_LINK):QMAKE_POST_LINK = $$escape_expand(\\n\\t)$$QMAKE_POST_LINK
|
||||
|
||||
QMAKE_POST_LINK = $$copy_debug_info && $$strip_debug_info && $$link_debug_info $$QMAKE_POST_LINK
|
||||
silent:QMAKE_POST_LINK = @echo creating $@.debug && $$QMAKE_POST_LINK
|
||||
|
||||
target.targets += $$QMAKE_TARGET_DEBUG_INFO
|
||||
QMAKE_DISTCLEAN += $$QMAKE_TARGET_DEBUG_INFO
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
MAKEFILE_GENERATOR = UNIX
|
||||
QMAKE_PLATFORM = freebsd bsd
|
||||
|
||||
include(../../common/unix.conf)
|
||||
include(../common/unix.conf)
|
||||
|
||||
QMAKE_CFLAGS_THREAD = -pthread -D_THREAD_SAFE
|
||||
|
||||
@ -29,6 +29,6 @@ QMAKE_OBJCOPY = objcopy
|
||||
QMAKE_NM = nm -P
|
||||
QMAKE_RANLIB =
|
||||
|
||||
include(../../common/gcc-base-unix.conf)
|
||||
include(../../common/g++-unix.conf)
|
||||
include(../common/gcc-base-unix.conf)
|
||||
include(../common/g++-unix.conf)
|
||||
load(qt_config)
|
@ -37,4 +37,4 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "../freebsd-g++/qplatformdefs.h"
|
||||
#include "../freebsd-clang/qplatformdefs.h"
|
@ -1,95 +0,0 @@
|
||||
#
|
||||
# qmake configuration for freebsd-icc
|
||||
#
|
||||
# Written for Intel C++ 7.1 and 8.0 on FreeBSD
|
||||
#
|
||||
# Note: Some of the remarks from the Intel compiler are disabled (even
|
||||
# with 'warn_on' specified):
|
||||
#
|
||||
# remark #171: invalid type conversion: "int" to "void *"
|
||||
# remark #193: zero used for undefined preprocessing identifier
|
||||
# remark #279: controlling expression is constant
|
||||
# remark #304: access control not specified ("public" by default)
|
||||
# remark #310: old-style parameter list (anachronism)
|
||||
# remark #383: value copied to temporary, reference to temporary used
|
||||
# remark #424: extra ";" ignored
|
||||
# remark #444: destructor for base class "Class" is not virtual
|
||||
# remark #488: template parameter "T" is not used in declaring the parameter
|
||||
# types of function template "function"
|
||||
# remark #810: conversion from "type1" to "type2" may loose significant bits
|
||||
# remark #858: type qualifier on return type is meaningless
|
||||
# remark #967: conversion from "type1" to "type2"; sizes do not match
|
||||
# remark #981: operands are evaluated in unspecified order
|
||||
# remark #1418: external definition with no prior declaration
|
||||
# remark #1419: external declaration in primary source file
|
||||
# warning #1476: field uses tail padding of a base class
|
||||
# warning #1477: GNU C++ compilers may use bit field padding
|
||||
# warning #1572: floating-point equality and inequality comparisons are unreliable
|
||||
#
|
||||
|
||||
MAKEFILE_GENERATOR = UNIX
|
||||
QMAKE_PLATFORM = freebsd bsd
|
||||
|
||||
include(../common/unix.conf)
|
||||
|
||||
QMAKE_COMPILER = gcc intel_icc # icc pretends to be gcc
|
||||
|
||||
QMAKE_CC = icc
|
||||
QMAKE_LEX = flex
|
||||
QMAKE_LEXFLAGS =
|
||||
QMAKE_YACC = yacc
|
||||
QMAKE_YACCFLAGS = -d
|
||||
QMAKE_CFLAGS = -wd858,1572
|
||||
QMAKE_CFLAGS_DEPS = -M
|
||||
QMAKE_CFLAGS_WARN_ON = -w2 -wd171,193,279,304,310,383,424,444,488,810,967,981,1418,1419,1476,1477
|
||||
QMAKE_CFLAGS_WARN_OFF = -w
|
||||
QMAKE_CFLAGS_RELEASE =
|
||||
QMAKE_CFLAGS_DEBUG = -g
|
||||
QMAKE_CFLAGS_SHLIB = -fpic
|
||||
QMAKE_CFLAGS_STATIC_LIB = $$QMAKE_CFLAGS_SHLIB
|
||||
QMAKE_CFLAGS_YACC =
|
||||
QMAKE_CFLAGS_THREAD = -D_THREAD_SAFE
|
||||
|
||||
QMAKE_CXX = icpc
|
||||
QMAKE_CXXFLAGS = $$QMAKE_CFLAGS
|
||||
QMAKE_CXXFLAGS_DEPS = $$QMAKE_CFLAGS_DEPS
|
||||
QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON
|
||||
QMAKE_CXXFLAGS_WARN_OFF = $$QMAKE_CFLAGS_WARN_OFF
|
||||
QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE
|
||||
QMAKE_CXXFLAGS_DEBUG = $$QMAKE_CFLAGS_DEBUG
|
||||
QMAKE_CXXFLAGS_SHLIB = $$QMAKE_CFLAGS_SHLIB
|
||||
QMAKE_CXXFLAGS_STATIC_LIB = $$QMAKE_CFLAGS_STATIC_LIB
|
||||
QMAKE_CXXFLAGS_YACC = $$QMAKE_CFLAGS_YACC
|
||||
QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD
|
||||
|
||||
# Addon software goes into /usr/local on the BSDs, by default we will look there
|
||||
QMAKE_INCDIR = /usr/local/include
|
||||
QMAKE_LIBDIR = /usr/local/lib
|
||||
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_LINK = icpc
|
||||
QMAKE_LINK_SHLIB = icpc
|
||||
QMAKE_LFLAGS =
|
||||
QMAKE_LFLAGS_RELEASE =
|
||||
QMAKE_LFLAGS_DEBUG =
|
||||
QMAKE_LFLAGS_SHLIB = -shared
|
||||
QMAKE_LFLAGS_PLUGIN = $$QMAKE_LFLAGS_SHLIB
|
||||
QMAKE_LFLAGS_SONAME = -Qoption,ld,-soname,
|
||||
QMAKE_LFLAGS_THREAD = -mt
|
||||
QMAKE_LFLAGS_RPATH = -Qoption,ld,-rpath,
|
||||
|
||||
QMAKE_LIBS =
|
||||
QMAKE_LIBS_DYNLOAD =
|
||||
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)
|
@ -61,6 +61,7 @@ QMAKE_LFLAGS_RPATH = -Wl,-rpath,
|
||||
|
||||
QMAKE_LIBS =
|
||||
QMAKE_LIBS_DYNLOAD =
|
||||
QMAKE_LIBS_EXECINFO = -lexecinfo
|
||||
QMAKE_LIBS_X11 = -lXext -lX11 -lm
|
||||
QMAKE_LIBS_OPENGL = -lGL
|
||||
QMAKE_LIBS_THREAD =
|
||||
|
@ -62,6 +62,7 @@ QMAKE_LFLAGS_NOUNDEF = -Wl,-no_unresolved
|
||||
|
||||
QMAKE_LIBS =
|
||||
QMAKE_LIBS_DYNLOAD =
|
||||
QMAKE_LIBS_EXECINFO = -lexecinfo
|
||||
QMAKE_LIBS_X11 = -lXext -lX11 -lm
|
||||
QMAKE_LIBS_OPENGL = -lGL
|
||||
QMAKE_LIBS_THREAD =
|
||||
|
@ -1,40 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the qmake spec of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://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 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "../../freebsd-clang/qplatformdefs.h"
|
@ -1616,6 +1616,13 @@
|
||||
\note Platform-specific variables that change the extension override
|
||||
the contents of this variable.
|
||||
|
||||
\target QMAKE_EXTENSION_STATICLIB
|
||||
\section1 QMAKE_EXTENSION_STATICLIB
|
||||
|
||||
Contains the extension for shared static libraries. The value of
|
||||
this variable is typically handled by qmake or
|
||||
\l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified.
|
||||
|
||||
\section1 QMAKE_EXT_MOC
|
||||
|
||||
Contains the extension used on included moc files.
|
||||
|
46
src/3rdparty/forkfd/forkfd.c
vendored
46
src/3rdparty/forkfd/forkfd.c
vendored
@ -30,6 +30,9 @@
|
||||
#include "forkfd.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#if defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/wait.h>
|
||||
@ -65,7 +68,9 @@
|
||||
# undef HAVE_WAITID
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__) && defined(__FreeBSD_version) && __FreeBSD_version >= 1000032
|
||||
#if (defined(__FreeBSD__) && defined(__FreeBSD_version) && __FreeBSD_version >= 1000032) || \
|
||||
(defined(__OpenBSD__) && OpenBSD >= 201505) || \
|
||||
(defined(__NetBSD__) && __NetBSD_Version__ >= 600000000)
|
||||
# define HAVE_PIPE2 1
|
||||
#endif
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) || \
|
||||
@ -410,6 +415,26 @@ chain_handler:
|
||||
old_sigaction.sa_handler(signum);
|
||||
}
|
||||
|
||||
static void ignore_sigpipe()
|
||||
{
|
||||
#ifdef O_NOSIGPIPE
|
||||
static ffd_atomic_int done = FFD_ATOMIC_INIT(0);
|
||||
if (ffd_atomic_load(&done, FFD_ATOMIC_RELAXED))
|
||||
return;
|
||||
#endif
|
||||
|
||||
struct sigaction action;
|
||||
memset(&action, 0, sizeof action);
|
||||
sigemptyset(&action.sa_mask);
|
||||
action.sa_handler = SIG_IGN;
|
||||
action.sa_flags = 0;
|
||||
sigaction(SIGPIPE, &action, NULL);
|
||||
|
||||
#ifdef O_NOSIGPIPE
|
||||
ffd_atomic_store(&done, 1, FFD_ATOMIC_RELAXED);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void forkfd_initialize()
|
||||
{
|
||||
#if defined(HAVE_BROKEN_WAITID)
|
||||
@ -446,6 +471,11 @@ static void forkfd_initialize()
|
||||
*/
|
||||
sigaction(SIGCHLD, &action, &old_sigaction);
|
||||
|
||||
#ifndef O_NOSIGPIPE
|
||||
/* disable SIGPIPE too */
|
||||
ignore_sigpipe();
|
||||
#endif
|
||||
|
||||
#ifndef __GNUC__
|
||||
atexit(cleanup);
|
||||
#endif
|
||||
@ -486,13 +516,23 @@ static void cleanup()
|
||||
|
||||
static int create_pipe(int filedes[], int flags)
|
||||
{
|
||||
int ret;
|
||||
int ret = -1;
|
||||
#ifdef HAVE_PIPE2
|
||||
/* use pipe2(2) whenever possible, since it can thread-safely create a
|
||||
* cloexec pair of pipes. Without it, we have a race condition setting
|
||||
* FD_CLOEXEC
|
||||
*/
|
||||
ret = pipe2(filedes, O_CLOEXEC);
|
||||
|
||||
# ifdef O_NOSIGPIPE
|
||||
/* try first with O_NOSIGPIPE */
|
||||
ret = pipe2(filedes, O_CLOEXEC | O_NOSIGPIPE);
|
||||
if (ret == -1) {
|
||||
/* O_NOSIGPIPE not supported, ignore SIGPIPE */
|
||||
ignore_sigpipe();
|
||||
}
|
||||
# endif
|
||||
if (ret == -1)
|
||||
ret = pipe2(filedes, O_CLOEXEC);
|
||||
if (ret == -1)
|
||||
return ret;
|
||||
|
||||
|
@ -28,8 +28,9 @@ SOURCES += \
|
||||
global/qmalloc.cpp \
|
||||
global/qnumeric.cpp \
|
||||
global/qlogging.cpp \
|
||||
global/qhooks.cpp \
|
||||
global/qversiontagging.cpp
|
||||
global/qhooks.cpp
|
||||
|
||||
VERSIONTAGGING_SOURCES = global/qversiontagging.cpp
|
||||
|
||||
# qlibraryinfo.cpp includes qconfig.cpp
|
||||
INCLUDEPATH += $$QT_BUILD_TREE/src/corelib/global
|
||||
@ -63,3 +64,21 @@ journald {
|
||||
syslog {
|
||||
DEFINES += QT_USE_SYSLOG
|
||||
}
|
||||
|
||||
gcc:ltcg {
|
||||
versiontagging_compiler.commands = $$QMAKE_CXX -c $(CXXFLAGS) $(INCPATH)
|
||||
|
||||
# Disable LTO, as the symbols disappear somehow under GCC
|
||||
versiontagging_compiler.commands += -fno-lto
|
||||
|
||||
versiontagging_compiler.commands += -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN}
|
||||
versiontagging_compiler.dependency_type = TYPE_C
|
||||
versiontagging_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)}
|
||||
versiontagging_compiler.input = VERSIONTAGGING_SOURCES
|
||||
versiontagging_compiler.variable_out = OBJECTS
|
||||
versiontagging_compiler.name = compiling[versiontagging] ${QMAKE_FILE_IN}
|
||||
silent: versiontagging_compiler.commands = @echo compiling[versiontagging] ${QMAKE_FILE_IN} && $$versiontagging_compiler.commands
|
||||
QMAKE_EXTRA_COMPILERS += versiontagging_compiler
|
||||
} else {
|
||||
SOURCES += $$VERSIONTAGGING_SOURCES
|
||||
}
|
||||
|
@ -756,7 +756,9 @@
|
||||
# define Q_COMPILER_TEMPLATE_ALIAS
|
||||
# endif
|
||||
# if __has_feature(cxx_thread_local)
|
||||
# define Q_COMPILER_THREAD_LOCAL
|
||||
# if !defined(__FreeBSD__) /* FreeBSD clang fails on __cxa_thread_atexit */
|
||||
# define Q_COMPILER_THREAD_LOCAL
|
||||
# endif
|
||||
# endif
|
||||
# if __has_feature(cxx_user_literals)
|
||||
# define Q_COMPILER_UDL
|
||||
@ -1114,7 +1116,8 @@
|
||||
# define Q_DECL_NOTHROW Q_DECL_NOEXCEPT
|
||||
#endif
|
||||
|
||||
#if defined(Q_COMPILER_ALIGNOF) && !defined(Q_ALIGNOF)
|
||||
#if defined(Q_COMPILER_ALIGNOF)
|
||||
# undef Q_ALIGNOF
|
||||
# define Q_ALIGNOF(x) alignof(x)
|
||||
#endif
|
||||
|
||||
|
@ -49,6 +49,11 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
#ifdef __has_builtin
|
||||
# define QT_HAS_BUILTIN(x) __has_builtin(x)
|
||||
#else
|
||||
# define QT_HAS_BUILTIN(x) 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ENDIAN FUNCTIONS
|
||||
@ -71,18 +76,29 @@ template <typename T> inline void qbswap(const T src, uchar *dest)
|
||||
|
||||
// Used to implement a type-safe and alignment-safe copy operation
|
||||
// If you want to avoid the memcpy, you must write specializations for these functions
|
||||
template <typename T> inline void qToUnaligned(const T src, uchar *dest)
|
||||
template <typename T> Q_ALWAYS_INLINE void qToUnaligned(const T src, uchar *dest)
|
||||
{
|
||||
// Using sizeof(T) inside memcpy function produces internal compiler error with
|
||||
// MSVC2008/ARM in tst_endian -> use extra indirection to resolve size of T.
|
||||
const size_t size = sizeof(T);
|
||||
memcpy(dest, &src, size);
|
||||
#if QT_HAS_BUILTIN(__builtin_memcpy)
|
||||
__builtin_memcpy
|
||||
#else
|
||||
memcpy
|
||||
#endif
|
||||
(dest, &src, size);
|
||||
}
|
||||
template <typename T> inline T qFromUnaligned(const uchar *src)
|
||||
|
||||
template <typename T> Q_ALWAYS_INLINE T qFromUnaligned(const uchar *src)
|
||||
{
|
||||
T dest;
|
||||
const size_t size = sizeof(T);
|
||||
memcpy(&dest, src, size);
|
||||
#if QT_HAS_BUILTIN(__builtin_memcpy)
|
||||
__builtin_memcpy
|
||||
#else
|
||||
memcpy
|
||||
#endif
|
||||
(&dest, src, size);
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,29 @@
|
||||
little and big endian representations of numbers.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\internal
|
||||
\fn T qFromUnaligned(const uchar *ptr)
|
||||
\since 5.5
|
||||
|
||||
Loads a \c{T} from address \a ptr, which may be misaligned.
|
||||
|
||||
Use of this function avoids the undefined behavior that the C++ standard
|
||||
otherwise attributes to unaligned loads.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\internal
|
||||
\fn void qToUnaligned(T t, uchar *ptr)
|
||||
\since 4.5
|
||||
|
||||
Stores \a t to address \a ptr, which may be misaligned.
|
||||
|
||||
Use of this function avoids the undefined behavior that the C++ standard
|
||||
otherwise attributes to unaligned stores.
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\fn T qFromBigEndian(const uchar *src)
|
||||
\since 4.3
|
||||
|
@ -67,6 +67,7 @@
|
||||
NETBSD - NetBSD
|
||||
OPENBSD - OpenBSD
|
||||
BSDI - BSD/OS
|
||||
INTERIX - Interix
|
||||
IRIX - SGI Irix
|
||||
OSF - HP Tru64 UNIX
|
||||
SCO - SCO OpenServer 5
|
||||
@ -172,6 +173,9 @@
|
||||
#elif defined(__bsdi__)
|
||||
# define Q_OS_BSDI
|
||||
# define Q_OS_BSD4
|
||||
#elif defined(__INTERIX)
|
||||
# define Q_OS_INTERIX
|
||||
# define Q_OS_BSD4
|
||||
#elif defined(__sgi)
|
||||
# define Q_OS_IRIX
|
||||
#elif defined(__osf__)
|
||||
|
@ -149,7 +149,6 @@ win32 {
|
||||
SOURCES += io/qsettings_mac.cpp
|
||||
OBJECTIVE_SOURCES += io/qurl_mac.mm
|
||||
}
|
||||
freebsd: LIBS_PRIVATE += -lutil # qlockfile_unix.cpp requires this
|
||||
mac {
|
||||
SOURCES += io/qstorageinfo_mac.cpp
|
||||
OBJECTIVE_SOURCES += io/qstandardpaths_mac.mm
|
||||
|
@ -58,7 +58,7 @@
|
||||
# include "qfilesystemwatcher_win_p.h"
|
||||
#elif defined(USE_INOTIFY)
|
||||
# include "qfilesystemwatcher_inotify_p.h"
|
||||
#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) || defined(Q_OS_IOS)
|
||||
#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) || defined(Q_OS_OPENBSD) || defined(Q_OS_IOS)
|
||||
# include "qfilesystemwatcher_kqueue_p.h"
|
||||
#elif defined(Q_OS_OSX)
|
||||
# include "qfilesystemwatcher_fsevents_p.h"
|
||||
@ -74,7 +74,7 @@ QFileSystemWatcherEngine *QFileSystemWatcherPrivate::createNativeEngine(QObject
|
||||
// there is a chance that inotify may fail on Linux pre-2.6.13 (August
|
||||
// 2005), so we can't just new inotify directly.
|
||||
return QInotifyFileSystemWatcherEngine::create(parent);
|
||||
#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) || defined(Q_OS_IOS)
|
||||
#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) || defined(Q_OS_OPENBSD) || defined(Q_OS_IOS)
|
||||
return QKqueueFileSystemWatcherEngine::create(parent);
|
||||
#elif defined(Q_OS_OSX)
|
||||
return QFseventsFileSystemWatcherEngine::create(parent);
|
||||
|
@ -172,7 +172,6 @@ QStringList QKqueueFileSystemWatcherEngine::removePaths(const QStringList &paths
|
||||
QStringList *files,
|
||||
QStringList *directories)
|
||||
{
|
||||
bool isEmpty;
|
||||
QStringList p = paths;
|
||||
if (pathToID.isEmpty())
|
||||
return p;
|
||||
@ -193,7 +192,6 @@ QStringList QKqueueFileSystemWatcherEngine::removePaths(const QStringList &paths
|
||||
else
|
||||
files->removeAll(path);
|
||||
}
|
||||
isEmpty = pathToID.isEmpty();
|
||||
|
||||
return p;
|
||||
}
|
||||
|
@ -71,14 +71,12 @@
|
||||
#elif defined(Q_OS_HAIKU)
|
||||
# include <kernel/OS.h>
|
||||
#elif defined(Q_OS_BSD4) && !defined(Q_OS_IOS)
|
||||
# if !defined(Q_OS_NETBSD)
|
||||
# include <sys/user.h>
|
||||
# if defined(__GLIBC__) && defined(__FreeBSD_kernel__)
|
||||
# endif
|
||||
# include <sys/cdefs.h>
|
||||
# include <sys/param.h>
|
||||
# include <sys/sysctl.h>
|
||||
# else
|
||||
# include <libutil.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
@ -286,30 +284,33 @@ QString QLockFilePrivate::processNameByPid(qint64 pid)
|
||||
return QString();
|
||||
return QFile::decodeName(info.name);
|
||||
#elif defined(Q_OS_BSD4) && !defined(Q_OS_IOS)
|
||||
# if defined(__GLIBC__) && defined(__FreeBSD_kernel__)
|
||||
int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid };
|
||||
size_t len = 0;
|
||||
if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0)
|
||||
return QString();
|
||||
kinfo_proc *proc = static_cast<kinfo_proc *>(malloc(len));
|
||||
# if defined(Q_OS_NETBSD)
|
||||
struct kinfo_proc2 kp;
|
||||
int mib[6] = { CTL_KERN, KERN_PROC2, KERN_PROC_PID, (int)pid, sizeof(struct kinfo_proc2), 1 };
|
||||
# elif defined(Q_OS_OPENBSD)
|
||||
struct kinfo_proc kp;
|
||||
int mib[6] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, (int)pid, sizeof(struct kinfo_proc), 1 };
|
||||
# else
|
||||
kinfo_proc *proc = kinfo_getproc(pid);
|
||||
struct kinfo_proc kp;
|
||||
int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, (int)pid };
|
||||
# endif
|
||||
if (!proc)
|
||||
size_t len = sizeof(kp);
|
||||
u_int mib_len = sizeof(mib)/sizeof(u_int);
|
||||
|
||||
if (sysctl(mib, mib_len, &kp, &len, NULL, 0) < 0)
|
||||
return QString();
|
||||
# if defined(__GLIBC__) && defined(__FreeBSD_kernel__)
|
||||
if (sysctl(mib, 4, proc, &len, NULL, 0) < 0) {
|
||||
free(proc);
|
||||
|
||||
# if defined(Q_OS_OPENBSD) || defined(Q_OS_NETBSD)
|
||||
if (kp.p_pid != pid)
|
||||
return QString();
|
||||
}
|
||||
if (proc->ki_pid != pid) {
|
||||
free(proc);
|
||||
QString name = QFile::decodeName(kp.p_comm);
|
||||
# else
|
||||
if (kp.ki_pid != pid)
|
||||
return QString();
|
||||
}
|
||||
QString name = QFile::decodeName(kp.ki_comm);
|
||||
# endif
|
||||
QString name = QFile::decodeName(proc->ki_comm);
|
||||
free(proc);
|
||||
return name;
|
||||
|
||||
#else
|
||||
Q_UNUSED(pid);
|
||||
return QString();
|
||||
|
@ -143,9 +143,11 @@ bool QLockFilePrivate::isApparentlyStale() const
|
||||
if (!procHandle)
|
||||
return true;
|
||||
// We got a handle but check if process is still alive
|
||||
DWORD dwR = ::WaitForSingleObject(procHandle, 0);
|
||||
DWORD exitCode = 0;
|
||||
if (!::GetExitCodeProcess(procHandle, &exitCode))
|
||||
exitCode = 0;
|
||||
::CloseHandle(procHandle);
|
||||
if (dwR == WAIT_TIMEOUT)
|
||||
if (exitCode != STILL_ACTIVE)
|
||||
return true;
|
||||
const QString processName = processNameByPid(pid);
|
||||
if (!processName.isEmpty() && processName != appname)
|
||||
|
@ -2097,10 +2097,7 @@ void QProcess::start(const QString &program, const QStringList &arguments, OpenM
|
||||
return;
|
||||
}
|
||||
if (program.isEmpty()) {
|
||||
Q_D(QProcess);
|
||||
d->processError = QProcess::FailedToStart;
|
||||
setErrorString(tr("No program defined"));
|
||||
emit error(d->processError);
|
||||
d->setErrorAndEmit(QProcess::FailedToStart, tr("No program defined"));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2127,10 +2124,7 @@ void QProcess::start(OpenMode mode)
|
||||
return;
|
||||
}
|
||||
if (d->program.isEmpty()) {
|
||||
Q_D(QProcess);
|
||||
d->processError = QProcess::FailedToStart;
|
||||
setErrorString(tr("No program defined"));
|
||||
emit error(d->processError);
|
||||
d->setErrorAndEmit(QProcess::FailedToStart, tr("No program defined"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@
|
||||
# if !defined(ST_RDONLY)
|
||||
# define ST_RDONLY MNT_RDONLY
|
||||
# endif
|
||||
# if !defined(_STATFS_F_FLAGS)
|
||||
# if !defined(_STATFS_F_FLAGS) && !defined(Q_OS_NETBSD)
|
||||
# define _STATFS_F_FLAGS 1
|
||||
# endif
|
||||
#elif defined(Q_OS_ANDROID)
|
||||
|
@ -208,6 +208,8 @@ bool QWindowsPipeWriter::write(const QByteArray &ba)
|
||||
void QWindowsPipeWriter::stop()
|
||||
{
|
||||
stopped = true;
|
||||
bytesWrittenPending = false;
|
||||
pendingBytesWrittenValue = 0;
|
||||
if (writeSequenceStarted) {
|
||||
if (!qt_cancelIo(handle, &overlapped)) {
|
||||
const DWORD dwError = GetLastError();
|
||||
|
@ -410,7 +410,7 @@ public:
|
||||
// pack with itself, we'll discard the high part anyway
|
||||
chunk = _mm_packus_epi16(chunk, chunk);
|
||||
// unaligned 64-bit store
|
||||
qUnalignedStore(l + i, _mm_cvtsi128_si64(chunk));
|
||||
qToUnaligned(_mm_cvtsi128_si64(chunk), l + i);
|
||||
i += 8;
|
||||
}
|
||||
# endif
|
||||
|
@ -275,25 +275,11 @@ QJsonValue::QJsonValue(const QJsonValue &other)
|
||||
*/
|
||||
QJsonValue &QJsonValue::operator =(const QJsonValue &other)
|
||||
{
|
||||
if (t == String && stringData && !stringData->ref.deref())
|
||||
free(stringData);
|
||||
|
||||
t = other.t;
|
||||
dbl = other.dbl;
|
||||
|
||||
if (d != other.d) {
|
||||
|
||||
if (d && !d->ref.deref())
|
||||
delete d;
|
||||
d = other.d;
|
||||
if (d)
|
||||
d->ref.ref();
|
||||
|
||||
}
|
||||
|
||||
if (t == String && stringData)
|
||||
stringData->ref.ref();
|
||||
|
||||
QJsonValue copy(other);
|
||||
// swap(copy);
|
||||
qSwap(dbl, copy.dbl);
|
||||
qSwap(d, copy.d);
|
||||
qSwap(t, copy.t);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -41,16 +41,6 @@
|
||||
#include "qcore_unix_p.h"
|
||||
#include "qelapsedtimer.h"
|
||||
|
||||
#ifdef Q_OS_NACL
|
||||
#elif !defined (Q_OS_VXWORKS)
|
||||
# if !defined(Q_OS_HPUX) || defined(__ia64)
|
||||
# include <sys/select.h>
|
||||
# endif
|
||||
# include <sys/time.h>
|
||||
#else
|
||||
# include <selectLib.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
|
@ -65,6 +65,16 @@
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef Q_OS_NACL
|
||||
#elif !defined (Q_OS_VXWORKS)
|
||||
# if !defined(Q_OS_HPUX) || defined(__ia64)
|
||||
# include <sys/select.h>
|
||||
# endif
|
||||
# include <sys/time.h>
|
||||
#else
|
||||
# include <selectLib.h>
|
||||
#endif
|
||||
|
||||
#include <sys/wait.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
@ -4699,7 +4699,7 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s
|
||||
QOrderedMutexLocker locker(signalSlotLock(sender),
|
||||
signalSlotLock(receiver));
|
||||
|
||||
if (type & Qt::UniqueConnection) {
|
||||
if (type & Qt::UniqueConnection && slot) {
|
||||
QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists;
|
||||
if (connectionLists && connectionLists->count() > signal_index) {
|
||||
const QObjectPrivate::Connection *c2 =
|
||||
|
@ -419,8 +419,7 @@ protected:
|
||||
QScopedPointer<QObjectData> d_ptr;
|
||||
|
||||
static const QMetaObject staticQtMetaObject;
|
||||
friend inline const QMetaObject *qt_getQtMetaObject() Q_DECL_NOEXCEPT
|
||||
{ return &staticQtMetaObject; }
|
||||
friend inline const QMetaObject *qt_getQtMetaObject() Q_DECL_NOEXCEPT;
|
||||
|
||||
friend struct QMetaObject;
|
||||
friend struct QMetaObjectPrivate;
|
||||
@ -451,6 +450,9 @@ inline QMetaObject::Connection QObject::connect(const QObject *asender, const ch
|
||||
const char *amember, Qt::ConnectionType atype) const
|
||||
{ return connect(asender, asignal, this, amember, atype); }
|
||||
|
||||
inline const QMetaObject *qt_getQtMetaObject() Q_DECL_NOEXCEPT
|
||||
{ return &QObject::staticQtMetaObject; }
|
||||
|
||||
#ifndef QT_NO_USERDATA
|
||||
class Q_CORE_EXPORT QObjectUserData {
|
||||
public:
|
||||
|
@ -48,7 +48,6 @@
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QDebug>
|
||||
#include <qendian.h>
|
||||
#include <private/qsimd_p.h> // for qUnalignedLoad
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@ -164,7 +163,7 @@ bool QMimeMagicRule::matchNumber(const QByteArray &data) const
|
||||
const char *p = data.constData() + m_startPos;
|
||||
const char *e = data.constData() + qMin(data.size() - int(sizeof(T)), m_endPos + 1);
|
||||
for ( ; p <= e; ++p) {
|
||||
if ((qUnalignedLoad<T>(p) & mask) == (value & mask))
|
||||
if ((qFromUnaligned<T>(reinterpret_cast<const uchar *>(p)) & mask) == (value & mask))
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include <qalgorithms.h>
|
||||
#include <qdatastream.h>
|
||||
#include <qdebug.h>
|
||||
#include <qendian.h>
|
||||
#include <string.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
@ -169,25 +170,6 @@ QBitArray::QBitArray(int size, bool value)
|
||||
Same as size().
|
||||
*/
|
||||
|
||||
template <typename T> T qUnalignedLoad(const uchar *ptr)
|
||||
{
|
||||
/*
|
||||
* Testing with different compilers shows that they all optimize the memcpy
|
||||
* call away and replace with direct loads whenever possible. On x86 and PPC,
|
||||
* GCC does direct unaligned loads; on MIPS, it generates a pair of load-left
|
||||
* and load-right instructions. ICC and Clang do the same on x86. This is both
|
||||
* 32- and 64-bit.
|
||||
*
|
||||
* On ARM cores without unaligned loads, the compiler leaves a call to
|
||||
* memcpy.
|
||||
*/
|
||||
|
||||
T u;
|
||||
memcpy(&u, ptr, sizeof(u));
|
||||
return u;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
If \a on is true, this function returns the number of
|
||||
1-bits stored in the bit array; otherwise the number
|
||||
@ -203,17 +185,17 @@ int QBitArray::count(bool on) const
|
||||
const quint8 *const end = reinterpret_cast<const quint8 *>(d.end());
|
||||
|
||||
while (bits + 7 <= end) {
|
||||
quint64 v = qUnalignedLoad<quint64>(bits);
|
||||
quint64 v = qFromUnaligned<quint64>(bits);
|
||||
bits += 8;
|
||||
numBits += int(qPopulationCount(v));
|
||||
}
|
||||
if (bits + 3 <= end) {
|
||||
quint32 v = qUnalignedLoad<quint32>(bits);
|
||||
quint32 v = qFromUnaligned<quint32>(bits);
|
||||
bits += 4;
|
||||
numBits += int(qPopulationCount(v));
|
||||
}
|
||||
if (bits + 1 < end) {
|
||||
quint16 v = qUnalignedLoad<quint16>(bits);
|
||||
quint16 v = qFromUnaligned<quint16>(bits);
|
||||
bits += 2;
|
||||
numBits += int(qPopulationCount(v));
|
||||
}
|
||||
|
@ -95,9 +95,29 @@ static SHA3Final * const sha3Final = Final;
|
||||
available on all platforms (MSVC 2008, for example), we #define them to the
|
||||
Qt equivalents.
|
||||
*/
|
||||
|
||||
#ifdef uint64_t
|
||||
#undef uint64_t
|
||||
#endif
|
||||
|
||||
#define uint64_t QT_PREPEND_NAMESPACE(quint64)
|
||||
|
||||
#ifdef uint32_t
|
||||
#undef uint32_t
|
||||
#endif
|
||||
|
||||
#define uint32_t QT_PREPEND_NAMESPACE(quint32)
|
||||
|
||||
#ifdef uint8_t
|
||||
#undef uint8_t
|
||||
#endif
|
||||
|
||||
#define uint8_t QT_PREPEND_NAMESPACE(quint8)
|
||||
|
||||
#ifdef int_least16_t
|
||||
#undef int_least16_t
|
||||
#endif
|
||||
|
||||
#define int_least16_t QT_PREPEND_NAMESPACE(qint16)
|
||||
|
||||
// Header from rfc6234 with 1 modification:
|
||||
|
@ -2180,7 +2180,7 @@ static int qt_timezone()
|
||||
// number of seconds west of UTC.
|
||||
// - It also takes DST into account, so we need to adjust it to always
|
||||
// get the Standard Time offset.
|
||||
return -t.tm_gmtoff + (t.tm_isdst ? SECS_PER_HOUR : 0L);
|
||||
return -t.tm_gmtoff + (t.tm_isdst ? (long)SECS_PER_HOUR : 0L);
|
||||
#elif defined(Q_OS_INTEGRITY)
|
||||
return 0;
|
||||
#else
|
||||
|
@ -58,6 +58,7 @@
|
||||
#include <qbytearray.h>
|
||||
#include <qdatetime.h>
|
||||
#include <qbasicatomic.h>
|
||||
#include <qendian.h>
|
||||
#include <private/qsimd_p.h>
|
||||
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
@ -112,24 +113,24 @@ static uint crc32(const Char *ptr, size_t len, uint h)
|
||||
|
||||
p += 8;
|
||||
for ( ; p <= e; p += 8)
|
||||
h2 = _mm_crc32_u64(h2, qUnalignedLoad<qlonglong>(p - 8));
|
||||
h2 = _mm_crc32_u64(h2, qFromUnaligned<qlonglong>(p - 8));
|
||||
h = h2;
|
||||
p -= 8;
|
||||
|
||||
len = e - p;
|
||||
if (len & 4) {
|
||||
h = _mm_crc32_u32(h, qUnalignedLoad<uint>(p));
|
||||
h = _mm_crc32_u32(h, qFromUnaligned<uint>(p));
|
||||
p += 4;
|
||||
}
|
||||
# else
|
||||
p += 4;
|
||||
for ( ; p <= e; p += 4)
|
||||
h = _mm_crc32_u32(h, qUnalignedLoad<uint>(p - 4));
|
||||
h = _mm_crc32_u32(h, qFromUnaligned<uint>(p - 4));
|
||||
p -= 4;
|
||||
len = e - p;
|
||||
# endif
|
||||
if (len & 2) {
|
||||
h = _mm_crc32_u16(h, qUnalignedLoad<ushort>(p));
|
||||
h = _mm_crc32_u16(h, qFromUnaligned<ushort>(p));
|
||||
p += 2;
|
||||
}
|
||||
if (sizeof(Char) == 1 && len & 1)
|
||||
|
@ -46,9 +46,29 @@
|
||||
available on all platforms (MSVC 2008, for example), we #define them to the
|
||||
Qt equivalents.
|
||||
*/
|
||||
|
||||
#ifdef uint64_t
|
||||
#undef uint64_t
|
||||
#endif
|
||||
|
||||
#define uint64_t QT_PREPEND_NAMESPACE(quint64)
|
||||
|
||||
#ifdef uint32_t
|
||||
#undef uint32_t
|
||||
#endif
|
||||
|
||||
#define uint32_t QT_PREPEND_NAMESPACE(quint32)
|
||||
|
||||
#ifdef uint8_t
|
||||
#undef uint8_t
|
||||
#endif
|
||||
|
||||
#define uint8_t QT_PREPEND_NAMESPACE(quint8)
|
||||
|
||||
#ifdef int_least16_t
|
||||
#undef int_least16_t
|
||||
#endif
|
||||
|
||||
#define int_least16_t QT_PREPEND_NAMESPACE(qint16)
|
||||
|
||||
// Header from rfc6234 with 1 modification:
|
||||
|
@ -751,26 +751,4 @@ void qDumpCPUFeatures()
|
||||
puts("");
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
\fn T qUnalignedLoad(const void *ptr)
|
||||
\since 5.6.1
|
||||
|
||||
Loads a \c{T} from address \a ptr, which may be misaligned.
|
||||
|
||||
Use of this function avoid the undefined behavior that the C++ standard
|
||||
otherwise attributes to unaligned loads.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\internal
|
||||
\fn void qUnalignedStore(void *ptr, T t)
|
||||
\since 5.6.1
|
||||
|
||||
Stores \a t to address \a ptr, which may be misaligned.
|
||||
|
||||
Use of this function avoid the undefined behavior that the C++ standard
|
||||
otherwise attributes to unaligned stores.
|
||||
*/
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -584,7 +584,7 @@ static int ucstrncmp(const QChar *a, const uchar *c, int l)
|
||||
// we'll read uc[offset..offset+7] (16 bytes) and c[offset..offset+7] (8 bytes)
|
||||
if (uc + offset + 7 < e) {
|
||||
// same, but we're using an 8-byte load
|
||||
__m128i chunk = _mm_cvtsi64_si128(qUnalignedLoad<long long>(c + offset));
|
||||
__m128i chunk = _mm_cvtsi64_si128(qFromUnaligned<long long>(c + offset));
|
||||
__m128i secondHalf = _mm_unpacklo_epi8(chunk, nullmask);
|
||||
|
||||
__m128i ucdata = _mm_loadu_si128((const __m128i*)(uc + offset));
|
||||
|
@ -47,6 +47,8 @@
|
||||
|
||||
#include <qdebug.h>
|
||||
|
||||
#include "qlocale_tools_p.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
@ -376,39 +378,126 @@ static QDate calculatePosixDate(const QByteArray &dateRule, int year)
|
||||
}
|
||||
}
|
||||
|
||||
static QTime parsePosixTime(const QByteArray &timeRule)
|
||||
// returns the time in seconds, INT_MIN if we failed to parse
|
||||
static int parsePosixTime(const char *begin, const char *end)
|
||||
{
|
||||
// Format "HH:mm:ss", put check parts count just in case
|
||||
QList<QByteArray> parts = timeRule.split(':');
|
||||
int count = parts.count();
|
||||
if (count == 3)
|
||||
return QTime(parts.at(0).toInt(), parts.at(1).toInt(), parts.at(2).toInt());
|
||||
else if (count == 2)
|
||||
return QTime(parts.at(0).toInt(), parts.at(1).toInt(), 0);
|
||||
else if (count == 1)
|
||||
return QTime(parts.at(0).toInt(), 0, 0);
|
||||
return QTime(2, 0, 0);
|
||||
// Format "hh[:mm[:ss]]"
|
||||
int hour, min = 0, sec = 0;
|
||||
|
||||
// Note that the calls to qstrtoll do *not* check the end pointer, which
|
||||
// means they proceed until they find a non-digit. We check that we're
|
||||
// still in range at the end, but we may have read from past end. It's the
|
||||
// caller's responsibility to ensure that begin is part of a
|
||||
// null-terminated string.
|
||||
|
||||
bool ok = false;
|
||||
hour = qstrtoll(begin, &begin, 10, &ok);
|
||||
if (!ok || hour < 0)
|
||||
return INT_MIN;
|
||||
if (begin < end && *begin == ':') {
|
||||
// minutes
|
||||
++begin;
|
||||
min = qstrtoll(begin, &begin, 10, &ok);
|
||||
if (!ok || min < 0)
|
||||
return INT_MIN;
|
||||
|
||||
if (begin < end && *begin == ':') {
|
||||
// seconds
|
||||
++begin;
|
||||
sec = qstrtoll(begin, &begin, 10, &ok);
|
||||
if (!ok || sec < 0)
|
||||
return INT_MIN;
|
||||
}
|
||||
}
|
||||
|
||||
// we must have consumed everything
|
||||
if (begin != end)
|
||||
return INT_MIN;
|
||||
|
||||
return (hour * 60 + min) * 60 + sec;
|
||||
}
|
||||
|
||||
static int parsePosixOffset(const QByteArray &timeRule)
|
||||
static QTime parsePosixTransitionTime(const QByteArray &timeRule)
|
||||
{
|
||||
// Format "hh[:mm[:ss]]"
|
||||
int value = parsePosixTime(timeRule.constBegin(), timeRule.constEnd());
|
||||
if (value == INT_MIN) {
|
||||
// if we failed to parse, return 02:00
|
||||
return QTime(2, 0, 0);
|
||||
}
|
||||
return QTime::fromMSecsSinceStartOfDay(value * 1000);
|
||||
}
|
||||
|
||||
static int parsePosixOffset(const char *begin, const char *end)
|
||||
{
|
||||
// Format "[+|-]hh[:mm[:ss]]"
|
||||
QList<QByteArray> parts = timeRule.split(':');
|
||||
int count = parts.count();
|
||||
if (count == 3) {
|
||||
int hour = parts.at(0).toInt();
|
||||
int sign = hour >= 0 ? -1 : 1;
|
||||
return sign * ((qAbs(hour) * 60 * 60) + (parts.at(1).toInt() * 60) + parts.at(2).toInt());
|
||||
} else if (count == 2) {
|
||||
int hour = parts.at(0).toInt();
|
||||
int sign = hour >= 0 ? -1 : 1;
|
||||
return sign * ((qAbs(hour) * 60 * 60) + (parts.at(1).toInt() * 60));
|
||||
} else if (count == 1) {
|
||||
int hour = parts.at(0).toInt();
|
||||
int sign = hour >= 0 ? -1 : 1;
|
||||
return sign * (qAbs(hour) * 60 * 60);
|
||||
// note that the sign is inverted because POSIX counts in hours West of GMT
|
||||
bool negate = true;
|
||||
if (*begin == '+') {
|
||||
++begin;
|
||||
} else if (*begin == '-') {
|
||||
negate = false;
|
||||
++begin;
|
||||
}
|
||||
return 0;
|
||||
|
||||
int value = parsePosixTime(begin, end);
|
||||
if (value == INT_MIN)
|
||||
return value;
|
||||
return negate ? -value : value;
|
||||
}
|
||||
|
||||
static inline bool asciiIsLetter(char ch)
|
||||
{
|
||||
ch |= 0x20; // lowercases if it is a letter, otherwise just corrupts ch
|
||||
return ch >= 'a' && ch <= 'z';
|
||||
}
|
||||
|
||||
// Returns the zone name, the offset (in seconds) and advances \a begin to
|
||||
// where the parsing ended. Returns a zone of INT_MIN in case an offset
|
||||
// couldn't be read.
|
||||
static QPair<QString, int> parsePosixZoneNameAndOffset(const char *&pos, const char *end)
|
||||
{
|
||||
static const char offsetChars[] = "0123456789:";
|
||||
QPair<QString, int> result = qMakePair(QString(), INT_MIN);
|
||||
|
||||
const char *nameBegin = pos;
|
||||
const char *nameEnd;
|
||||
Q_ASSERT(pos < end);
|
||||
|
||||
if (*pos == '<') {
|
||||
nameBegin = pos + 1; // skip the '<'
|
||||
nameEnd = nameBegin;
|
||||
while (nameEnd < end && *nameEnd != '>') {
|
||||
// POSIX says only alphanumeric, but we allow anything
|
||||
++nameEnd;
|
||||
}
|
||||
pos = nameEnd + 1; // skip the '>'
|
||||
} else {
|
||||
nameBegin = pos;
|
||||
nameEnd = nameBegin;
|
||||
while (nameEnd < end && asciiIsLetter(*nameEnd))
|
||||
++nameEnd;
|
||||
pos = nameEnd;
|
||||
}
|
||||
if (nameEnd - nameBegin < 3)
|
||||
return result; // name must be at least 3 characters long
|
||||
|
||||
// zone offset, form [+-]hh:mm:ss
|
||||
const char *zoneBegin = pos;
|
||||
const char *zoneEnd = pos;
|
||||
if (zoneEnd < end && (zoneEnd[0] == '+' || zoneEnd[0] == '-'))
|
||||
++zoneEnd;
|
||||
while (zoneEnd < end) {
|
||||
if (strchr(offsetChars, char(*zoneEnd)) == NULL)
|
||||
break;
|
||||
++zoneEnd;
|
||||
}
|
||||
|
||||
result.first = QString::fromUtf8(nameBegin, nameEnd - nameBegin);
|
||||
if (zoneEnd > zoneBegin)
|
||||
result.second = parsePosixOffset(zoneBegin, zoneEnd);
|
||||
pos = zoneEnd;
|
||||
return result;
|
||||
}
|
||||
|
||||
static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArray &posixRule,
|
||||
@ -425,58 +514,45 @@ static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArra
|
||||
|
||||
// POSIX Format is like "TZ=CST6CDT,M3.2.0/2:00:00,M11.1.0/2:00:00"
|
||||
// i.e. "std offset dst [offset],start[/time],end[/time]"
|
||||
// See http://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html
|
||||
// See the section about TZ at http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html
|
||||
QList<QByteArray> parts = posixRule.split(',');
|
||||
|
||||
QString name = QString::fromUtf8(parts.at(0));
|
||||
QString stdName;
|
||||
QString stdOffsetString;
|
||||
QString dstName;
|
||||
QString dstOffsetString;
|
||||
bool parsedStdName = false;
|
||||
bool parsedStdOffset = false;
|
||||
for (int i = 0; i < name.size(); ++i) {
|
||||
if (name.at(i).isLetter()) {
|
||||
if (parsedStdName) {
|
||||
parsedStdOffset = true;
|
||||
dstName.append(name.at(i));
|
||||
} else {
|
||||
stdName.append(name.at(i));
|
||||
QPair<QString, int> stdZone, dstZone;
|
||||
{
|
||||
const QByteArray &zoneinfo = parts.at(0);
|
||||
const char *begin = zoneinfo.constBegin();
|
||||
|
||||
stdZone = parsePosixZoneNameAndOffset(begin, zoneinfo.constEnd());
|
||||
if (stdZone.second == INT_MIN) {
|
||||
stdZone.second = 0; // reset to UTC if we failed to parse
|
||||
} else if (begin < zoneinfo.constEnd()) {
|
||||
dstZone = parsePosixZoneNameAndOffset(begin, zoneinfo.constEnd());
|
||||
if (dstZone.second == INT_MIN) {
|
||||
// if the dst offset isn't provided, it is 1 hour ahead of the standard offset
|
||||
dstZone.second = stdZone.second + (60 * 60);
|
||||
}
|
||||
} else {
|
||||
parsedStdName = true;
|
||||
if (parsedStdOffset)
|
||||
dstOffsetString.append(name.at(i));
|
||||
else
|
||||
stdOffsetString.append(name.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
int utcOffset = parsePosixOffset(stdOffsetString.toUtf8());
|
||||
|
||||
// If only the name part then no transitions
|
||||
if (parts.count() == 1) {
|
||||
QTimeZonePrivate::Data data;
|
||||
data.atMSecsSinceEpoch = lastTranMSecs;
|
||||
data.offsetFromUtc = utcOffset;
|
||||
data.standardTimeOffset = utcOffset;
|
||||
data.offsetFromUtc = stdZone.second;
|
||||
data.standardTimeOffset = stdZone.second;
|
||||
data.daylightTimeOffset = 0;
|
||||
data.abbreviation = stdName;
|
||||
data.abbreviation = stdZone.first;
|
||||
result << data;
|
||||
return result;
|
||||
}
|
||||
|
||||
// If not populated the total dst offset is 1 hour
|
||||
int dstOffset = utcOffset + (60 * 60);
|
||||
if (!dstOffsetString.isEmpty())
|
||||
dstOffset = parsePosixOffset(dstOffsetString.toUtf8());
|
||||
|
||||
// Get the std to dst transtion details
|
||||
QList<QByteArray> dstParts = parts.at(1).split('/');
|
||||
QByteArray dstDateRule = dstParts.at(0);
|
||||
QTime dstTime;
|
||||
if (dstParts.count() > 1)
|
||||
dstTime = parsePosixTime(dstParts.at(1));
|
||||
dstTime = parsePosixTransitionTime(dstParts.at(1));
|
||||
else
|
||||
dstTime = QTime(2, 0, 0);
|
||||
|
||||
@ -485,25 +561,25 @@ static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArra
|
||||
QByteArray stdDateRule = stdParts.at(0);
|
||||
QTime stdTime;
|
||||
if (stdParts.count() > 1)
|
||||
stdTime = parsePosixTime(stdParts.at(1));
|
||||
stdTime = parsePosixTransitionTime(stdParts.at(1));
|
||||
else
|
||||
stdTime = QTime(2, 0, 0);
|
||||
|
||||
for (int year = startYear; year <= endYear; ++year) {
|
||||
QTimeZonePrivate::Data dstData;
|
||||
QDateTime dst(calculatePosixDate(dstDateRule, year), dstTime, Qt::UTC);
|
||||
dstData.atMSecsSinceEpoch = dst.toMSecsSinceEpoch() - (utcOffset * 1000);
|
||||
dstData.offsetFromUtc = dstOffset;
|
||||
dstData.standardTimeOffset = utcOffset;
|
||||
dstData.daylightTimeOffset = dstOffset - utcOffset;
|
||||
dstData.abbreviation = dstName;
|
||||
dstData.atMSecsSinceEpoch = dst.toMSecsSinceEpoch() - (stdZone.second * 1000);
|
||||
dstData.offsetFromUtc = dstZone.second;
|
||||
dstData.standardTimeOffset = stdZone.second;
|
||||
dstData.daylightTimeOffset = dstZone.second - stdZone.second;
|
||||
dstData.abbreviation = dstZone.first;
|
||||
QTimeZonePrivate::Data stdData;
|
||||
QDateTime std(calculatePosixDate(stdDateRule, year), stdTime, Qt::UTC);
|
||||
stdData.atMSecsSinceEpoch = std.toMSecsSinceEpoch() - (dstOffset * 1000);
|
||||
stdData.offsetFromUtc = utcOffset;
|
||||
stdData.standardTimeOffset = utcOffset;
|
||||
stdData.atMSecsSinceEpoch = std.toMSecsSinceEpoch() - (dstZone.second * 1000);
|
||||
stdData.offsetFromUtc = stdZone.second;
|
||||
stdData.standardTimeOffset = stdZone.second;
|
||||
stdData.daylightTimeOffset = 0;
|
||||
stdData.abbreviation = stdName;
|
||||
stdData.abbreviation = stdZone.first;
|
||||
// Part of the high year will overflow
|
||||
if (year == 292278994 && (dstData.atMSecsSinceEpoch < 0 || stdData.atMSecsSinceEpoch < 0)) {
|
||||
if (dstData.atMSecsSinceEpoch > 0) {
|
||||
|
@ -49,7 +49,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
//! [0]
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
QClipboard *clipboard = QGuiApplication::clipboard();
|
||||
QString originalText = clipboard->text();
|
||||
...
|
||||
clipboard->setText(newText);
|
||||
|
@ -289,6 +289,12 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int
|
||||
format = QImage::Format_Mono;
|
||||
}
|
||||
|
||||
if (depth != 32) {
|
||||
ncols = bi.biClrUsed ? bi.biClrUsed : 1 << nbits;
|
||||
if (ncols < 1 || ncols > 256) // sanity check - don't run out of mem if color table is broken
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bi.biHeight < 0)
|
||||
h = -h; // support images with negative height
|
||||
|
||||
@ -296,19 +302,15 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int
|
||||
image = QImage(w, h, format);
|
||||
if (image.isNull()) // could not create image
|
||||
return false;
|
||||
}
|
||||
|
||||
if (depth != 32) {
|
||||
ncols = bi.biClrUsed ? bi.biClrUsed : 1 << nbits;
|
||||
if (ncols < 1 || ncols > 256) // sanity check - don't run out of mem if color table is broken
|
||||
return false;
|
||||
image.setColorCount(ncols);
|
||||
if (ncols)
|
||||
image.setColorCount(ncols); // Ensure valid QImage
|
||||
}
|
||||
|
||||
image.setDotsPerMeterX(bi.biXPelsPerMeter);
|
||||
image.setDotsPerMeterY(bi.biYPelsPerMeter);
|
||||
|
||||
if (ncols > 0) { // read color table
|
||||
image.setColorCount(ncols);
|
||||
uchar rgb[4];
|
||||
int rgb_len = t == BMP_OLD ? 3 : 4;
|
||||
for (int i=0; i<ncols; i++) {
|
||||
|
@ -176,6 +176,9 @@ QImageData::~QImageData()
|
||||
data = 0;
|
||||
}
|
||||
|
||||
#if defined(_M_ARM)
|
||||
#pragma optimize("", off)
|
||||
#endif
|
||||
|
||||
bool QImageData::checkForAlphaPixels() const
|
||||
{
|
||||
@ -290,6 +293,9 @@ bool QImageData::checkForAlphaPixels() const
|
||||
|
||||
return has_alpha_pixels;
|
||||
}
|
||||
#if defined(_M_ARM)
|
||||
#pragma optimize("", on)
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\class QImage
|
||||
|
@ -67,7 +67,7 @@ QT_BEGIN_NAMESPACE
|
||||
Drop}.
|
||||
|
||||
There is a single QClipboard object in an application, accessible
|
||||
as QApplication::clipboard().
|
||||
as QGuiApplication::clipboard().
|
||||
|
||||
Example:
|
||||
\snippet code/src_gui_kernel_qclipboard.cpp 0
|
||||
@ -137,7 +137,7 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
\endlist
|
||||
|
||||
\sa QApplication
|
||||
\sa QGuiApplication
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -147,7 +147,7 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
Do not call this function.
|
||||
|
||||
Call QApplication::clipboard() instead to get a pointer to the
|
||||
Call QGuiApplication::clipboard() instead to get a pointer to the
|
||||
application's global clipboard object.
|
||||
|
||||
There is only one clipboard in the window system, and creating
|
||||
@ -165,7 +165,7 @@ QClipboard::QClipboard(QObject *parent)
|
||||
|
||||
Destroys the clipboard.
|
||||
|
||||
You should never delete the clipboard. QApplication will do this
|
||||
You should never delete the clipboard. QGuiApplication will do this
|
||||
when the application terminates.
|
||||
*/
|
||||
QClipboard::~QClipboard()
|
||||
|
@ -2186,11 +2186,10 @@ void QPainter::setBrushOrigin(const QPointF &p)
|
||||
destination pixel in such a way that the alpha component of the
|
||||
source defines the translucency of the pixel.
|
||||
|
||||
When the paint device is a QImage, the image format must be set to
|
||||
\l {QImage::Format}{Format_ARGB32_Premultiplied} or
|
||||
\l {QImage::Format}{Format_ARGB32} for the composition modes to have
|
||||
any effect. For performance the premultiplied version is the preferred
|
||||
format.
|
||||
Several composition modes require an alpha channel in the source or
|
||||
target images to have an effect. For optimal performance the
|
||||
image format \l {QImage::Format}{Format_ARGB32_Premultiplied} is
|
||||
preferred.
|
||||
|
||||
When a composition mode is set it applies to all painting
|
||||
operator, pens, brushes, gradients and pixmap/image drawing.
|
||||
|
@ -2732,8 +2732,7 @@ void QFontDatabase::load(const QFontPrivate *d, int script)
|
||||
}
|
||||
if (req.pointSize < 0)
|
||||
req.pointSize = req.pixelSize*72.0/d->dpi;
|
||||
if (req.weight == 0)
|
||||
req.weight = QFont::Normal;
|
||||
req.weight = QFont::Normal;
|
||||
if (req.stretch == 0)
|
||||
req.stretch = 100;
|
||||
|
||||
|
@ -1833,8 +1833,7 @@ QFontEngine *QFontEngineMulti::loadEngine(int at)
|
||||
request.family = fallbackFamilyAt(at - 1);
|
||||
|
||||
if (QFontEngine *engine = QFontDatabase::findFont(request, m_script)) {
|
||||
if (request.weight > QFont::Normal)
|
||||
engine->fontDef.weight = request.weight;
|
||||
engine->fontDef.weight = request.weight;
|
||||
if (request.style > QFont::StyleNormal)
|
||||
engine->fontDef.style = request.style;
|
||||
return engine;
|
||||
|
@ -1645,8 +1645,14 @@ void QTextEngine::itemize() const
|
||||
if (analysis->bidiLevel % 2)
|
||||
--analysis->bidiLevel;
|
||||
analysis->flags = QScriptAnalysis::LineOrParagraphSeparator;
|
||||
if (option.flags() & QTextOption::ShowLineAndParagraphSeparators)
|
||||
if (option.flags() & QTextOption::ShowLineAndParagraphSeparators) {
|
||||
const int offset = uc - string;
|
||||
layoutData->string.detach();
|
||||
string = reinterpret_cast<const ushort *>(layoutData->string.unicode());
|
||||
uc = string + offset;
|
||||
e = uc + length;
|
||||
*const_cast<ushort*>(uc) = 0x21B5; // visual line separator
|
||||
}
|
||||
break;
|
||||
case QChar::Tabulation:
|
||||
analysis->flags = QScriptAnalysis::Tab;
|
||||
|
@ -364,9 +364,10 @@ void QTextFormatPrivate::recalcFont() const
|
||||
f.setPixelSize(props.at(i).value.toInt());
|
||||
break;
|
||||
case QTextFormat::FontWeight: {
|
||||
int weight = props.at(i).value.toInt();
|
||||
if (weight == 0) weight = QFont::Normal;
|
||||
f.setWeight(weight);
|
||||
const QVariant weightValue = props.at(i).value;
|
||||
int weight = weightValue.toInt();
|
||||
if (weight >= 0 && weightValue.isValid())
|
||||
f.setWeight(weight);
|
||||
break; }
|
||||
case QTextFormat::FontItalic:
|
||||
f.setItalic(props.at(i).value.toBool());
|
||||
|
@ -431,9 +431,9 @@ public:
|
||||
{ return doubleProperty(FontPointSize); }
|
||||
|
||||
inline void setFontWeight(int weight)
|
||||
{ if (weight == QFont::Normal) weight = 0; setProperty(FontWeight, weight); }
|
||||
{ setProperty(FontWeight, weight); }
|
||||
inline int fontWeight() const
|
||||
{ int weight = intProperty(FontWeight); if (weight == 0) weight = QFont::Normal; return weight; }
|
||||
{ return hasProperty(FontWeight) ? intProperty(FontWeight) : QFont::Normal; }
|
||||
inline void setFontItalic(bool italic)
|
||||
{ setProperty(FontItalic, italic); }
|
||||
inline bool fontItalic() const
|
||||
|
@ -72,14 +72,4 @@ SOURCES += \
|
||||
|
||||
mac: LIBS_PRIVATE += -framework Security
|
||||
|
||||
ios {
|
||||
HEADERS += \
|
||||
access/qnetworkreplynsurlconnectionimpl_p.h
|
||||
|
||||
OBJECTIVE_SOURCES += \
|
||||
access/qnetworkreplynsurlconnectionimpl.mm
|
||||
|
||||
LIBS_PRIVATE += -framework Foundation
|
||||
}
|
||||
|
||||
include($$PWD/../../3rdparty/zlib_dependency.pri)
|
||||
|
@ -331,7 +331,7 @@ bool QHttpNetworkConnectionChannel::ensureConnection()
|
||||
priv->phase = QAuthenticatorPrivate::Start;
|
||||
|
||||
QString connectHost = connection->d_func()->hostName;
|
||||
qint16 connectPort = connection->d_func()->port;
|
||||
quint16 connectPort = connection->d_func()->port;
|
||||
|
||||
#ifndef QT_NO_NETWORKPROXY
|
||||
// HTTPS always use transparent proxy.
|
||||
|
@ -56,10 +56,6 @@
|
||||
#include "qnetworkreplydataimpl_p.h"
|
||||
#include "qnetworkreplyfileimpl_p.h"
|
||||
|
||||
#if defined(Q_OS_IOS) && defined(QT_NO_SSL)
|
||||
#include "qnetworkreplynsurlconnectionimpl_p.h"
|
||||
#endif
|
||||
|
||||
#include "QtCore/qbuffer.h"
|
||||
#include "QtCore/qurl.h"
|
||||
#include "QtCore/qvector.h"
|
||||
@ -1207,12 +1203,6 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
|
||||
}
|
||||
}
|
||||
|
||||
// Use NSURLConnection for https on iOS when OpenSSL is disabled.
|
||||
#if defined(Q_OS_IOS) && defined(QT_NO_SSL)
|
||||
if (scheme == QLatin1String("https"))
|
||||
return new QNetworkReplyNSURLConnectionImpl(this, request, op, outgoingData);
|
||||
#endif
|
||||
|
||||
#ifndef QT_NO_HTTP
|
||||
// Since Qt 5 we use the new QNetworkReplyHttpImpl
|
||||
if (scheme == QLatin1String("http") || scheme == QLatin1String("preconnect-http")
|
||||
|
@ -1,458 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://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 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qnetworkreplynsurlconnectionimpl_p.h"
|
||||
|
||||
#include "QtCore/qdatetime.h"
|
||||
#include <QtCore/qcoreapplication.h>
|
||||
#include <QtCore/qdebug.h>
|
||||
#include <Foundation/Foundation.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
// Network reply implementation using NSUrlConnection.
|
||||
//
|
||||
// Class/object structure:
|
||||
//
|
||||
// QNetworkReplyNSURLConnectionImpl
|
||||
// |- QNetworkReplyNSURLConnectionImplPrivate
|
||||
// |- (bytes read)
|
||||
// |- (QIODevice and CFStream for async POST data transfer)
|
||||
// |- NSURLConnection
|
||||
// |- QtNSURLConnectionDelegate <NSURLConnectionDataDelegate>
|
||||
// |- NSURLResponse/NSHTTPURLResponse
|
||||
// |- (response data)
|
||||
//
|
||||
// The main entry point is the QNetworkReplyNSURLConnectionImpl constructor, which
|
||||
// receives a network request from QNetworkAccessManager. The constructor
|
||||
// creates a NSURLRequest and initiates a NSURLConnection with a QtNSURLConnectionDelegate.
|
||||
// The delegate callbacks are then called asynchronously as the request completes.
|
||||
//
|
||||
|
||||
@class QtNSURLConnectionDelegate;
|
||||
class QNetworkReplyNSURLConnectionImplPrivate: public QNetworkReplyPrivate
|
||||
{
|
||||
public:
|
||||
QNetworkReplyNSURLConnectionImplPrivate();
|
||||
virtual ~QNetworkReplyNSURLConnectionImplPrivate();
|
||||
|
||||
Q_DECLARE_PUBLIC(QNetworkReplyNSURLConnectionImpl)
|
||||
NSURLConnection * urlConnection;
|
||||
QtNSURLConnectionDelegate *urlConnectionDelegate;
|
||||
qint64 bytesRead;
|
||||
|
||||
// Sequental outgiong data streaming
|
||||
QIODevice *outgoingData;
|
||||
CFReadStreamRef readStream;
|
||||
CFWriteStreamRef writeStream;
|
||||
CFIndex transferBufferSize;
|
||||
|
||||
// Forwarding functions to the public class.
|
||||
void setFinished();
|
||||
void setHeader(QNetworkRequest::KnownHeaders header, const QVariant &value);
|
||||
void setRawHeader(const QByteArray &headerName, const QByteArray &value);
|
||||
void setError(QNetworkReply::NetworkError errorCode, const QString &errorString);
|
||||
void setAttribute(QNetworkRequest::Attribute code, const QVariant &value);
|
||||
};
|
||||
|
||||
@interface QtNSURLConnectionDelegate : NSObject
|
||||
{
|
||||
NSURLResponse *response;
|
||||
NSMutableData *responseData;
|
||||
QNetworkReplyNSURLConnectionImplPrivate * replyprivate;
|
||||
}
|
||||
|
||||
- (id)initWithQNetworkReplyNSURLConnectionImplPrivate:(QNetworkReplyNSURLConnectionImplPrivate *)a_replyPrivate ;
|
||||
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_3_0)
|
||||
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
|
||||
#endif
|
||||
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError*)error;
|
||||
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse*)response;
|
||||
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData*)data;
|
||||
- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten
|
||||
totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite;
|
||||
- (NSCachedURLResponse*)connection:(NSURLConnection*)connection willCacheResponse:(NSCachedURLResponse*)cachedResponse;
|
||||
- (NSURLRequest*)connection:(NSURLConnection*)connection willSendRequest:(NSURLRequest*)request redirectResponse:(NSURLResponse*)redirectResponse;
|
||||
- (void)connectionDidFinishLoading:(NSURLConnection*)connection;
|
||||
- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection*)connection;
|
||||
|
||||
@end
|
||||
|
||||
QNetworkReplyNSURLConnectionImplPrivate::QNetworkReplyNSURLConnectionImplPrivate()
|
||||
: QNetworkReplyPrivate()
|
||||
, urlConnection(0)
|
||||
, urlConnectionDelegate(0)
|
||||
, bytesRead(0)
|
||||
, readStream(0)
|
||||
, writeStream(0)
|
||||
, transferBufferSize(4096)
|
||||
{
|
||||
}
|
||||
|
||||
QNetworkReplyNSURLConnectionImplPrivate::~QNetworkReplyNSURLConnectionImplPrivate()
|
||||
{
|
||||
[urlConnection cancel];
|
||||
[urlConnection release];
|
||||
[urlConnectionDelegate release];
|
||||
if (readStream)
|
||||
CFRelease(readStream);
|
||||
if (writeStream)
|
||||
CFRelease(writeStream);
|
||||
}
|
||||
|
||||
void QNetworkReplyNSURLConnectionImplPrivate::setFinished()
|
||||
{
|
||||
q_func()->setFinished(true);
|
||||
QMetaObject::invokeMethod(q_func(), "finished", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void QNetworkReplyNSURLConnectionImplPrivate::setHeader(QNetworkRequest::KnownHeaders header, const QVariant &value)
|
||||
{
|
||||
q_func()->setHeader(header, value);
|
||||
}
|
||||
|
||||
void QNetworkReplyNSURLConnectionImplPrivate::setRawHeader(const QByteArray &headerName, const QByteArray &value)
|
||||
{
|
||||
q_func()->setRawHeader(headerName, value);
|
||||
}
|
||||
|
||||
void QNetworkReplyNSURLConnectionImplPrivate::setError(QNetworkReply::NetworkError errorCode, const QString &errorString)
|
||||
{
|
||||
q_func()->setError(errorCode, errorString);
|
||||
}
|
||||
|
||||
void QNetworkReplyNSURLConnectionImplPrivate::setAttribute(QNetworkRequest::Attribute code, const QVariant &value)
|
||||
{
|
||||
q_func()->setAttribute(code, value);
|
||||
}
|
||||
|
||||
void QNetworkReplyNSURLConnectionImpl::readyReadOutgoingData()
|
||||
{
|
||||
Q_D(QNetworkReplyNSURLConnectionImpl);
|
||||
int bytesRead = 0;
|
||||
do {
|
||||
char data[d->transferBufferSize];
|
||||
bytesRead = d->outgoingData->read(data, d->transferBufferSize);
|
||||
if (bytesRead <= 0)
|
||||
break;
|
||||
CFIndex bytesWritten = CFWriteStreamWrite(d->writeStream, reinterpret_cast<unsigned char *>(data), bytesRead);
|
||||
if (bytesWritten != bytesRead) {
|
||||
CFErrorRef err = CFWriteStreamCopyError(d->writeStream);
|
||||
qWarning() << "QNetworkReplyNSURLConnectionImpl: CFWriteStreamWrite error"
|
||||
<< (err ? QString::number(CFErrorGetCode(err)) : QStringLiteral(""));
|
||||
}
|
||||
} while (bytesRead > 0);
|
||||
|
||||
if (d->outgoingData->atEnd())
|
||||
CFWriteStreamClose(d->writeStream);
|
||||
}
|
||||
|
||||
@interface QtNSURLConnectionDelegate ()
|
||||
|
||||
@property (nonatomic, retain) NSURLResponse* response;
|
||||
@property (nonatomic, retain) NSMutableData* responseData;
|
||||
|
||||
@end
|
||||
|
||||
@implementation QtNSURLConnectionDelegate
|
||||
|
||||
@synthesize response;
|
||||
@synthesize responseData;
|
||||
|
||||
- (id)initWithQNetworkReplyNSURLConnectionImplPrivate:(QNetworkReplyNSURLConnectionImplPrivate *)a_replyPrivate
|
||||
{
|
||||
if (self = [super init])
|
||||
replyprivate = a_replyPrivate;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[response release];
|
||||
[responseData release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_3_0)
|
||||
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
|
||||
{
|
||||
Q_UNUSED(connection)
|
||||
Q_UNUSED(challenge)
|
||||
|
||||
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
|
||||
SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
|
||||
SecTrustResultType resultType;
|
||||
SecTrustEvaluate(serverTrust, &resultType);
|
||||
if (resultType == kSecTrustResultUnspecified) {
|
||||
// All good
|
||||
[challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge];
|
||||
} else if (resultType == kSecTrustResultRecoverableTrustFailure) {
|
||||
// Certificate verification error, ask user
|
||||
// ### TODO actually ask user
|
||||
// (test site: https://testssl-expire.disig.sk/index.en.html)
|
||||
qWarning() << "QNetworkReplyNSURLConnection: Certificate verification error handlig is"
|
||||
<< "not implemented. Connection will time out.";
|
||||
} else {
|
||||
// other error, which the default handler will handle
|
||||
[challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge];
|
||||
}
|
||||
}
|
||||
|
||||
[challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge];
|
||||
}
|
||||
#endif
|
||||
|
||||
- (void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error
|
||||
{
|
||||
Q_UNUSED(connection)
|
||||
|
||||
QNetworkReply::NetworkError qtError = QNetworkReply::UnknownNetworkError;
|
||||
if ([[error domain] isEqualToString:NSURLErrorDomain]) {
|
||||
switch ([error code]) {
|
||||
case NSURLErrorTimedOut: qtError = QNetworkReply::TimeoutError; break;
|
||||
case NSURLErrorUnsupportedURL: qtError = QNetworkReply::ProtocolUnknownError; break;
|
||||
case NSURLErrorCannotFindHost: qtError = QNetworkReply::HostNotFoundError; break;
|
||||
case NSURLErrorCannotConnectToHost: qtError = QNetworkReply::ConnectionRefusedError; break;
|
||||
case NSURLErrorNetworkConnectionLost: qtError = QNetworkReply::NetworkSessionFailedError; break;
|
||||
case NSURLErrorDNSLookupFailed: qtError = QNetworkReply::HostNotFoundError; break;
|
||||
case NSURLErrorNotConnectedToInternet: qtError = QNetworkReply::NetworkSessionFailedError; break;
|
||||
case NSURLErrorUserAuthenticationRequired: qtError = QNetworkReply::AuthenticationRequiredError; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
replyprivate->setError(qtError, QString::fromNSString([error localizedDescription]));
|
||||
replyprivate->setFinished();
|
||||
}
|
||||
|
||||
- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)aResponse
|
||||
{
|
||||
Q_UNUSED(connection)
|
||||
self.response = aResponse;
|
||||
self.responseData = [NSMutableData data];
|
||||
|
||||
// copy headers
|
||||
if ([aResponse isKindOfClass:[NSHTTPURLResponse class]]) {
|
||||
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)aResponse;
|
||||
NSDictionary *headers = [httpResponse allHeaderFields];
|
||||
for (NSString *key in headers) {
|
||||
NSString *value = [headers objectForKey:key];
|
||||
replyprivate->setRawHeader(QString::fromNSString(key).toUtf8(), QString::fromNSString(value).toUtf8());
|
||||
}
|
||||
|
||||
int code = [httpResponse statusCode];
|
||||
replyprivate->setAttribute(QNetworkRequest::HttpStatusCodeAttribute, code);
|
||||
} else {
|
||||
if ([aResponse expectedContentLength] != NSURLResponseUnknownLength)
|
||||
replyprivate->setHeader(QNetworkRequest::ContentLengthHeader, [aResponse expectedContentLength]);
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod(replyprivate->q_func(), "metaDataChanged", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data
|
||||
{
|
||||
Q_UNUSED(connection)
|
||||
[responseData appendData:data];
|
||||
|
||||
if ([response expectedContentLength] != NSURLResponseUnknownLength) {
|
||||
QMetaObject::invokeMethod(replyprivate->q_func(), "downloadProgress", Qt::QueuedConnection,
|
||||
Q_ARG(qint64, qint64([responseData length] + replyprivate->bytesRead)),
|
||||
Q_ARG(qint64, qint64([response expectedContentLength])));
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod(replyprivate->q_func(), "readyRead", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
- (void)connection:(NSURLConnection*)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten
|
||||
totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
|
||||
{
|
||||
Q_UNUSED(connection)
|
||||
Q_UNUSED(bytesWritten)
|
||||
QMetaObject::invokeMethod(replyprivate->q_func(), "uploadProgress", Qt::QueuedConnection,
|
||||
Q_ARG(qint64, qint64(totalBytesWritten)),
|
||||
Q_ARG(qint64, qint64(totalBytesExpectedToWrite)));
|
||||
}
|
||||
|
||||
- (NSCachedURLResponse*)connection:(NSURLConnection*)connection willCacheResponse:(NSCachedURLResponse*)cachedResponse
|
||||
{
|
||||
Q_UNUSED(connection)
|
||||
return cachedResponse;
|
||||
}
|
||||
|
||||
- (NSURLRequest*)connection:(NSURLConnection*)connection willSendRequest:(NSURLRequest*)request redirectResponse:(NSURLResponse*)redirectResponse
|
||||
{
|
||||
Q_UNUSED(connection)
|
||||
Q_UNUSED(redirectResponse)
|
||||
return request;
|
||||
}
|
||||
|
||||
- (void)connectionDidFinishLoading:(NSURLConnection*)connection
|
||||
{
|
||||
Q_UNUSED(connection)
|
||||
replyprivate->setFinished();
|
||||
}
|
||||
|
||||
- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection*)connection
|
||||
{
|
||||
Q_UNUSED(connection)
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
QNetworkReplyNSURLConnectionImpl::~QNetworkReplyNSURLConnectionImpl()
|
||||
{
|
||||
}
|
||||
|
||||
QNetworkReplyNSURLConnectionImpl::QNetworkReplyNSURLConnectionImpl(QObject *parent,
|
||||
const QNetworkRequest &request, const QNetworkAccessManager::Operation operation, QIODevice* outgoingData)
|
||||
: QNetworkReply(*new QNetworkReplyNSURLConnectionImplPrivate(), parent)
|
||||
{
|
||||
setRequest(request);
|
||||
setUrl(request.url());
|
||||
setOperation(operation);
|
||||
QNetworkReply::open(QIODevice::ReadOnly);
|
||||
|
||||
QNetworkReplyNSURLConnectionImplPrivate *d = (QNetworkReplyNSURLConnectionImplPrivate*) d_func();
|
||||
|
||||
QUrl url = request.url();
|
||||
if (url.host() == QLatin1String("localhost"))
|
||||
url.setHost(QString());
|
||||
|
||||
if (url.path().isEmpty())
|
||||
url.setPath(QLatin1String("/"));
|
||||
setUrl(url);
|
||||
|
||||
// Create a NSMutableURLRequest from QNetworkRequest
|
||||
NSMutableURLRequest *nsRequest = [NSMutableURLRequest requestWithURL:request.url().toNSURL()
|
||||
cachePolicy:NSURLRequestUseProtocolCachePolicy
|
||||
timeoutInterval:60.0];
|
||||
// copy headers
|
||||
const auto headers = request.rawHeaderList();
|
||||
for (const QByteArray &header : headers) {
|
||||
QByteArray headerValue = request.rawHeader(header);
|
||||
[nsRequest addValue:QString::fromUtf8(headerValue).toNSString()
|
||||
forHTTPHeaderField:QString::fromUtf8(header).toNSString()];
|
||||
}
|
||||
|
||||
if (operation == QNetworkAccessManager::GetOperation)
|
||||
[nsRequest setHTTPMethod:@"GET"];
|
||||
else if (operation == QNetworkAccessManager::PostOperation)
|
||||
[nsRequest setHTTPMethod:@"POST"];
|
||||
else if (operation == QNetworkAccessManager::PutOperation)
|
||||
[nsRequest setHTTPMethod:@"PUT"];
|
||||
else if (operation == QNetworkAccessManager::DeleteOperation)
|
||||
[nsRequest setHTTPMethod:@"DELETE"];
|
||||
else
|
||||
qWarning() << "QNetworkReplyNSURLConnection: Unsupported netork operation" << operation;
|
||||
|
||||
if (outgoingData) {
|
||||
d->outgoingData = outgoingData;
|
||||
if (outgoingData->isSequential()) {
|
||||
// set up streaming from outgoingData iodevice to request
|
||||
CFStreamCreateBoundPair(kCFAllocatorDefault, &d->readStream, &d->writeStream, d->transferBufferSize);
|
||||
CFWriteStreamOpen(d->writeStream);
|
||||
[nsRequest setHTTPBodyStream:reinterpret_cast<NSInputStream *>(d->readStream)];
|
||||
connect(outgoingData, SIGNAL(readyRead()), this, SLOT(readyReadOutgoingData()));
|
||||
readyReadOutgoingData();
|
||||
} else {
|
||||
// move all data at once
|
||||
QByteArray data = outgoingData->readAll();
|
||||
[nsRequest setHTTPBody:[NSData dataWithBytes:data.constData() length:data.length()]];
|
||||
}
|
||||
}
|
||||
|
||||
// Create connection
|
||||
d->urlConnectionDelegate = [[QtNSURLConnectionDelegate alloc] initWithQNetworkReplyNSURLConnectionImplPrivate:d];
|
||||
d->urlConnection = [[NSURLConnection alloc] initWithRequest:nsRequest delegate:d->urlConnectionDelegate];
|
||||
if (!d->urlConnection) {
|
||||
// ### what type of error is an initWithRequest fail?
|
||||
setError(QNetworkReply::ProtocolUnknownError, QStringLiteral("QNetworkReplyNSURLConnection internal error"));
|
||||
}
|
||||
}
|
||||
|
||||
void QNetworkReplyNSURLConnectionImpl::close()
|
||||
{
|
||||
// No-op? Network ops should continue (especially POSTs)
|
||||
QNetworkReply::close();
|
||||
}
|
||||
|
||||
void QNetworkReplyNSURLConnectionImpl::abort()
|
||||
{
|
||||
Q_D(QNetworkReplyNSURLConnectionImpl);
|
||||
[d->urlConnection cancel];
|
||||
QNetworkReply::close();
|
||||
}
|
||||
|
||||
qint64 QNetworkReplyNSURLConnectionImpl::bytesAvailable() const
|
||||
{
|
||||
Q_D(const QNetworkReplyNSURLConnectionImpl);
|
||||
qint64 available = QNetworkReply::bytesAvailable() +
|
||||
[[d->urlConnectionDelegate responseData] length];
|
||||
return available;
|
||||
}
|
||||
|
||||
bool QNetworkReplyNSURLConnectionImpl::isSequential() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
qint64 QNetworkReplyNSURLConnectionImpl::size() const
|
||||
{
|
||||
Q_D(const QNetworkReplyNSURLConnectionImpl);
|
||||
return [[d->urlConnectionDelegate responseData] length] + d->bytesRead;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
qint64 QNetworkReplyNSURLConnectionImpl::readData(char *data, qint64 maxlen)
|
||||
{
|
||||
Q_D(QNetworkReplyNSURLConnectionImpl);
|
||||
qint64 dataSize = [[d->urlConnectionDelegate responseData] length];
|
||||
qint64 canRead = qMin(maxlen, dataSize);
|
||||
const char *sourceBase = static_cast<const char *>([[d->urlConnectionDelegate responseData] bytes]);
|
||||
memcpy(data, sourceBase, canRead);
|
||||
[[d->urlConnectionDelegate responseData] replaceBytesInRange:NSMakeRange(0, canRead) withBytes:NULL length:0];
|
||||
d->bytesRead += canRead;
|
||||
return canRead;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
@ -1,87 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://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 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QNETWORKREPLYNSURLCONNECTIONIMPL_H
|
||||
#define QNETWORKREPLYNSURLCONNECTIONIMPL_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists for the convenience
|
||||
// of the Network Access API. This header file may change from
|
||||
// version to version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "qnetworkreply.h"
|
||||
#include "qnetworkreply_p.h"
|
||||
#include "qnetworkaccessmanager.h"
|
||||
#include <QFile>
|
||||
#include <private/qabstractfileengine_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
||||
class QNetworkReplyNSURLConnectionImplPrivate;
|
||||
class QNetworkReplyNSURLConnectionImpl: public QNetworkReply
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QNetworkReplyNSURLConnectionImpl(QObject *parent, const QNetworkRequest &req, const QNetworkAccessManager::Operation op, QIODevice* outgoingData);
|
||||
virtual ~QNetworkReplyNSURLConnectionImpl();
|
||||
virtual void abort();
|
||||
|
||||
// reimplemented from QNetworkReply
|
||||
virtual void close();
|
||||
virtual qint64 bytesAvailable() const;
|
||||
virtual bool isSequential () const;
|
||||
qint64 size() const;
|
||||
|
||||
virtual qint64 readData(char *data, qint64 maxlen);
|
||||
public Q_SLOTS:
|
||||
void readyReadOutgoingData();
|
||||
|
||||
Q_DECLARE_PRIVATE(QNetworkReplyNSURLConnectionImpl)
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QNetworkReplyNSURLConnectionImpl_H
|
@ -47,7 +47,9 @@
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <arpa/nameser_compat.h>
|
||||
#if !defined(Q_OS_OPENBSD)
|
||||
# include <arpa/nameser_compat.h>
|
||||
#endif
|
||||
#include <resolv.h>
|
||||
|
||||
#if defined(__GNU_LIBRARY__) && !defined(__UCLIBC__)
|
||||
@ -58,6 +60,9 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
#ifndef QT_NO_LIBRARY
|
||||
|
||||
#if defined(Q_OS_OPENBSD)
|
||||
typedef struct __res_state* res_state;
|
||||
#endif
|
||||
typedef int (*dn_expand_proto)(const unsigned char *, const unsigned char *, const unsigned char *, char *, int);
|
||||
static dn_expand_proto local_dn_expand = 0;
|
||||
typedef void (*res_nclose_proto)(res_state);
|
||||
|
@ -560,7 +560,9 @@ int QNativeSocketEnginePrivate::nativeAccept()
|
||||
setError(QAbstractSocket::SocketResourceError, NotSocketErrorString);
|
||||
break;
|
||||
case EPROTONOSUPPORT:
|
||||
#if !defined(Q_OS_OPENBSD)
|
||||
case EPROTO:
|
||||
#endif
|
||||
case EAFNOSUPPORT:
|
||||
case EINVAL:
|
||||
setError(QAbstractSocket::UnsupportedSocketOperationError, ProtocolUnsupportedErrorString);
|
||||
@ -900,7 +902,9 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS
|
||||
if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_RECVIF
|
||||
&& cmsgptr->cmsg_len >= CMSG_LEN(sizeof(sockaddr_dl))) {
|
||||
sockaddr_dl *sdl = reinterpret_cast<sockaddr_dl *>(CMSG_DATA(cmsgptr));
|
||||
|
||||
# if defined(Q_OS_OPENBSD)
|
||||
# define LLINDEX(s) ((s)->sdl_index)
|
||||
# endif
|
||||
header->ifindex = LLINDEX(sdl);
|
||||
}
|
||||
# endif
|
||||
|
@ -337,7 +337,7 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port)
|
||||
d->socketState = QAbstractSocket::ConnectingState;
|
||||
hr = QEventDispatcherWinRT::runOnXamlThread([d]() {
|
||||
return d->connectOp->put_Completed(Callback<IAsyncActionCompletedHandler>(
|
||||
d, &QNativeSocketEnginePrivate::handleConnectToHost).Get());
|
||||
d, &QNativeSocketEnginePrivate::handleConnectOpFinished).Get());
|
||||
});
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
@ -477,7 +477,10 @@ void QNativeSocketEngine::close()
|
||||
hr = socket3->CancelIOAsync(&action);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
hr = QWinRTFunctions::await(action);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
// If there is no pending IO (no read established before) the function will fail with
|
||||
// "function was called at an unexpected time" which is fine.
|
||||
if (hr != E_ILLEGAL_METHOD_CALL)
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
return S_OK;
|
||||
});
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
@ -759,7 +762,7 @@ bool QNativeSocketEngine::waitForWrite(int msecs, bool *timedOut)
|
||||
if (d->socketState == QAbstractSocket::ConnectingState) {
|
||||
HRESULT hr = QWinRTFunctions::await(d->connectOp, QWinRTFunctions::ProcessMainThreadEvents);
|
||||
if (SUCCEEDED(hr)) {
|
||||
d->handleConnectionEstablished(d->connectOp.Get());
|
||||
d->handleConnectOpFinished(d->connectOp.Get(), Completed);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1214,38 +1217,32 @@ HRESULT QNativeSocketEnginePrivate::handleClientConnection(IStreamSocketListener
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT QNativeSocketEnginePrivate::handleConnectToHost(IAsyncAction *action, AsyncStatus)
|
||||
{
|
||||
handleConnectionEstablished(action);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void QNativeSocketEnginePrivate::handleConnectionEstablished(IAsyncAction *action)
|
||||
HRESULT QNativeSocketEnginePrivate::handleConnectOpFinished(IAsyncAction *action, AsyncStatus)
|
||||
{
|
||||
Q_Q(QNativeSocketEngine);
|
||||
if (wasDeleted || !connectOp) // Protect against a late callback
|
||||
return;
|
||||
return S_OK;
|
||||
|
||||
HRESULT hr = action->GetResults();
|
||||
switch (hr) {
|
||||
case 0x8007274c: // A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
|
||||
setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString);
|
||||
socketState = QAbstractSocket::UnconnectedState;
|
||||
break;
|
||||
return S_OK;
|
||||
case 0x80072751: // A socket operation was attempted to an unreachable host.
|
||||
setError(QAbstractSocket::HostNotFoundError, HostUnreachableErrorString);
|
||||
socketState = QAbstractSocket::UnconnectedState;
|
||||
break;
|
||||
return S_OK;
|
||||
case 0x8007274d: // No connection could be made because the target machine actively refused it.
|
||||
setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
|
||||
socketState = QAbstractSocket::UnconnectedState;
|
||||
break;
|
||||
return S_OK;
|
||||
default:
|
||||
if (FAILED(hr)) {
|
||||
setError(QAbstractSocket::UnknownSocketError, UnknownSocketErrorString);
|
||||
socketState = QAbstractSocket::UnconnectedState;
|
||||
return S_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// The callback might be triggered several times if we do not cancel/reset it here
|
||||
@ -1267,13 +1264,14 @@ void QNativeSocketEnginePrivate::handleConnectionEstablished(IAsyncAction *actio
|
||||
emit q->connectionReady();
|
||||
|
||||
if (socketType != QAbstractSocket::TcpSocket)
|
||||
return;
|
||||
return S_OK;
|
||||
|
||||
// Delay the reader so that the SSL socket can upgrade
|
||||
if (sslSocket)
|
||||
QObject::connect(qobject_cast<QSslSocket *>(sslSocket), &QSslSocket::encrypted, q, &QNativeSocketEngine::establishRead);
|
||||
else
|
||||
q->establishRead();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *asyncInfo, AsyncStatus status)
|
||||
|
@ -220,8 +220,7 @@ private:
|
||||
ABI::Windows::Networking::Sockets::IDatagramSocketMessageReceivedEventArgs *args);
|
||||
HRESULT handleClientConnection(ABI::Windows::Networking::Sockets::IStreamSocketListener *tcpListener,
|
||||
ABI::Windows::Networking::Sockets::IStreamSocketListenerConnectionReceivedEventArgs *args);
|
||||
HRESULT handleConnectToHost(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus);
|
||||
void handleConnectionEstablished(ABI::Windows::Foundation::IAsyncAction *action);
|
||||
HRESULT handleConnectOpFinished(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus);
|
||||
HRESULT handleReadyRead(ABI::Windows::Foundation::IAsyncOperationWithProgress<ABI::Windows::Storage::Streams::IBuffer *, UINT32> *asyncInfo, ABI::Windows::Foundation::AsyncStatus);
|
||||
};
|
||||
|
||||
|
@ -1122,7 +1122,9 @@ bool QSocks5SocketEngine::connectInternal()
|
||||
}
|
||||
|
||||
if (d->socketState != QAbstractSocket::ConnectingState) {
|
||||
if (d->socks5State == QSocks5SocketEnginePrivate::Uninitialized) {
|
||||
if (d->socks5State == QSocks5SocketEnginePrivate::Uninitialized
|
||||
// We may have new auth credentials since an earlier failure:
|
||||
|| d->socks5State == QSocks5SocketEnginePrivate::AuthenticatingError) {
|
||||
setState(QAbstractSocket::ConnectingState);
|
||||
//limit buffer in internal socket, data is buffered in the external socket under application control
|
||||
d->data->controlSocket->setReadBufferSize(65536);
|
||||
|
@ -2632,7 +2632,8 @@ QList<QByteArray> QSslSocketPrivate::unixRootCertDirectories()
|
||||
<< "/var/ssl/certs/" // AIX
|
||||
<< "/usr/local/ssl/certs/" // Solaris
|
||||
<< "/etc/openssl/certs/" // BlackBerry
|
||||
<< "/opt/openssl/certs/"; // HP-UX
|
||||
<< "/opt/openssl/certs/" // HP-UX
|
||||
<< "/etc/ssl/"; // OpenBSD
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -80,6 +80,19 @@
|
||||
|
||||
\sa QXcbWindowFunctions QWindowsWindowFunctions
|
||||
|
||||
\section1 Getting Started
|
||||
|
||||
To include the definitions of the module's functions and classes, use the following directives:
|
||||
\code
|
||||
#include <QtPlatformHeaders/QWindowsWindowFunctions>
|
||||
#include <QtPlatformHeaders/QXcbWindowFunctions>
|
||||
\endcode
|
||||
|
||||
As the module is header-only, no further modifications to the .pro files are required to use it.
|
||||
|
||||
\note The module name (\c QtPlatformHeaders) must appear in the \c #include directive.
|
||||
\note It is not necessary to enclose the code in \c #ifdef directives depending on platform.
|
||||
|
||||
\section1 API Reference
|
||||
\list
|
||||
\li \l{Qt Platform Headers C++ Classes}{C++ Classes}
|
||||
|
@ -1,18 +1,14 @@
|
||||
HEADERS += $$PWD/qdevicediscovery_p.h
|
||||
|
||||
linux {
|
||||
contains(QT_CONFIG, libudev) {
|
||||
SOURCES += $$PWD/qdevicediscovery_udev.cpp
|
||||
HEADERS += $$PWD/qdevicediscovery_udev_p.h
|
||||
INCLUDEPATH += $$QMAKE_INCDIR_LIBUDEV
|
||||
LIBS_PRIVATE += $$QMAKE_LIBS_LIBUDEV
|
||||
} else: contains(QT_CONFIG, evdev) {
|
||||
SOURCES += $$PWD/qdevicediscovery_static.cpp
|
||||
HEADERS += $$PWD/qdevicediscovery_static_p.h
|
||||
} else {
|
||||
SOURCES += $$PWD/qdevicediscovery_dummy.cpp
|
||||
HEADERS += $$PWD/qdevicediscovery_dummy_p.h
|
||||
}
|
||||
contains(QT_CONFIG, libudev) {
|
||||
SOURCES += $$PWD/qdevicediscovery_udev.cpp
|
||||
HEADERS += $$PWD/qdevicediscovery_udev_p.h
|
||||
INCLUDEPATH += $$QMAKE_INCDIR_LIBUDEV
|
||||
LIBS_PRIVATE += $$QMAKE_LIBS_LIBUDEV
|
||||
} else: contains(QT_CONFIG, evdev) {
|
||||
SOURCES += $$PWD/qdevicediscovery_static.cpp
|
||||
HEADERS += $$PWD/qdevicediscovery_static_p.h
|
||||
} else {
|
||||
SOURCES += $$PWD/qdevicediscovery_dummy.cpp
|
||||
HEADERS += $$PWD/qdevicediscovery_dummy_p.h
|
||||
}
|
||||
|
@ -587,6 +587,10 @@ int q_screenDepthFromFb(int framebufferDevice)
|
||||
|
||||
qreal q_refreshRateFromFb(int framebufferDevice)
|
||||
{
|
||||
#ifndef Q_OS_LINUX
|
||||
Q_UNUSED(framebufferDevice)
|
||||
#endif
|
||||
|
||||
static qreal rate = 0;
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
|
@ -60,7 +60,7 @@ Q_LOGGING_CATEGORY(qLcEvdevKeyMap, "qt.qpa.input.keymap")
|
||||
#include "qevdevkeyboard_defaultmap_p.h"
|
||||
|
||||
QEvdevKeyboardHandler::QEvdevKeyboardHandler(const QString &device, int fd, bool disableZap, bool enableCompose, const QString &keymapFile)
|
||||
: m_device(device), m_fd(fd),
|
||||
: m_device(device), m_fd(fd), m_notify(Q_NULLPTR),
|
||||
m_modifiers(0), m_composing(0), m_dead_unicode(0xffff),
|
||||
m_no_zap(disableZap), m_do_compose(enableCompose),
|
||||
m_keymap(0), m_keymap_size(0), m_keycompose(0), m_keycompose_size(0)
|
||||
@ -75,9 +75,8 @@ QEvdevKeyboardHandler::QEvdevKeyboardHandler(const QString &device, int fd, bool
|
||||
unloadKeymap();
|
||||
|
||||
// socket notifier for events on the keyboard device
|
||||
QSocketNotifier *notifier;
|
||||
notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
|
||||
connect(notifier, SIGNAL(activated(int)), this, SLOT(readKeycode()));
|
||||
m_notify = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
|
||||
connect(m_notify, SIGNAL(activated(int)), this, SLOT(readKeycode()));
|
||||
}
|
||||
|
||||
QEvdevKeyboardHandler::~QEvdevKeyboardHandler()
|
||||
@ -162,6 +161,14 @@ void QEvdevKeyboardHandler::readKeycode()
|
||||
} else if (result < 0) {
|
||||
if (errno != EINTR && errno != EAGAIN) {
|
||||
qErrnoWarning(errno, "evdevkeyboard: Could not read from input device");
|
||||
// If the device got disconnected, stop reading, otherwise we get flooded
|
||||
// by the above error over and over again.
|
||||
if (errno == ENODEV) {
|
||||
delete m_notify;
|
||||
m_notify = Q_NULLPTR;
|
||||
qt_safe_close(m_fd);
|
||||
m_fd = -1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
@ -57,6 +57,8 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QSocketNotifier;
|
||||
|
||||
namespace QEvdevKeyboardMap {
|
||||
const quint32 FileMagic = 0x514d4150; // 'QMAP'
|
||||
|
||||
@ -186,6 +188,7 @@ private:
|
||||
|
||||
QString m_device;
|
||||
int m_fd;
|
||||
QSocketNotifier *m_notify;
|
||||
|
||||
// keymap handling
|
||||
quint8 m_modifiers;
|
||||
|
@ -111,9 +111,8 @@ QEvdevMouseHandler::QEvdevMouseHandler(const QString &device, int fd, bool abs,
|
||||
m_abs = getHardwareMaximum();
|
||||
|
||||
// socket notifier for events on the mouse device
|
||||
QSocketNotifier *notifier;
|
||||
notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
|
||||
connect(notifier, SIGNAL(activated(int)), this, SLOT(readMouseData()));
|
||||
m_notify = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
|
||||
connect(m_notify, SIGNAL(activated(int)), this, SLOT(readMouseData()));
|
||||
}
|
||||
|
||||
QEvdevMouseHandler::~QEvdevMouseHandler()
|
||||
@ -202,6 +201,14 @@ void QEvdevMouseHandler::readMouseData()
|
||||
} else if (result < 0) {
|
||||
if (errno != EINTR && errno != EAGAIN) {
|
||||
qErrnoWarning(errno, "evdevmouse: Could not read from input device");
|
||||
// If the device got disconnected, stop reading, otherwise we get flooded
|
||||
// by the above error over and over again.
|
||||
if (errno == ENODEV) {
|
||||
delete m_notify;
|
||||
m_notify = Q_NULLPTR;
|
||||
qt_safe_close(m_fd);
|
||||
m_fd = -1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
@ -21,7 +21,11 @@ include(accessibility/accessibility.pri)
|
||||
include(linuxaccessibility/linuxaccessibility.pri)
|
||||
include(clipboard/clipboard.pri)
|
||||
include(platformcompositor/platformcompositor.pri)
|
||||
contains(QT_CONFIG, dbus) {
|
||||
|
||||
# dbus convenience, but not for darwin: the platform
|
||||
# plugins for these platforms do not use dbus and we
|
||||
# don't want to create a false dependency.
|
||||
!darwin: contains(QT_CONFIG, dbus) {
|
||||
include(dbusmenu/dbusmenu.pri)
|
||||
include(dbustray/dbustray.pri)
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ static bool isMouseEvent(NSEvent *ev)
|
||||
if (NSMouseInRect(loc, windowFrame, NO) &&
|
||||
!NSMouseInRect(loc, contentFrame, NO))
|
||||
{
|
||||
QNSView *contentView = (QNSView *)pw->contentView();
|
||||
QNSView *contentView = pw->m_qtView;
|
||||
[contentView handleFrameStrutMouseEvent: theEvent];
|
||||
}
|
||||
}
|
||||
@ -1188,7 +1188,11 @@ NSView *QCocoaWindow::contentView() const
|
||||
void QCocoaWindow::setContentView(NSView *contentView)
|
||||
{
|
||||
// Remove and release the previous content view
|
||||
[m_contentView removeFromSuperview];
|
||||
if (m_nsWindow)
|
||||
[m_nsWindow setContentView:nil];
|
||||
else
|
||||
[m_contentView removeFromSuperview];
|
||||
|
||||
[m_contentView release];
|
||||
|
||||
// Insert and retain the new content view
|
||||
|
@ -663,7 +663,9 @@ QT_WARNING_POP
|
||||
|
||||
- (BOOL)becomeFirstResponder
|
||||
{
|
||||
if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) )
|
||||
if (!m_window || !m_platformWindow)
|
||||
return NO;
|
||||
if (m_window->flags() & Qt::WindowTransparentForInput)
|
||||
return NO;
|
||||
if (!m_platformWindow->windowIsPopupType() && !m_isMenuView)
|
||||
QWindowSystemInterface::handleWindowActivated([self topLevelWindow]);
|
||||
@ -672,11 +674,13 @@ QT_WARNING_POP
|
||||
|
||||
- (BOOL)acceptsFirstResponder
|
||||
{
|
||||
if (!m_window || !m_platformWindow)
|
||||
return NO;
|
||||
if (m_isMenuView)
|
||||
return NO;
|
||||
if (m_platformWindow->shouldRefuseKeyWindowAndFirstResponder())
|
||||
return NO;
|
||||
if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) )
|
||||
if (m_window->flags() & Qt::WindowTransparentForInput)
|
||||
return NO;
|
||||
if ((m_window->flags() & Qt::ToolTip) == Qt::ToolTip)
|
||||
return NO;
|
||||
@ -686,7 +690,9 @@ QT_WARNING_POP
|
||||
- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
|
||||
{
|
||||
Q_UNUSED(theEvent)
|
||||
if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) )
|
||||
if (!m_window || !m_platformWindow)
|
||||
return NO;
|
||||
if (m_window->flags() & Qt::WindowTransparentForInput)
|
||||
return NO;
|
||||
return YES;
|
||||
}
|
||||
@ -2199,7 +2205,11 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin
|
||||
|
||||
// keep our state, and QGuiApplication state (buttons member) in-sync,
|
||||
// or future mouse events will be processed incorrectly
|
||||
m_buttons &= ~(m_sendUpAsRightButton ? Qt::RightButton : Qt::LeftButton);
|
||||
NSUInteger pmb = [NSEvent pressedMouseButtons];
|
||||
for (int buttonNumber = 0; buttonNumber < 32; buttonNumber++) { // see cocoaButton2QtButton() for the 32 value
|
||||
if (!(pmb & (1 << buttonNumber)))
|
||||
m_buttons &= ~cocoaButton2QtButton(buttonNumber);
|
||||
}
|
||||
|
||||
NSPoint windowPoint = [self convertPoint: point fromView: nil];
|
||||
QPoint qtWindowPoint(windowPoint.x, windowPoint.y);
|
||||
|
@ -132,7 +132,7 @@ void QEglFSKmsGbmCursor::updateMouseStatus()
|
||||
m_state = visible ? CursorPendingVisible : CursorPendingHidden;
|
||||
|
||||
#ifndef QT_NO_CURSOR
|
||||
changeCursor(nullptr, m_screen->topLevelAt(pos()));
|
||||
changeCursor(Q_NULLPTR, m_screen->topLevelAt(pos()));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,7 @@
|
||||
|
||||
#include <UIKit/UIKit.h>
|
||||
|
||||
#include <QtCore/qlocale.h>
|
||||
#include <QtGui/qevent.h>
|
||||
#include <QtGui/qtransform.h>
|
||||
#include <qpa/qplatforminputcontext.h>
|
||||
@ -52,6 +53,7 @@ const char kImePlatformDataReturnKeyType[] = "returnKeyType";
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@class QIOSLocaleListener;
|
||||
@class QIOSKeyboardListener;
|
||||
@class QIOSTextInputResponder;
|
||||
@protocol KeyboardState;
|
||||
@ -98,6 +100,8 @@ public:
|
||||
void reset() Q_DECL_OVERRIDE;
|
||||
void commit() Q_DECL_OVERRIDE;
|
||||
|
||||
QLocale locale() const Q_DECL_OVERRIDE;
|
||||
|
||||
void clearCurrentFocusObject();
|
||||
|
||||
void setFocusObject(QObject *object) Q_DECL_OVERRIDE;
|
||||
@ -118,6 +122,7 @@ public:
|
||||
private:
|
||||
UIView* scrollableRootView();
|
||||
|
||||
QIOSLocaleListener *m_localeListener;
|
||||
QIOSKeyboardListener *m_keyboardHideGesture;
|
||||
QIOSTextInputResponder *m_textResponder;
|
||||
KeyboardState m_keyboardState;
|
||||
|
@ -62,6 +62,39 @@ static QUIView *focusView()
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@interface QIOSLocaleListener : NSObject
|
||||
@end
|
||||
|
||||
@implementation QIOSLocaleListener
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if (self = [super init]) {
|
||||
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
|
||||
[notificationCenter addObserver:self
|
||||
selector:@selector(localeDidChange:)
|
||||
name:NSCurrentLocaleDidChangeNotification object:nil];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)localeDidChange:(NSNotification *)notification
|
||||
{
|
||||
Q_UNUSED(notification);
|
||||
QIOSInputContext::instance()->emitLocaleChanged();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@interface QIOSKeyboardListener : UIGestureRecognizer <UIGestureRecognizerDelegate> {
|
||||
@private
|
||||
QIOSInputContext *m_context;
|
||||
@ -291,6 +324,7 @@ QIOSInputContext *QIOSInputContext::instance()
|
||||
|
||||
QIOSInputContext::QIOSInputContext()
|
||||
: QPlatformInputContext()
|
||||
, m_localeListener([QIOSLocaleListener new])
|
||||
, m_keyboardHideGesture([[QIOSKeyboardListener alloc] initWithQIOSInputContext:this])
|
||||
, m_textResponder(0)
|
||||
{
|
||||
@ -304,6 +338,7 @@ QIOSInputContext::QIOSInputContext()
|
||||
|
||||
QIOSInputContext::~QIOSInputContext()
|
||||
{
|
||||
[m_localeListener release];
|
||||
[m_keyboardHideGesture.view removeGestureRecognizer:m_keyboardHideGesture];
|
||||
[m_keyboardHideGesture release];
|
||||
|
||||
@ -663,3 +698,8 @@ void QIOSInputContext::commit()
|
||||
[m_textResponder unmarkText];
|
||||
[m_textResponder notifyInputDelegate:Qt::ImSurroundingText];
|
||||
}
|
||||
|
||||
QLocale QIOSInputContext::locale() const
|
||||
{
|
||||
return QLocale(QString::fromNSString([[NSLocale currentLocale] objectForKey:NSLocaleIdentifier]));
|
||||
}
|
||||
|
@ -359,6 +359,7 @@
|
||||
|
||||
- (void)sendKeyPressRelease:(Qt::Key)key modifiers:(Qt::KeyboardModifiers)modifiers
|
||||
{
|
||||
QScopedValueRollback<BOOL> rollback(m_inSendEventToFocusObject, true);
|
||||
QWindowSystemInterface::handleKeyEvent(qApp->focusWindow(), QEvent::KeyPress, key, modifiers);
|
||||
QWindowSystemInterface::handleKeyEvent(qApp->focusWindow(), QEvent::KeyRelease, key, modifiers);
|
||||
QWindowSystemInterface::flushWindowSystemEvents();
|
||||
|
@ -11,6 +11,7 @@ HEADERS = qminimalintegration.h \
|
||||
OTHER_FILES += minimal.json
|
||||
|
||||
CONFIG += qpa/genericunixfontdatabase
|
||||
darwin: DEFINES += QT_NO_FONTCONFIG
|
||||
|
||||
PLUGIN_TYPE = platforms
|
||||
PLUGIN_CLASS_NAME = QMinimalIntegrationPlugin
|
||||
|
@ -2,9 +2,9 @@ TEMPLATE = subdirs
|
||||
|
||||
android: SUBDIRS += android
|
||||
|
||||
SUBDIRS += minimal
|
||||
!android: SUBDIRS += minimal
|
||||
|
||||
!win32|contains(QT_CONFIG, freetype):SUBDIRS += offscreen
|
||||
!android:if(!win32|contains(QT_CONFIG, freetype)): SUBDIRS += offscreen
|
||||
|
||||
contains(QT_CONFIG, xcb) {
|
||||
SUBDIRS += xcb
|
||||
|
@ -205,6 +205,45 @@ QWindowsEGLStaticContext::QWindowsEGLStaticContext(EGLDisplay display)
|
||||
{
|
||||
}
|
||||
|
||||
bool QWindowsEGLStaticContext::initializeAngle(QWindowsOpenGLTester::Renderers preferredType, HDC dc,
|
||||
EGLDisplay *display, EGLint *major, EGLint *minor)
|
||||
{
|
||||
#ifdef EGL_ANGLE_platform_angle
|
||||
if (libEGL.eglGetPlatformDisplayEXT
|
||||
&& (preferredType & QWindowsOpenGLTester::AngleBackendMask)) {
|
||||
const EGLint anglePlatformAttributes[][5] = {
|
||||
{ EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_NONE },
|
||||
{ EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE, EGL_NONE },
|
||||
{ EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
|
||||
EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE, EGL_NONE }
|
||||
};
|
||||
const EGLint *attributes = 0;
|
||||
if (preferredType & QWindowsOpenGLTester::AngleRendererD3d11)
|
||||
attributes = anglePlatformAttributes[0];
|
||||
else if (preferredType & QWindowsOpenGLTester::AngleRendererD3d9)
|
||||
attributes = anglePlatformAttributes[1];
|
||||
else if (preferredType & QWindowsOpenGLTester::AngleRendererD3d11Warp)
|
||||
attributes = anglePlatformAttributes[2];
|
||||
if (attributes) {
|
||||
*display = libEGL.eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, dc, attributes);
|
||||
if (!libEGL.eglInitialize(*display, major, minor)) {
|
||||
libEGL.eglTerminate(*display);
|
||||
*display = EGL_NO_DISPLAY;
|
||||
*major = *minor = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else // EGL_ANGLE_platform_angle
|
||||
Q_UNUSED(preferredType);
|
||||
Q_UNUSED(dc);
|
||||
Q_UNUSED(display);
|
||||
Q_UNUSED(major);
|
||||
Q_UNUSED(minor);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester::Renderers preferredType)
|
||||
{
|
||||
const HDC dc = QWindowsContext::instance()->displayContext();
|
||||
@ -225,33 +264,13 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester:
|
||||
EGLDisplay display = EGL_NO_DISPLAY;
|
||||
EGLint major = 0;
|
||||
EGLint minor = 0;
|
||||
#ifdef EGL_ANGLE_platform_angle
|
||||
if (libEGL.eglGetPlatformDisplayEXT
|
||||
&& (preferredType & QWindowsOpenGLTester::AngleBackendMask)) {
|
||||
const EGLint anglePlatformAttributes[][5] = {
|
||||
{ EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_NONE },
|
||||
{ EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE, EGL_NONE },
|
||||
{ EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
|
||||
EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE, EGL_NONE }
|
||||
};
|
||||
const EGLint *attributes = 0;
|
||||
if (preferredType & QWindowsOpenGLTester::AngleRendererD3d11)
|
||||
attributes = anglePlatformAttributes[0];
|
||||
else if (preferredType & QWindowsOpenGLTester::AngleRendererD3d9)
|
||||
attributes = anglePlatformAttributes[1];
|
||||
else if (preferredType & QWindowsOpenGLTester::AngleRendererD3d11Warp)
|
||||
attributes = anglePlatformAttributes[2];
|
||||
if (attributes) {
|
||||
display = libEGL.eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, dc, attributes);
|
||||
if (!libEGL.eglInitialize(display, &major, &minor)) {
|
||||
display = EGL_NO_DISPLAY;
|
||||
major = minor = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!initializeAngle(preferredType, dc, &display, &major, &minor)
|
||||
&& (preferredType & QWindowsOpenGLTester::AngleRendererD3d11)) {
|
||||
preferredType &= ~QWindowsOpenGLTester::AngleRendererD3d11;
|
||||
initializeAngle(preferredType, dc, &display, &major, &minor);
|
||||
}
|
||||
#else // EGL_ANGLE_platform_angle
|
||||
Q_UNUSED(preferredType)
|
||||
#endif
|
||||
|
||||
if (display == EGL_NO_DISPLAY)
|
||||
display = libEGL.eglGetDisplay(dc);
|
||||
if (!display) {
|
||||
|
@ -131,6 +131,8 @@ public:
|
||||
|
||||
private:
|
||||
explicit QWindowsEGLStaticContext(EGLDisplay display);
|
||||
static bool initializeAngle(QWindowsOpenGLTester::Renderers preferredType, HDC dc,
|
||||
EGLDisplay *display, EGLint *major, EGLint *minor);
|
||||
|
||||
const EGLDisplay m_display;
|
||||
};
|
||||
|
@ -1346,8 +1346,7 @@ QFontEngine *QWindowsMultiFontEngine::loadEngine(int at)
|
||||
QWindowsFontEngineDirectWrite *fedw = new QWindowsFontEngineDirectWrite(directWriteFontFace,
|
||||
fontEngine->fontDef.pixelSize,
|
||||
data);
|
||||
if (fontEngine->fontDef.weight > QFont::Normal)
|
||||
fedw->fontDef.weight = fontEngine->fontDef.weight;
|
||||
fedw->fontDef.weight = fontEngine->fontDef.weight;
|
||||
if (fontEngine->fontDef.style > QFont::StyleNormal)
|
||||
fedw->fontDef.style = fontEngine->fontDef.style;
|
||||
fedw->fontDef.family = fam;
|
||||
@ -1364,8 +1363,7 @@ QFontEngine *QWindowsMultiFontEngine::loadEngine(int at)
|
||||
// reason
|
||||
|
||||
QFontEngine *fe = new QWindowsFontEngine(fam, lf, data);
|
||||
if (fontEngine->fontDef.weight > QFont::Normal)
|
||||
fe->fontDef.weight = fontEngine->fontDef.weight;
|
||||
fe->fontDef.weight = fontEngine->fontDef.weight;
|
||||
if (fontEngine->fontDef.style > QFont::StyleNormal)
|
||||
fe->fontDef.style = fontEngine->fontDef.style;
|
||||
fe->fontDef.family = fam;
|
||||
|
@ -138,7 +138,16 @@ public:
|
||||
explicit ShGetFileInfoFunction(const wchar_t *fn, DWORD a, SHFILEINFO *i, UINT f, bool *r) :
|
||||
m_fileName(fn), m_attributes(a), m_flags(f), m_info(i), m_result(r) {}
|
||||
|
||||
void operator()() const { *m_result = SHGetFileInfo(m_fileName, m_attributes, m_info, sizeof(SHFILEINFO), m_flags); }
|
||||
void operator()() const
|
||||
{
|
||||
#ifndef Q_OS_WINCE
|
||||
const UINT oldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
|
||||
#endif
|
||||
*m_result = SHGetFileInfo(m_fileName, m_attributes, m_info, sizeof(SHFILEINFO), m_flags);
|
||||
#ifndef Q_OS_WINCE
|
||||
SetErrorMode(oldErrorMode);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
const wchar_t *m_fileName;
|
||||
|
@ -1677,12 +1677,13 @@ bool QWindowsWindow::handleWmPaint(HWND hwnd, UINT message,
|
||||
return false;
|
||||
PAINTSTRUCT ps;
|
||||
|
||||
// Observed painting problems with Aero style disabled (QTBUG-7865).
|
||||
if (testFlag(OpenGLSurface) && testFlag(OpenGLDoubleBuffered))
|
||||
InvalidateRect(hwnd, 0, false);
|
||||
|
||||
BeginPaint(hwnd, &ps);
|
||||
|
||||
// Observed painting problems with Aero style disabled (QTBUG-7865).
|
||||
// 5.8: Consider making it dependent on !DwmIsCompositionEnabled().
|
||||
if (testFlag(OpenGLSurface) && testFlag(OpenGLDoubleBuffered))
|
||||
SelectClipRgn(ps.hdc, NULL);
|
||||
|
||||
// If the a window is obscured by another window (such as a child window)
|
||||
// we still need to send isExposed=true, for compatibility.
|
||||
// Our tests depend on it.
|
||||
|
893
src/plugins/platforms/winrt/qwinrtdrag.cpp
Normal file
893
src/plugins/platforms/winrt/qwinrtdrag.cpp
Normal file
@ -0,0 +1,893 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the plugins of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL3$
|
||||
** 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 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or later as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.GPL included in
|
||||
** the packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 2.0 requirements will be
|
||||
** met: http://www.gnu.org/licenses/gpl-2.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
#include "qwinrtdrag.h"
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
#include <QtCore/QMimeData>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
|
||||
#include <qfunctions_winrt.h>
|
||||
#include <private/qeventdispatcher_winrt_p.h>
|
||||
|
||||
#include <Windows.ApplicationModel.datatransfer.h>
|
||||
#include <windows.ui.xaml.h>
|
||||
#include <windows.foundation.collections.h>
|
||||
#include <windows.graphics.imaging.h>
|
||||
#include <windows.storage.streams.h>
|
||||
#include <functional>
|
||||
#include <robuffer.h>
|
||||
|
||||
using namespace ABI::Windows::ApplicationModel::DataTransfer;
|
||||
using namespace ABI::Windows::ApplicationModel::DataTransfer::DragDrop;
|
||||
using namespace ABI::Windows::Foundation;
|
||||
using namespace ABI::Windows::Foundation::Collections;
|
||||
using namespace ABI::Windows::Graphics::Imaging;
|
||||
using namespace ABI::Windows::Storage;
|
||||
using namespace ABI::Windows::Storage::Streams;
|
||||
using namespace ABI::Windows::UI::Xaml;
|
||||
using namespace Microsoft::WRL;
|
||||
using namespace Microsoft::WRL::Wrappers;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
Q_LOGGING_CATEGORY(lcQpaMime, "qt.qpa.mime")
|
||||
|
||||
ComPtr<IBuffer> createIBufferFromData(const char *data, qint32 size)
|
||||
{
|
||||
static ComPtr<IBufferFactory> bufferFactory;
|
||||
HRESULT hr;
|
||||
if (!bufferFactory) {
|
||||
hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(),
|
||||
IID_PPV_ARGS(&bufferFactory));
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
ComPtr<IBuffer> buffer;
|
||||
const UINT32 length = size;
|
||||
hr = bufferFactory->Create(length, &buffer);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
hr = buffer->put_Length(length);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteArrayAccess;
|
||||
hr = buffer.As(&byteArrayAccess);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
byte *bytes;
|
||||
hr = byteArrayAccess->Buffer(&bytes);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
memcpy(bytes, data, length);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
class DragThreadTransferData : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public slots:
|
||||
void handleDrag();
|
||||
public:
|
||||
explicit DragThreadTransferData(QObject *parent = Q_NULLPTR);
|
||||
QWindow *window;
|
||||
QWinRTInternalMimeData *mime;
|
||||
QPoint point;
|
||||
Qt::DropActions actions;
|
||||
bool dropAction;
|
||||
ComPtr<IDragEventArgs> nativeArgs;
|
||||
ComPtr<IDragOperationDeferral> deferral;
|
||||
};
|
||||
|
||||
inline QString hStringToQString(const HString &hString)
|
||||
{
|
||||
quint32 l;
|
||||
const wchar_t *raw = hString.GetRawBuffer(&l);
|
||||
return (QString::fromWCharArray(raw, l));
|
||||
}
|
||||
|
||||
inline HString qStringToHString(const QString &qString)
|
||||
{
|
||||
HString h;
|
||||
h.Set(reinterpret_cast<const wchar_t*>(qString.utf16()), qString.size());
|
||||
return h;
|
||||
}
|
||||
|
||||
namespace NativeFormatStrings {
|
||||
static ComPtr<IStandardDataFormatsStatics> dataStatics;
|
||||
static HSTRING text; // text/plain
|
||||
static HSTRING html; // text/html
|
||||
static HSTRING storage; // text/uri-list
|
||||
}
|
||||
|
||||
static inline DataPackageOperation translateFromQDragDropActions(const Qt::DropAction action)
|
||||
{
|
||||
switch (action) {
|
||||
case Qt::CopyAction:
|
||||
return DataPackageOperation_Copy;
|
||||
case Qt::MoveAction:
|
||||
return DataPackageOperation_Move;
|
||||
case Qt::LinkAction:
|
||||
return DataPackageOperation_Link;
|
||||
case Qt::IgnoreAction:
|
||||
default:
|
||||
return DataPackageOperation_None;
|
||||
}
|
||||
}
|
||||
|
||||
static inline Qt::DropActions translateToQDragDropActions(const DataPackageOperation op)
|
||||
{
|
||||
Qt::DropActions actions = Qt::IgnoreAction;
|
||||
// None needs to be interpreted as the sender being able to handle
|
||||
// anything and let the receiver decide
|
||||
if (op == DataPackageOperation_None)
|
||||
actions = Qt::LinkAction | Qt::CopyAction | Qt::MoveAction;
|
||||
if (op & DataPackageOperation_Link)
|
||||
actions |= Qt::LinkAction;
|
||||
if (op & DataPackageOperation_Copy)
|
||||
actions |= Qt::CopyAction;
|
||||
if (op & DataPackageOperation_Move)
|
||||
actions |= Qt::MoveAction;
|
||||
return actions;
|
||||
}
|
||||
|
||||
QWinRTInternalMimeData::QWinRTInternalMimeData()
|
||||
: QInternalMimeData()
|
||||
{
|
||||
qCDebug(lcQpaMime) << __FUNCTION__;
|
||||
if (!NativeFormatStrings::dataStatics) {
|
||||
HRESULT hr;
|
||||
hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_ApplicationModel_DataTransfer_StandardDataFormats).Get(),
|
||||
IID_PPV_ARGS(&NativeFormatStrings::dataStatics));
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
hr = NativeFormatStrings::dataStatics->get_Text(&NativeFormatStrings::text);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
hr = NativeFormatStrings::dataStatics->get_Html(&NativeFormatStrings::html);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
hr = NativeFormatStrings::dataStatics->get_StorageItems(&NativeFormatStrings::storage);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
}
|
||||
}
|
||||
|
||||
QWinRTInternalMimeData::~QWinRTInternalMimeData()
|
||||
{
|
||||
}
|
||||
|
||||
bool QWinRTInternalMimeData::hasFormat_sys(const QString &mimetype) const
|
||||
{
|
||||
qCDebug(lcQpaMime) << __FUNCTION__ << mimetype;
|
||||
|
||||
if (!dataView)
|
||||
return false;
|
||||
|
||||
return formats_sys().contains(mimetype);
|
||||
}
|
||||
|
||||
QStringList QWinRTInternalMimeData::formats_sys() const
|
||||
{
|
||||
qCDebug(lcQpaMime) << __FUNCTION__;
|
||||
|
||||
if (!dataView)
|
||||
return QStringList();
|
||||
|
||||
if (!formats.isEmpty())
|
||||
return formats;
|
||||
|
||||
HRESULT hr;
|
||||
hr = QEventDispatcherWinRT::runOnXamlThread([this]() {
|
||||
boolean contains;
|
||||
HRESULT hr;
|
||||
hr = dataView->Contains(NativeFormatStrings::text, &contains);
|
||||
if (SUCCEEDED(hr) && contains)
|
||||
formats.append(QLatin1String("text/plain"));
|
||||
|
||||
hr = dataView->Contains(NativeFormatStrings::html, &contains);
|
||||
if (SUCCEEDED(hr) && contains)
|
||||
formats.append(QLatin1String("text/html"));
|
||||
|
||||
hr = dataView->Contains(NativeFormatStrings::storage, &contains);
|
||||
if (SUCCEEDED(hr) && contains)
|
||||
formats.append(QLatin1String("text/uri-list"));
|
||||
|
||||
// We need to add any additional format as well, for legacy windows
|
||||
// reasons, but also in case someone adds custom formats.
|
||||
ComPtr<IVectorView<HSTRING>> availableFormats;
|
||||
hr = dataView->get_AvailableFormats(&availableFormats);
|
||||
RETURN_OK_IF_FAILED("Could not query available formats.");
|
||||
|
||||
quint32 size;
|
||||
hr = availableFormats->get_Size(&size);
|
||||
RETURN_OK_IF_FAILED("Could not query format vector size.");
|
||||
for (quint32 i = 0; i < size; ++i) {
|
||||
HString str;
|
||||
hr = availableFormats->GetAt(i, str.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
continue;
|
||||
formats.append(hStringToQString(str));
|
||||
}
|
||||
return S_OK;
|
||||
});
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
return formats;
|
||||
}
|
||||
|
||||
QVariant QWinRTInternalMimeData::retrieveData_sys(const QString &mimetype, QVariant::Type preferredType) const
|
||||
{
|
||||
qCDebug(lcQpaMime) << __FUNCTION__ << mimetype << preferredType;
|
||||
|
||||
if (!dataView || !formats.contains(mimetype))
|
||||
return QVariant();
|
||||
|
||||
QVariant result;
|
||||
HRESULT hr;
|
||||
if (mimetype == QLatin1String("text/plain")) {
|
||||
hr = QEventDispatcherWinRT::runOnXamlThread([this, &result]() {
|
||||
HRESULT hr;
|
||||
ComPtr<IAsyncOperation<HSTRING>> op;
|
||||
HString res;
|
||||
hr = dataView->GetTextAsync(&op);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
hr = QWinRTFunctions::await(op, res.GetAddressOf());
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
result.setValue(hStringToQString(res));
|
||||
return S_OK;
|
||||
});
|
||||
} else if (mimetype == QLatin1String("text/uri-list")) {
|
||||
hr = QEventDispatcherWinRT::runOnXamlThread([this, &result]() {
|
||||
HRESULT hr;
|
||||
ComPtr<IAsyncOperation<IVectorView<IStorageItem*>*>> op;
|
||||
hr = dataView->GetStorageItemsAsync(&op);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
ComPtr<IVectorView<IStorageItem*>> nativeItems;
|
||||
hr = QWinRTFunctions::await(op, nativeItems.GetAddressOf());
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
QList<QVariant> items;
|
||||
quint32 count;
|
||||
hr = nativeItems->get_Size(&count);
|
||||
for (quint32 i = 0; i < count; ++i) {
|
||||
ComPtr<IStorageItem> item;
|
||||
hr = nativeItems->GetAt(i, &item);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
HString path;
|
||||
hr = item->get_Path(path.GetAddressOf());
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
items.append(QUrl::fromLocalFile(hStringToQString(path)));
|
||||
}
|
||||
result.setValue(items);
|
||||
return S_OK;
|
||||
});
|
||||
} else if (mimetype == QLatin1String("text/html")) {
|
||||
hr = QEventDispatcherWinRT::runOnXamlThread([this, &result]() {
|
||||
HRESULT hr;
|
||||
ComPtr<IAsyncOperation<HSTRING>> op;
|
||||
HString res;
|
||||
hr = dataView->GetHtmlFormatAsync(&op);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
hr = QWinRTFunctions::await(op, res.GetAddressOf());
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
result.setValue(hStringToQString(res));
|
||||
return S_OK;
|
||||
});
|
||||
} else {
|
||||
// Asking for custom data
|
||||
hr = QEventDispatcherWinRT::runOnXamlThread([this, &result, mimetype]() {
|
||||
HRESULT hr;
|
||||
ComPtr<IAsyncOperation<IInspectable*>> op;
|
||||
ComPtr<IInspectable> res;
|
||||
HString type;
|
||||
type.Set(reinterpret_cast<const wchar_t*>(mimetype.utf16()), mimetype.size());
|
||||
hr = dataView->GetDataAsync(type.Get(), &op);
|
||||
RETURN_OK_IF_FAILED("Could not query custom drag data.");
|
||||
hr = QWinRTFunctions::await(op, res.GetAddressOf());
|
||||
if (FAILED(hr) || !res) {
|
||||
qCDebug(lcQpaMime) << "Custom drop data operation returned no results or failed.";
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Test for properties
|
||||
ComPtr<IPropertyValue> propertyValue;
|
||||
hr = res.As(&propertyValue);
|
||||
if (SUCCEEDED(hr)) {
|
||||
// We need to check which type of custom data we are receiving
|
||||
PropertyType type;
|
||||
propertyValue->get_Type(&type);
|
||||
switch (type) {
|
||||
case PropertyType_UInt8: {
|
||||
quint8 v;
|
||||
hr = propertyValue->GetUInt8(&v);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
result.setValue(v);
|
||||
return S_OK;
|
||||
}
|
||||
case PropertyType_Int16: {
|
||||
qint16 v;
|
||||
hr = propertyValue->GetInt16(&v);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
result.setValue(v);
|
||||
return S_OK;
|
||||
}
|
||||
case PropertyType_UInt16: {
|
||||
quint16 v;
|
||||
hr = propertyValue->GetUInt16(&v);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
result.setValue(v);
|
||||
return S_OK;
|
||||
}
|
||||
case PropertyType_Int32: {
|
||||
qint32 v;
|
||||
hr = propertyValue->GetInt32(&v);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
result.setValue(v);
|
||||
return S_OK;
|
||||
}
|
||||
case PropertyType_UInt32: {
|
||||
quint32 v;
|
||||
hr = propertyValue->GetUInt32(&v);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
result.setValue(v);
|
||||
return S_OK;
|
||||
}
|
||||
case PropertyType_Int64: {
|
||||
qint64 v;
|
||||
hr = propertyValue->GetInt64(&v);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
result.setValue(v);
|
||||
return S_OK;
|
||||
}
|
||||
case PropertyType_UInt64: {
|
||||
quint64 v;
|
||||
hr = propertyValue->GetUInt64(&v);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
result.setValue(v);
|
||||
return S_OK;
|
||||
}
|
||||
case PropertyType_Single: {
|
||||
float v;
|
||||
hr = propertyValue->GetSingle(&v);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
result.setValue(v);
|
||||
return S_OK;
|
||||
}
|
||||
case PropertyType_Double: {
|
||||
double v;
|
||||
hr = propertyValue->GetDouble(&v);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
result.setValue(v);
|
||||
return S_OK;
|
||||
}
|
||||
case PropertyType_Char16: {
|
||||
wchar_t v;
|
||||
hr = propertyValue->GetChar16(&v);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
result.setValue(QString::fromWCharArray(&v, 1));
|
||||
return S_OK;
|
||||
}
|
||||
case PropertyType_Boolean: {
|
||||
boolean v;
|
||||
hr = propertyValue->GetBoolean(&v);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
result.setValue(v);
|
||||
return S_OK;
|
||||
}
|
||||
case PropertyType_String: {
|
||||
HString stringProperty;
|
||||
hr = propertyValue->GetString(stringProperty.GetAddressOf());
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
result.setValue(hStringToQString(stringProperty));
|
||||
return S_OK;
|
||||
}
|
||||
default:
|
||||
qCDebug(lcQpaMime) << "Unknown property type dropped:" << type;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Custom data can be read via input streams
|
||||
ComPtr<IRandomAccessStream> randomAccessStream;
|
||||
hr = res.As(&randomAccessStream);
|
||||
if (SUCCEEDED(hr)) {
|
||||
UINT64 size;
|
||||
hr = randomAccessStream->get_Size(&size);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
ComPtr<IInputStream> stream;
|
||||
hr = randomAccessStream.As(&stream);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
ComPtr<IBufferFactory> bufferFactory;
|
||||
hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(),
|
||||
IID_PPV_ARGS(&bufferFactory));
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
UINT32 length = qBound(quint64(0), quint64(size), quint64(UINT_MAX));
|
||||
ComPtr<IBuffer> buffer;
|
||||
hr = bufferFactory->Create(length, &buffer);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
ComPtr<IAsyncOperationWithProgress<IBuffer *, UINT32>> readOp;
|
||||
hr = stream->ReadAsync(buffer.Get(), length, InputStreamOptions_None, &readOp);
|
||||
|
||||
ComPtr<IBuffer> effectiveBuffer;
|
||||
hr = QWinRTFunctions::await(readOp, effectiveBuffer.GetAddressOf());
|
||||
|
||||
hr = effectiveBuffer->get_Length(&length);
|
||||
|
||||
ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteArrayAccess;
|
||||
hr = effectiveBuffer.As(&byteArrayAccess);
|
||||
|
||||
byte *bytes;
|
||||
hr = byteArrayAccess->Buffer(&bytes);
|
||||
QByteArray array((char *)bytes, length);
|
||||
result.setValue(array);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HSTRING runtimeClass;
|
||||
hr = res->GetRuntimeClassName(&runtimeClass);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
HString converted;
|
||||
converted.Set(runtimeClass);
|
||||
qCDebug(lcQpaMime) << "Unknown drop data type received (" << hStringToQString(converted)
|
||||
<< "). Ignoring...";
|
||||
return S_OK;
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void QWinRTInternalMimeData::setDataView(const Microsoft::WRL::ComPtr<IDataPackageView> &d)
|
||||
{
|
||||
dataView = d;
|
||||
formats.clear();
|
||||
}
|
||||
|
||||
static HRESULT qt_drag_enter(IInspectable *sender, ABI::Windows::UI::Xaml::IDragEventArgs *e)
|
||||
{
|
||||
QWinRTDrag::instance()->handleNativeDragEvent(sender, e);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT qt_drag_over(IInspectable *sender, ABI::Windows::UI::Xaml::IDragEventArgs *e)
|
||||
{
|
||||
QWinRTDrag::instance()->handleNativeDragEvent(sender, e);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT qt_drag_leave(IInspectable *sender, ABI::Windows::UI::Xaml::IDragEventArgs *e)
|
||||
{
|
||||
// Qt internally checks for new drags and auto sends leave events
|
||||
// Also there is no QPA function for handling leave
|
||||
Q_UNUSED(sender);
|
||||
Q_UNUSED(e);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT qt_drop(IInspectable *sender, ABI::Windows::UI::Xaml::IDragEventArgs *e)
|
||||
{
|
||||
QWinRTDrag::instance()->handleNativeDragEvent(sender, e, true);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#define Q_DECLARE_DRAGHANDLER(name,func) \
|
||||
class QtDragEventHandler##name : public IDragEventHandler \
|
||||
{ \
|
||||
public: \
|
||||
virtual HRESULT STDMETHODCALLTYPE Invoke(IInspectable *sender, \
|
||||
ABI::Windows::UI::Xaml::IDragEventArgs *e) \
|
||||
{ \
|
||||
return qt_##func(sender, e);\
|
||||
} \
|
||||
\
|
||||
STDMETHODIMP \
|
||||
QueryInterface(REFIID riid, void FAR* FAR* ppvObj) \
|
||||
{ \
|
||||
if (riid == IID_IUnknown || riid == IID_IDragEventHandler) { \
|
||||
*ppvObj = this; \
|
||||
AddRef(); \
|
||||
return NOERROR; \
|
||||
} \
|
||||
*ppvObj = NULL; \
|
||||
return ResultFromScode(E_NOINTERFACE); \
|
||||
} \
|
||||
\
|
||||
STDMETHODIMP_(ULONG) \
|
||||
AddRef(void) \
|
||||
{ \
|
||||
return ++m_refs; \
|
||||
} \
|
||||
\
|
||||
STDMETHODIMP_(ULONG) \
|
||||
Release(void) \
|
||||
{ \
|
||||
if (--m_refs == 0) { \
|
||||
delete this; \
|
||||
return 0; \
|
||||
} \
|
||||
return m_refs; \
|
||||
} \
|
||||
private: \
|
||||
ULONG m_refs{0}; \
|
||||
};
|
||||
|
||||
Q_DECLARE_DRAGHANDLER(Enter, drag_enter)
|
||||
Q_DECLARE_DRAGHANDLER(Over, drag_over)
|
||||
Q_DECLARE_DRAGHANDLER(Leave, drag_leave)
|
||||
Q_DECLARE_DRAGHANDLER(Drop, drop)
|
||||
|
||||
#define Q_INST_DRAGHANDLER(name) QtDragEventHandler##name()
|
||||
|
||||
Q_GLOBAL_STATIC(QWinRTDrag, gDrag);
|
||||
|
||||
extern ComPtr<ABI::Windows::UI::Input::IPointerPoint> qt_winrt_lastPointerPoint; // qwinrtscreen.cpp
|
||||
|
||||
QWinRTDrag::QWinRTDrag()
|
||||
: QPlatformDrag()
|
||||
, m_dragTarget(0)
|
||||
{
|
||||
qCDebug(lcQpaMime) << __FUNCTION__;
|
||||
m_enter = new Q_INST_DRAGHANDLER(Enter);
|
||||
m_over = new Q_INST_DRAGHANDLER(Over);
|
||||
m_leave = new Q_INST_DRAGHANDLER(Leave);
|
||||
m_drop = new Q_INST_DRAGHANDLER(Drop);
|
||||
m_mimeData = new QWinRTInternalMimeData;
|
||||
}
|
||||
|
||||
QWinRTDrag::~QWinRTDrag()
|
||||
{
|
||||
qCDebug(lcQpaMime) << __FUNCTION__;
|
||||
delete m_enter;
|
||||
delete m_over;
|
||||
delete m_leave;
|
||||
delete m_drop;
|
||||
delete m_mimeData;
|
||||
}
|
||||
|
||||
QWinRTDrag *QWinRTDrag::instance()
|
||||
{
|
||||
return gDrag;
|
||||
}
|
||||
|
||||
inline HRESULT resetUiElementDrag(ComPtr<IUIElement3> &elem3, EventRegistrationToken startingToken)
|
||||
{
|
||||
return QEventDispatcherWinRT::runOnXamlThread([elem3, startingToken]() {
|
||||
HRESULT hr;
|
||||
hr = elem3->put_CanDrag(false);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
hr = elem3->remove_DragStarting(startingToken);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
return S_OK;
|
||||
});
|
||||
}
|
||||
|
||||
Qt::DropAction QWinRTDrag::drag(QDrag *drag)
|
||||
{
|
||||
qCDebug(lcQpaMime) << __FUNCTION__ << drag;
|
||||
|
||||
if (!qt_winrt_lastPointerPoint) {
|
||||
Q_ASSERT_X(qt_winrt_lastPointerPoint, Q_FUNC_INFO, "No pointerpoint known");
|
||||
return Qt::IgnoreAction;
|
||||
}
|
||||
|
||||
ComPtr<IUIElement3> elem3;
|
||||
HRESULT hr = m_ui.As(&elem3);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
ComPtr<IAsyncOperation<ABI::Windows::ApplicationModel::DataTransfer::DataPackageOperation>> op;
|
||||
EventRegistrationToken startingToken;
|
||||
|
||||
hr = QEventDispatcherWinRT::runOnXamlThread([drag, &op, &hr, elem3, &startingToken, this]() {
|
||||
|
||||
hr = elem3->put_CanDrag(true);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
auto startingCallback = Callback<ITypedEventHandler<UIElement*, DragStartingEventArgs*>> ([drag](IInspectable *, IDragStartingEventArgs *args) {
|
||||
qCDebug(lcQpaMime) << "Drag starting" << args;
|
||||
|
||||
ComPtr<IDataPackage> dataPackage;
|
||||
HRESULT hr;
|
||||
hr = args->get_Data(dataPackage.GetAddressOf());
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
Qt::DropAction action = drag->defaultAction();
|
||||
hr = dataPackage->put_RequestedOperation(translateFromQDragDropActions(action));
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
#ifndef QT_WINRT_LIMITED_DRAGANDDROP
|
||||
ComPtr<IDragStartingEventArgs2> args2;
|
||||
hr = args->QueryInterface(IID_PPV_ARGS(&args2));
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
Qt::DropActions actions = drag->supportedActions();
|
||||
DataPackageOperation allowedOperations = DataPackageOperation_None;
|
||||
if (actions & Qt::CopyAction)
|
||||
allowedOperations |= DataPackageOperation_Copy;
|
||||
if (actions & Qt::MoveAction)
|
||||
allowedOperations |= DataPackageOperation_Move;
|
||||
if (actions & Qt::LinkAction)
|
||||
allowedOperations |= DataPackageOperation_Link;
|
||||
hr = args2->put_AllowedOperations(allowedOperations);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
#endif // QT_WINRT_LIMITED_DRAGANDDROP
|
||||
QMimeData *mimeData = drag->mimeData();
|
||||
if (mimeData->hasText()) {
|
||||
hr = dataPackage->SetText(qStringToHString(mimeData->text()).Get());
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
}
|
||||
if (mimeData->hasHtml()) {
|
||||
hr = dataPackage->SetHtmlFormat(qStringToHString(mimeData->html()).Get());
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
}
|
||||
// ### TODO: Missing: weblink, image
|
||||
|
||||
if (!drag->pixmap().isNull()) {
|
||||
const QImage image2 = drag->pixmap().toImage();
|
||||
const QImage image = image2.convertToFormat(QImage::Format_ARGB32);
|
||||
if (!image.isNull()) {
|
||||
// Create IBuffer containing image
|
||||
ComPtr<IBuffer> imageBuffer = createIBufferFromData(reinterpret_cast<const char*>(image.bits()), image.byteCount());
|
||||
|
||||
ComPtr<ISoftwareBitmapFactory> bitmapFactory;
|
||||
hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Graphics_Imaging_SoftwareBitmap).Get(),
|
||||
IID_PPV_ARGS(&bitmapFactory));
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
ComPtr<ISoftwareBitmap> bitmap;
|
||||
hr = bitmapFactory->Create(BitmapPixelFormat_Rgba8, image.width(), image.height(), &bitmap);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
hr = bitmap->CopyFromBuffer(imageBuffer.Get());
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
ComPtr<IDragUI> dragUi;
|
||||
hr = args->get_DragUI(dragUi.GetAddressOf());
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
hr = dragUi->SetContentFromSoftwareBitmap(bitmap.Get());
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
}
|
||||
}
|
||||
|
||||
const QStringList formats = mimeData->formats();
|
||||
for (auto item : formats) {
|
||||
QByteArray data = mimeData->data(item);
|
||||
|
||||
ComPtr<IBuffer> buffer = createIBufferFromData(data.constData(), data.size());
|
||||
|
||||
// We cannot push the buffer to the data package as the result on
|
||||
// recipient side is different from native events. It still sends a
|
||||
// buffer, but that potentially cannot be parsed. Hence we need to create
|
||||
// a IRandomAccessStream which gets forwarded as is to the drop side.
|
||||
ComPtr<IRandomAccessStream> ras;
|
||||
hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_InMemoryRandomAccessStream).Get(), &ras);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
hr = ras->put_Size(data.size());
|
||||
ComPtr<IOutputStream> outputStream;
|
||||
hr = ras->GetOutputStreamAt(0, &outputStream);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
ComPtr<IAsyncOperationWithProgress<UINT32,UINT32>> writeOp;
|
||||
hr = outputStream->WriteAsync(buffer.Get(), &writeOp);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
UINT32 result;
|
||||
hr = QWinRTFunctions::await(writeOp, &result);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
unsigned char flushResult;
|
||||
ComPtr<IAsyncOperation<bool>> flushOp;
|
||||
hr = outputStream->FlushAsync(&flushOp);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
hr = QWinRTFunctions::await(flushOp, &flushResult);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
hr = dataPackage->SetData(qStringToHString(item).Get(), ras.Get());
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
}
|
||||
return S_OK;
|
||||
});
|
||||
|
||||
hr = elem3->add_DragStarting(startingCallback.Get(), &startingToken);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
hr = elem3->StartDragAsync(qt_winrt_lastPointerPoint.Get(), &op);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
return hr;
|
||||
});
|
||||
if (!op || FAILED(hr)) {
|
||||
qCDebug(lcQpaMime) << "Drag failed:" << hr;
|
||||
hr = resetUiElementDrag(elem3, startingToken);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
return Qt::IgnoreAction;
|
||||
}
|
||||
|
||||
DataPackageOperation nativeOperationType;
|
||||
// Do not yield, as that can cause deadlocks when dropping inside the same app
|
||||
hr = QWinRTFunctions::await(op, &nativeOperationType, QWinRTFunctions::ProcessThreadEvents);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
hr = resetUiElementDrag(elem3, startingToken);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
Qt::DropAction resultAction;
|
||||
switch (nativeOperationType) {
|
||||
case DataPackageOperation_Link:
|
||||
resultAction = Qt::LinkAction;
|
||||
break;
|
||||
case DataPackageOperation_Copy:
|
||||
resultAction = Qt::CopyAction;
|
||||
break;
|
||||
case DataPackageOperation_Move:
|
||||
resultAction = Qt::MoveAction;
|
||||
break;
|
||||
case DataPackageOperation_None:
|
||||
default:
|
||||
resultAction = Qt::IgnoreAction;
|
||||
break;
|
||||
}
|
||||
|
||||
return resultAction;
|
||||
}
|
||||
|
||||
void QWinRTDrag::setDropTarget(QWindow *target)
|
||||
{
|
||||
qCDebug(lcQpaMime) << __FUNCTION__ << target;
|
||||
m_dragTarget = target;
|
||||
}
|
||||
|
||||
QMimeData *QWinRTDrag::platformDropData()
|
||||
{
|
||||
qCDebug(lcQpaMime) << __FUNCTION__;
|
||||
return m_mimeData;
|
||||
}
|
||||
|
||||
void QWinRTDrag::setUiElement(ComPtr<ABI::Windows::UI::Xaml::IUIElement> &element)
|
||||
{
|
||||
qCDebug(lcQpaMime) << __FUNCTION__;
|
||||
m_ui = element;
|
||||
// We set the element to always accept drops and then evaluate during
|
||||
// runtime
|
||||
HRESULT hr = element->put_AllowDrop(TRUE);
|
||||
EventRegistrationToken tok;
|
||||
hr = element->add_DragEnter(m_enter, &tok);
|
||||
RETURN_VOID_IF_FAILED("Failed to add DragEnter handler.");
|
||||
hr = element->add_DragOver(m_over, &tok);
|
||||
RETURN_VOID_IF_FAILED("Failed to add DragOver handler.");
|
||||
hr = element->add_DragLeave(m_leave, &tok);
|
||||
RETURN_VOID_IF_FAILED("Failed to add DragLeave handler.");
|
||||
hr = element->add_Drop(m_drop, &tok);
|
||||
RETURN_VOID_IF_FAILED("Failed to add Drop handler.");
|
||||
}
|
||||
|
||||
void QWinRTDrag::handleNativeDragEvent(IInspectable *sender, ABI::Windows::UI::Xaml::IDragEventArgs *e, bool drop)
|
||||
{
|
||||
Q_UNUSED(sender);
|
||||
|
||||
if (!m_dragTarget)
|
||||
return;
|
||||
|
||||
HRESULT hr;
|
||||
Point relativePoint;
|
||||
hr = e->GetPosition(m_ui.Get(), &relativePoint);
|
||||
RETURN_VOID_IF_FAILED("Could not query drag position.");
|
||||
const QPoint p(relativePoint.X, relativePoint.Y);
|
||||
|
||||
ComPtr<IDragEventArgs2> e2;
|
||||
hr = e->QueryInterface(IID_PPV_ARGS(&e2));
|
||||
RETURN_VOID_IF_FAILED("Could not convert drag event args");
|
||||
|
||||
DragDropModifiers modifiers;
|
||||
hr = e2->get_Modifiers(&modifiers);
|
||||
|
||||
#ifndef QT_WINRT_LIMITED_DRAGANDDROP
|
||||
ComPtr<IDragEventArgs3> e3;
|
||||
hr = e->QueryInterface(IID_PPV_ARGS(&e3));
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
DataPackageOperation dataOp;
|
||||
hr = e3->get_AllowedOperations(&dataOp);
|
||||
if (FAILED(hr))
|
||||
qCDebug(lcQpaMime) << __FUNCTION__ << "Could not query drag operations";
|
||||
|
||||
const Qt::DropActions actions = translateToQDragDropActions(dataOp);
|
||||
#else // !QT_WINRT_LIMITED_DRAGANDDROP
|
||||
const Qt::DropActions actions = Qt::LinkAction | Qt::CopyAction | Qt::MoveAction;;
|
||||
#endif // !QT_WINRT_LIMITED_DRAGANDDROP
|
||||
|
||||
ComPtr<IDataPackageView> dataView;
|
||||
hr = e2->get_DataView(&dataView);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
m_mimeData->setDataView(dataView);
|
||||
|
||||
// We use deferral as we need to jump to the Qt thread to handle
|
||||
// the drag event
|
||||
ComPtr<IDragOperationDeferral> deferral;
|
||||
hr = e2->GetDeferral(&deferral);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
|
||||
DragThreadTransferData *transferData = new DragThreadTransferData;
|
||||
transferData->moveToThread(qGuiApp->thread());
|
||||
transferData->window = m_dragTarget;
|
||||
transferData->point = p;
|
||||
transferData->mime = m_mimeData;
|
||||
transferData->actions = actions;
|
||||
transferData->dropAction = drop;
|
||||
transferData->nativeArgs = e;
|
||||
transferData->deferral = deferral;
|
||||
QMetaObject::invokeMethod(transferData, "handleDrag", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
DragThreadTransferData::DragThreadTransferData(QObject *parent)
|
||||
: QObject(parent)
|
||||
, dropAction(false)
|
||||
{
|
||||
}
|
||||
|
||||
void DragThreadTransferData::handleDrag()
|
||||
{
|
||||
bool accepted = false;
|
||||
Qt::DropAction acceptedAction;
|
||||
if (dropAction) {
|
||||
QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(window, mime, point, actions);
|
||||
accepted = response.isAccepted();
|
||||
acceptedAction = response.acceptedAction();
|
||||
} else {
|
||||
QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(window, mime, point, actions);
|
||||
accepted = response.isAccepted();
|
||||
acceptedAction = response.acceptedAction();
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
hr = QEventDispatcherWinRT::runOnXamlThread([accepted, acceptedAction, this]() {
|
||||
HRESULT hr;
|
||||
hr = nativeArgs->put_Handled(accepted);
|
||||
if (acceptedAction != Qt::IgnoreAction) {
|
||||
ComPtr<IDragEventArgs2> e2;
|
||||
hr = nativeArgs.As(&e2);
|
||||
if (SUCCEEDED(hr))
|
||||
hr = e2->put_AcceptedOperation(translateFromQDragDropActions(acceptedAction));
|
||||
}
|
||||
deferral->Complete();
|
||||
return S_OK;
|
||||
});
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#include "qwinrtdrag.moc"
|
113
src/plugins/platforms/winrt/qwinrtdrag.h
Normal file
113
src/plugins/platforms/winrt/qwinrtdrag.h
Normal file
@ -0,0 +1,113 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the plugins of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL3$
|
||||
** 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 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or later as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.GPL included in
|
||||
** the packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 2.0 requirements will be
|
||||
** met: http://www.gnu.org/licenses/gpl-2.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <qpa/qplatformdrag.h>
|
||||
|
||||
#include <QtCore/QLoggingCategory>
|
||||
#include <QtCore/QMimeData>
|
||||
#include <QtGui/private/qdnd_p.h> // QInternalMime
|
||||
|
||||
#include <wrl.h>
|
||||
|
||||
namespace ABI {
|
||||
namespace Windows {
|
||||
namespace ApplicationModel {
|
||||
namespace DataTransfer {
|
||||
struct IDataPackageView;
|
||||
}
|
||||
}
|
||||
namespace UI {
|
||||
namespace Xaml {
|
||||
struct IUIElement;
|
||||
struct IDragEventArgs;
|
||||
struct IDragOperationDeferral;
|
||||
//struct IDataPackageView;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(lcQpaMime)
|
||||
|
||||
class QtDragEventHandlerEnter;
|
||||
class QtDragEventHandlerOver;
|
||||
class QtDragEventHandlerLeave;
|
||||
class QtDragEventHandlerDrop;
|
||||
class QWinRTInternalMimeData;
|
||||
|
||||
class QWinRTInternalMimeData : public QInternalMimeData {
|
||||
public:
|
||||
QWinRTInternalMimeData();
|
||||
virtual ~QWinRTInternalMimeData();
|
||||
|
||||
bool hasFormat_sys(const QString &mimetype) const Q_DECL_OVERRIDE;
|
||||
QStringList formats_sys() const Q_DECL_OVERRIDE;
|
||||
QVariant retrieveData_sys(const QString &mimetype, QVariant::Type preferredType) const Q_DECL_OVERRIDE;
|
||||
|
||||
void setDataView(const Microsoft::WRL::ComPtr<ABI::Windows::ApplicationModel::DataTransfer::IDataPackageView> &d);
|
||||
private:
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::ApplicationModel::DataTransfer::IDataPackageView> dataView;
|
||||
mutable QStringList formats;
|
||||
};
|
||||
|
||||
class QWinRTDrag : public QPlatformDrag {
|
||||
public:
|
||||
QWinRTDrag();
|
||||
virtual ~QWinRTDrag();
|
||||
static QWinRTDrag *instance();
|
||||
|
||||
QMimeData *platformDropData(void) Q_DECL_OVERRIDE;
|
||||
Qt::DropAction drag(QDrag *) Q_DECL_OVERRIDE;
|
||||
|
||||
void setDropTarget(QWindow *target);
|
||||
|
||||
// Native integration and registration
|
||||
void setUiElement(Microsoft::WRL::ComPtr<ABI::Windows::UI::Xaml::IUIElement> &element);
|
||||
|
||||
void handleNativeDragEvent(IInspectable *sender, ABI::Windows::UI::Xaml::IDragEventArgs *e, bool drop = false);
|
||||
private:
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::UI::Xaml::IUIElement> m_ui;
|
||||
QWindow *m_dragTarget;
|
||||
QtDragEventHandlerEnter *m_enter;
|
||||
QtDragEventHandlerOver *m_over;
|
||||
QtDragEventHandlerLeave *m_leave;
|
||||
QtDragEventHandlerDrop *m_drop;
|
||||
QWinRTInternalMimeData *m_mimeData;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
@ -48,6 +48,9 @@
|
||||
#include "qwinrtfontdatabase.h"
|
||||
#include "qwinrttheme.h"
|
||||
#include "qwinrtclipboard.h"
|
||||
#ifndef QT_NO_DRAGANDDROP
|
||||
#include "qwinrtdrag.h"
|
||||
#endif
|
||||
|
||||
#include <QtGui/QOffscreenSurface>
|
||||
#include <QtGui/QOpenGLContext>
|
||||
@ -312,6 +315,17 @@ QPlatformClipboard *QWinRTIntegration::clipboard() const
|
||||
return d->clipboard;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DRAGANDDROP
|
||||
QPlatformDrag *QWinRTIntegration::drag() const
|
||||
{
|
||||
#if _MSC_VER >= 1900
|
||||
return QWinRTDrag::instance();
|
||||
#else
|
||||
return QPlatformIntegration::drag();
|
||||
#endif
|
||||
}
|
||||
#endif // QT_NO_DRAGANDDROP
|
||||
|
||||
Qt::KeyboardModifiers QWinRTIntegration::queryKeyboardModifiers() const
|
||||
{
|
||||
Q_D(const QWinRTIntegration);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user