Merge remote-tracking branch 'origin/5.12' into dev

Change-Id: I33e0abc771a2a772d3334172d50e7b0efe896590
bb10
Qt Forward Merge Bot 2018-09-02 01:00:14 +02:00
commit ae868dfbdc
164 changed files with 7652 additions and 791 deletions

View File

@ -162,7 +162,8 @@
"sources": [
{ "libs": "-lzdll", "condition": "config.msvc" },
{ "libs": "-lzlib", "condition": "config.msvc" },
{ "libs": "-lz", "condition": "!config.msvc" }
{ "libs": "-lz", "condition": "!config.msvc" },
{ "libs": "-s USE_ZLIB=1", "condition": "config.wasm" }
]
},
"dbus": {
@ -613,7 +614,7 @@
},
"use_gold_linker": {
"label": "Using gold linker",
"condition": "!config.win32 && !config.integrity && tests.use_gold_linker",
"condition": "!config.win32 && !config.integrity && !config.wasm && tests.use_gold_linker",
"output": [ "privateConfig", "useGoldLinker" ]
},
"optimize_debug": {

View File

@ -68,7 +68,7 @@ defineReplace(qtConfFunc_crossCompile) {
}
defineReplace(qtConfFunc_licenseCheck) {
exists($$QT_SOURCE_TREE/LICENSE.LGPL3)|exists($$QT_SOURCE_TREE/LICENSE.GPL2): \
exists($$QT_SOURCE_TREE/LICENSE.LGPL3)|exists($$QT_SOURCE_TREE/LICENSE.GPL2)|exists($$QT_SOURCE_TREE/LICENSE.GPL3): \
hasOpenSource = true
else: \
hasOpenSource = false
@ -187,8 +187,13 @@ defineReplace(qtConfFunc_licenseCheck) {
theLicense = "GNU Lesser General Public License (LGPL) version 3"
showWhat = "Type 'L' to view the GNU Lesser General Public License version 3 (LGPLv3)."
gpl2Ok = false
gpl3Ok = false
winrt {
notTheLicense = "Note: GPL version 2 is not available on WinRT."
} else: wasm {
gpl3Ok = true
theLicense = "GNU General Public License (GPL) version 3"
showWhat = "Type 'G' to view the GNU General Public License version 3 (GPLv3)."
} else: $$qtConfEvaluate("features.android-style-assets") {
notTheLicense = "Note: GPL version 2 is not available due to using Android style assets."
} else {
@ -230,6 +235,8 @@ defineReplace(qtConfFunc_licenseCheck) {
licenseFile = $$QT_SOURCE_TREE/LICENSE.LGPL3
} else: equals(commercial, no):equals(val, g):$$gpl2Ok {
licenseFile = $$QT_SOURCE_TREE/LICENSE.GPL2
} else: equals(commercial, no):equals(val, g):$$gpl3Ok {
licenseFile = $$QT_SOURCE_TREE/LICENSE.GPL3
} else {
next()
}
@ -268,6 +275,8 @@ defineTest(qtConfTest_architecture) {
content = $$cat($$test_out_dir/arch.exe, blob)
else: android:exists($$test_out_dir/libarch.so): \
content = $$cat($$test_out_dir/libarch.so, blob)
else: wasm:exists($$test_out_dir/arch.wasm): \
content = $$cat($$test_out_dir/arch.wasm, blob)
else: \
error("$$eval($${1}.label) detection binary not found.")

View File

@ -148,12 +148,14 @@ void TabletCanvas::initPixmap()
m_pixmap = newPixmap;
}
void TabletCanvas::paintEvent(QPaintEvent *)
void TabletCanvas::paintEvent(QPaintEvent *event)
{
if (m_pixmap.isNull())
initPixmap();
QPainter painter(this);
painter.drawPixmap(0, 0, m_pixmap);
QRect pixmapPortion = QRect(event->rect().topLeft() * devicePixelRatioF(),
event->rect().size() * devicePixelRatioF());
painter.drawPixmap(event->rect().topLeft(), m_pixmap, pixmapPortion);
}
//! [4]

View File

@ -34,7 +34,9 @@ isEmpty($${target_prefix}.INCDIRS) {
#
# Get default include and library paths from compiler
#
gcc {
wasm {
# wasm compiler does not work here, just use defaults
} else: gcc {
cmd_suffix = "<$$QMAKE_SYSTEM_NULL_DEVICE >$$QMAKE_SYSTEM_NULL_DEVICE"
equals(QMAKE_HOST.os, Windows): \
cmd_prefix = "set LC_ALL=C&"

View File

@ -24,5 +24,3 @@ load(default_pre)
!versionAtLeast(QMAKE_XCODE_VERSION, 4.3): \
error("This mkspec requires Xcode 4.3 or later")
ios:shared:!versionAtLeast(QMAKE_IOS_DEPLOYMENT_TARGET, 8.0): \
QMAKE_IOS_DEPLOYMENT_TARGET = 8.0

View File

@ -0,0 +1,12 @@
qt_depends = $$resolve_depends(QT, "QT.")
equals(TEMPLATE, app):contains(qt_depends, gui(-private)?) {
LIBS *= -L$$[QT_INSTALL_PLUGINS/get]/platforms
lib_name = wasm
lib_path_and_base = $$[QT_INSTALL_PLUGINS/get]/platforms/lib$${lib_name}$$qtPlatformTargetSuffix()
LIBS += -l$${lib_name}$$qtPlatformTargetSuffix() $$fromfile($${lib_path_and_base}.prl, QMAKE_PRL_LIBS)
}
load(qt)

View File

@ -0,0 +1,81 @@
# DESTDIR will be empty if not set in the app .pro file; make sure it has a value
isEmpty(DESTDIR): DESTDIR = $$OUT_PWD
# Create js and wasm files for applications
contains(TEMPLATE, .*app) {
TARGET_BASE = $${TARGET}
TARGET_HTML = $${TARGET}.html
TARGET_JS = $${TARGET}.js
# Make the emscripten compiler generate a js file
TARGET = $$TARGET_JS
QMAKE_INCDIR += $$(HOME)/.emscripten_ports/openssl/include
CONFIG += static
js_file.files = $$TARGET_JS
js_file.path = $$target.path
isEmpty(js_file.path): \
js_file.path += ./
INSTALLS += js_file
# Copy hosting html and javascript to the application build directory.
exists($$[QT_INSTALL_PLUGINS]/platforms/wasm_shell.html) {
# don't pass this until it's installed somewhere
# otherwise makespec test fails during qt configure
WASM_PLUGIN_PATH = $$[QT_INSTALL_PLUGINS]/platforms
} else {
## internal build. not installed
WASM_PLUGIN_PATH = $$PWD/../../../src/plugins/platforms/wasm
}
# Copy/Generate main .html file (e.g. myapp.html) from the webassembly_shell.html by
# replacing the app name placeholder with the actual app name.
apphtml.name = application main html file
apphtml.output = $$DESTDIR/$$TARGET_HTML
apphtml.commands = sed -e s/APPNAME/$$TARGET_BASE/g $$WASM_PLUGIN_PATH/wasm_shell.html > $$DESTDIR/$$TARGET_HTML
apphtml.input = $$WASM_PLUGIN_PATH/wasm_shell.html
apphtml.depends = $$apphtml.input
QMAKE_EXTRA_COMPILERS += apphtml
appjs.name = application qtloader.js
appjs.output = $$DESTDIR/qtloader.js
appjs.commands = $$QMAKE_COPY $$WASM_PLUGIN_PATH/qtloader.js $$DESTDIR
appjs.input = $$WASM_PLUGIN_PATH/qtloader.js
appjs.depends = $$appjs.input
QMAKE_EXTRA_COMPILERS += appjs
appsvg.name = application qtlogo.svg
appsvg.output = $$DESTDIR/qtlogo.svg
appsvg.commands = $$QMAKE_COPY $$WASM_PLUGIN_PATH/qtlogo.svg $$DESTDIR
appsvg.input = $$WASM_PLUGIN_PATH/qtlogo.svg
appsvg.depends = $$appsvg.input
QMAKE_EXTRA_COMPILERS += appsvg
QMAKE_EXTRA_TARGETS += apphtml appjs appsvg
POST_TARGETDEPS += apphtml appjs appsvg
# Add manual target to make "make -B shellfiles" work.
shellfiles.target = shellfiles
shellfiles.depends = apphtml appjs appsvg
QMAKE_EXTRA_TARGETS += shellfiles
# emscripten ports are linked into the main module (this app), not the Qt
# libs which reference them
qt {
qt_depends = $$resolve_depends(QT, "QT.")
contains(qt_depends, core(-private)?): QMAKE_LFLAGS += \
$$QMAKE_LIBS_THREAD $$QMAKE_LIBS_ZLIB
contains(qt_depends, gui(-private)?): QMAKE_LFLAGS += \
$$QMAKE_LIBS_FREETYPE $$QMAKE_LIBS_LIBPNG
}
}
# Creates the stand-alone version of the library from bitcode
!static:contains(TEMPLATE, .*lib): {
load(resolve_target)
QMAKE_POST_LINK += $$QMAKE_LINK_SHLIB $$QMAKE_RESOLVED_TARGET -o $${QMAKE_RESOLVED_TARGET}.js
QMAKE_INCDIR += $$(HOME)/.emscripten_ports/openssl/include
}

View File

@ -0,0 +1,90 @@
# qmake configuration for building with emscripten
MAKEFILE_GENERATOR = UNIX
QMAKE_PLATFORM = wasm unix
include(../common/gcc-base.conf)
include(../common/clang.conf)
EMTERP_FLAGS = \
-s EMTERPRETIFY=1 \
-s EMTERPRETIFY_ASYNC=1 \
-s \"EMTERPRETIFY_FILE=\'data.binary\'\" \
-s ASSERTIONS=1 \
--profiling-funcs
EMCC_COMMON_CFLAGS = \
-s USE_LIBPNG=1 \
-s USE_FREETYPE=1 \
-s USE_ZLIB=1
EMCC_COMMON_LFLAGS = \
-s WASM=1 \
-s FULL_ES2=1 \
-s ALLOW_MEMORY_GROWTH=1 \
-s USE_WEBGL2=1 \
-s NO_EXIT_RUNTIME=0 \
-s ERROR_ON_UNDEFINED_SYMBOLS=1 \
--bind \
-s \"BINARYEN_METHOD=\'native-wasm\'\" \
-s \"BINARYEN_TRAP_MODE=\'clamp\'\"
EMCC_COMMON_LFLAGS_DEBUG = \
$$EMCC_COMMON_LFLAGS \
-s ASSERTIONS=2 \
-s DEMANGLE_SUPPORT=1 \
# -s LIBRARY_DEBUG=1 \ #print out library calls, verbose
# -s SYSCALL_DEBUG=1 \ #print out sys calls, verbose
# -s FS_LOG=1 \ #print out filesystem ops, verbose
# -s SOCKET_DEBUG \ #print out socket,network data transfer
-s GL_DEBUG=1
# the -s arguments can also be used with release builds
# but here in debug for clarity
QMAKE_COMPILER += emscripten
QMAKE_CC = emcc
QMAKE_CXX = em++
QMAKE_CFLAGS += $$EMCC_COMMON_CFLAGS
QMAKE_CXXFLAGS += $$EMCC_COMMON_CFLAGS
# Practical debugging setup:
# "-g4" preserves function names for stack traces
# "-Os" produces reasonably sized binaries
QMAKE_CFLAGS_DEBUG -= -g
QMAKE_CXXFLAGS_DEBUG -= -g
QMAKE_CFLAGS_DEBUG += -Os -g4
QMAKE_CXXFLAGS_DEBUG += -Os -g4
QMAKE_LFLAGS_DEBUG += -Os -g4
QMAKE_CXXFLAGS_RELEASE -= -O2
QMAKE_CXXFLAGS_RELEASE += -O3
QMAKE_CFLAGS_RELEASE -= -O2
QMAKE_CFLAGS_RELEASE += -O3
QMAKE_LFLAGS_RELEASE += -O3
MAKE_CFLAGS_OPTIMIZE += -O3
MAKE_CFLAGS_OPTIMIZE_FULL += -Oz
QMAKE_LINK = $$QMAKE_CXX
QMAKE_LINK_SHLIB = $$QMAKE_CXX
QMAKE_LINK_C = $$QMAKE_CC
QMAKE_LINK_C_SHLIB = $$QMAKE_CC
QMAKE_LIBS_THREAD = $$QMAKE_CFLAGS_THREAD
QMAKE_LFLAGS += $$EMCC_COMMON_LFLAGS
QMAKE_LFLAGS_DEBUG += $$EMCC_COMMON_LFLAGS_DEBUG
QMAKE_PREFIX_SHLIB = lib
QMAKE_EXTENSION_SHLIB = so # llvm bitcode, linked to js in post_link
QMAKE_PREFIX_STATICLIB = lib
QMAKE_EXTENSION_STATICLIB = a # llvm bitcode
QMAKE_AR = emar cqs
QMAKE_DISTCLEAN += *.html *.js *.wasm
QT_QPA_DEFAULT_PLATFORM = wasm
QTPLUGIN.platforms = wasm
load(qt_config)

View File

@ -0,0 +1,181 @@
/****************************************************************************
**
** Copyright (C) 2018 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$
**
****************************************************************************/
#ifndef QPLATFORMDEFS_H
#define QPLATFORMDEFS_H
// Get Qt defines/settings
#include "qglobal.h"
// Set any POSIX/XOPEN defines at the top of this file to turn on specific APIs
// 1) need to reset default environment if _BSD_SOURCE is defined
// 2) need to specify POSIX thread interfaces explicitly in glibc 2.0
// 3) it seems older glibc need this to include the X/Open stuff
#include <unistd.h>
// We are hot - unistd.h should have turned on the specific APIs we requested
#include <features.h>
#include <pthread.h>
#include <dirent.h>
#include <fcntl.h>
#include <grp.h>
#include <pwd.h>
#include <signal.h>
#include <dlfcn.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/ipc.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/wait.h>
#ifndef QT_NO_IPV6IFNAME
#include <net/if.h>
#endif
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#ifdef QT_LARGEFILE_SUPPORT
#define QT_STATBUF struct stat64
#define QT_STATBUF4TSTAT struct stat64
#define QT_STAT ::stat64
#define QT_FSTAT ::fstat64
#define QT_LSTAT ::lstat64
#define QT_OPEN ::open64
#define QT_TRUNCATE ::truncate64
#define QT_FTRUNCATE ::ftruncate64
#define QT_LSEEK ::lseek64
#else
#define QT_STATBUF struct stat
#define QT_STATBUF4TSTAT struct stat
#define QT_STAT ::stat
#define QT_FSTAT ::fstat
#define QT_LSTAT ::lstat
#define QT_OPEN ::open
#define QT_TRUNCATE ::truncate
#define QT_FTRUNCATE ::ftruncate
#define QT_LSEEK ::lseek
#endif
#ifdef QT_LARGEFILE_SUPPORT
#define QT_FOPEN ::fopen64
#define QT_FSEEK ::fseeko64
#define QT_FTELL ::ftello64
#define QT_FGETPOS ::fgetpos64
#define QT_FSETPOS ::fsetpos64
#define QT_MMAP ::mmap64
#define QT_FPOS_T fpos64_t
#define QT_OFF_T off64_t
#else
#define QT_FOPEN ::fopen
#define QT_FSEEK ::fseek
#define QT_FTELL ::ftell
#define QT_FGETPOS ::fgetpos
#define QT_FSETPOS ::fsetpos
#define QT_MMAP ::mmap
#define QT_FPOS_T fpos_t
#define QT_OFF_T long
#endif
#define QT_STAT_REG S_IFREG
#define QT_STAT_DIR S_IFDIR
#define QT_STAT_MASK S_IFMT
#define QT_STAT_LNK S_IFLNK
#define QT_SOCKET_CONNECT ::connect
#define QT_SOCKET_BIND ::bind
#define QT_FILENO fileno
#define QT_CLOSE ::close
#define QT_READ ::read
#define QT_WRITE ::write
#define QT_ACCESS ::access
#define QT_GETCWD ::getcwd
#define QT_CHDIR ::chdir
#define QT_MKDIR ::mkdir
#define QT_RMDIR ::rmdir
#define QT_OPEN_LARGEFILE O_LARGEFILE
#define QT_OPEN_RDONLY O_RDONLY
#define QT_OPEN_WRONLY O_WRONLY
#define QT_OPEN_RDWR O_RDWR
#define QT_OPEN_CREAT O_CREAT
#define QT_OPEN_TRUNC O_TRUNC
#define QT_OPEN_APPEND O_APPEND
#define QT_OPEN_EXCL O_EXCL
// Directory iteration
#define QT_DIR DIR
#define QT_OPENDIR ::opendir
#define QT_CLOSEDIR ::closedir
#if defined(QT_LARGEFILE_SUPPORT) \
&& defined(QT_USE_XOPEN_LFS_EXTENSIONS) \
&& !defined(QT_NO_READDIR64)
#define QT_DIRENT struct dirent64
#define QT_READDIR ::readdir64
#define QT_READDIR_R ::readdir64_r
#else
#define QT_DIRENT struct dirent
#define QT_READDIR ::readdir
#define QT_READDIR_R ::readdir_r
#endif
#define QT_SOCKET_CONNECT ::connect
#define QT_SOCKET_BIND ::bind
#define QT_SIGNAL_RETTYPE void
#define QT_SIGNAL_ARGS int
#define QT_SIGNAL_IGNORE SIG_IGN
#define QT_SOCKLEN_T socklen_t
#if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)
#define QT_SNPRINTF ::snprintf
#define QT_VSNPRINTF ::vsnprintf
#endif
#endif // QPLATFORMDEFS_H

View File

@ -1102,18 +1102,7 @@ MakefileGenerator::write()
QString
MakefileGenerator::prlFileName(bool fixify)
{
QString ret = project->first("TARGET_PRL").toQString();
if(ret.isEmpty())
ret = project->first("TARGET").toQString();
int slsh = ret.lastIndexOf(Option::dir_sep);
if(slsh != -1)
ret.remove(0, slsh);
if(!ret.endsWith(Option::prl_ext)) {
int dot = ret.indexOf('.');
if(dot != -1)
ret.truncate(dot);
ret += Option::prl_ext;
}
QString ret = project->first("PRL_TARGET") + Option::prl_ext;
if(!project->isEmpty("QMAKE_BUNDLE"))
ret.prepend(project->first("QMAKE_BUNDLE") + Option::dir_sep);
if(fixify) {

View File

@ -1244,7 +1244,8 @@ void UnixMakefileGenerator::init2()
if(!project->isEmpty("TARGET"))
project->values("TARGET").first().prepend(project->first("DESTDIR"));
} else if (project->isActiveConfig("staticlib")) {
project->values("TARGET").first().prepend(project->first("QMAKE_PREFIX_STATICLIB"));
project->values("PRL_TARGET") =
project->values("TARGET").first().prepend(project->first("QMAKE_PREFIX_STATICLIB"));
project->values("TARGET").first() += "." + project->first("QMAKE_EXTENSION_STATICLIB");
if(project->values("QMAKE_AR_CMD").isEmpty())
project->values("QMAKE_AR_CMD").append("$(AR) $(DESTDIR)$(TARGET) $(OBJECTS)");
@ -1278,6 +1279,7 @@ void UnixMakefileGenerator::init2()
QString prefix;
if(!project->isActiveConfig("no_plugin_name_prefix"))
prefix = "lib";
project->values("PRL_TARGET").prepend(prefix + project->first("TARGET"));
project->values("TARGET_x.y.z").append(prefix +
project->first("TARGET") + "." +
project->first("QMAKE_EXTENSION_PLUGIN"));
@ -1291,6 +1293,7 @@ void UnixMakefileGenerator::init2()
"." + project->first("VER_MAJ"));
project->values("TARGET") = project->values("TARGET_x.y.z");
} else if (!project->isEmpty("QMAKE_HPUX_SHLIB")) {
project->values("PRL_TARGET").prepend("lib" + project->first("TARGET"));
project->values("TARGET_").append("lib" + project->first("TARGET") + ".sl");
if(project->isActiveConfig("lib_version_first"))
project->values("TARGET_x").append("lib" + project->first("VER_MAJ") + "." +
@ -1300,6 +1303,7 @@ void UnixMakefileGenerator::init2()
project->first("VER_MAJ"));
project->values("TARGET") = project->values("TARGET_x");
} else if (!project->isEmpty("QMAKE_AIX_SHLIB")) {
project->values("PRL_TARGET").prepend("lib" + project->first("TARGET"));
project->values("TARGET_").append(project->first("QMAKE_PREFIX_STATICLIB") + project->first("TARGET")
+ "." + project->first("QMAKE_EXTENSION_STATICLIB"));
if(project->isActiveConfig("lib_version_first")) {
@ -1331,6 +1335,7 @@ void UnixMakefileGenerator::init2()
}
project->values("TARGET") = project->values("TARGET_x.y.z");
} else {
project->values("PRL_TARGET").prepend("lib" + project->first("TARGET"));
project->values("TARGET_").append("lib" + project->first("TARGET") + "." +
project->first("QMAKE_EXTENSION_SHLIB"));
if(project->isActiveConfig("lib_version_first")) {

View File

@ -204,8 +204,6 @@ void MingwMakefileGenerator::init()
return;
}
project->values("TARGET_PRL").append(project->first("TARGET"));
processVars();
project->values("QMAKE_LIBS") += project->values("RES_FILE");

View File

@ -185,7 +185,8 @@ void Win32MakefileGenerator::processVars()
if (project->first("TEMPLATE").endsWith("aux"))
return;
project->values("QMAKE_ORIG_TARGET") = project->values("TARGET");
project->values("PRL_TARGET") =
project->values("QMAKE_ORIG_TARGET") = project->values("TARGET");
if (project->isEmpty("QMAKE_PROJECT_NAME"))
project->values("QMAKE_PROJECT_NAME") = project->values("QMAKE_ORIG_TARGET");
else if (project->first("TEMPLATE").startsWith("vc"))

View File

@ -77,7 +77,7 @@ inline void abort_noreturn() { abort(); }
defined(__SH4__) || defined(__alpha__) || \
defined(_MIPS_ARCH_MIPS32R2) || \
defined(__AARCH64EL__) || defined(__aarch64__) || \
defined(__riscv)
defined(__riscv) || defined(__EMSCRIPTEN__)
#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
#elif defined(__mc68000__)
#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS

View File

@ -27,6 +27,75 @@
#include "compilersupport_p.h"
#ifndef CBOR_NO_FLOATING_POINT
# include <float.h>
# include <math.h>
#else
# ifndef CBOR_NO_HALF_FLOAT_TYPE
# define CBOR_NO_HALF_FLOAT_TYPE 1
# endif
#endif
#ifndef CBOR_NO_HALF_FLOAT_TYPE
# ifdef __F16C__
# include <immintrin.h>
static inline unsigned short encode_half(double val)
{
return _cvtss_sh((float)val, 3);
}
static inline double decode_half(unsigned short half)
{
return _cvtsh_ss(half);
}
# else
/* software implementation of float-to-fp16 conversions */
static inline unsigned short encode_half(double val)
{
uint64_t v;
int sign, exp, mant;
memcpy(&v, &val, sizeof(v));
sign = v >> 63 << 15;
exp = (v >> 52) & 0x7ff;
mant = v << 12 >> 12 >> (53-11); /* keep only the 11 most significant bits of the mantissa */
exp -= 1023;
if (exp == 1024) {
/* infinity or NaN */
exp = 16;
mant >>= 1;
} else if (exp >= 16) {
/* overflow, as largest number */
exp = 15;
mant = 1023;
} else if (exp >= -14) {
/* regular normal */
} else if (exp >= -24) {
/* subnormal */
mant |= 1024;
mant >>= -(exp + 14);
exp = -15;
} else {
/* underflow, make zero */
return 0;
}
/* safe cast here as bit operations above guarantee not to overflow */
return (unsigned short)(sign | ((exp + 15) << 10) | mant);
}
/* this function was copied & adapted from RFC 7049 Appendix D */
static inline double decode_half(unsigned short half)
{
int exp = (half >> 10) & 0x1f;
int mant = half & 0x3ff;
double val;
if (exp == 0) val = ldexp(mant, -24);
else if (exp != 31) val = ldexp(mant + 1024, exp - 25);
else val = mant == 0 ? INFINITY : NAN;
return half & 0x8000 ? -val : val;
}
# endif
#endif /* CBOR_NO_HALF_FLOAT_TYPE */
#ifndef CBOR_INTERNAL_API
# define CBOR_INTERNAL_API
#endif

View File

@ -36,8 +36,6 @@
#ifndef assert
# include <assert.h>
#endif
#include <float.h>
#include <math.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
@ -46,10 +44,6 @@
# include <stdbool.h>
#endif
#ifdef __F16C__
# include <immintrin.h>
#endif
#if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L || __cpp_static_assert >= 200410
# define cbor_static_assert(x) static_assert(x, #x)
#elif !defined(__cplusplus) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406) && (__STDC_VERSION__ > 199901L)
@ -207,58 +201,5 @@ static inline bool add_check_overflow(size_t v1, size_t v2, size_t *r)
#endif
}
static inline unsigned short encode_half(double val)
{
#ifdef __F16C__
return _cvtss_sh((float)val, 3);
#else
uint64_t v;
int sign, exp, mant;
memcpy(&v, &val, sizeof(v));
sign = v >> 63 << 15;
exp = (v >> 52) & 0x7ff;
mant = v << 12 >> 12 >> (53-11); /* keep only the 11 most significant bits of the mantissa */
exp -= 1023;
if (exp == 1024) {
/* infinity or NaN */
exp = 16;
mant >>= 1;
} else if (exp >= 16) {
/* overflow, as largest number */
exp = 15;
mant = 1023;
} else if (exp >= -14) {
/* regular normal */
} else if (exp >= -24) {
/* subnormal */
mant |= 1024;
mant >>= -(exp + 14);
exp = -15;
} else {
/* underflow, make zero */
return 0;
}
/* safe cast here as bit operations above guarantee not to overflow */
return (unsigned short)(sign | ((exp + 15) << 10) | mant);
#endif
}
/* this function was copied & adapted from RFC 7049 Appendix D */
static inline double decode_half(unsigned short half)
{
#ifdef __F16C__
return _cvtsh_ss(half);
#else
int exp = (half >> 10) & 0x1f;
int mant = half & 0x3ff;
double val;
if (exp == 0) val = ldexp(mant, -24);
else if (exp != 31) val = ldexp(mant + 1024, exp - 25);
else val = mant == 0 ? INFINITY : NAN;
return half & 0x8000 ? -val : val;
#endif
}
#endif /* COMPILERSUPPORT_H */

BIN
src/3rdparty/wasm/DejaVuSans.ttf vendored Normal file

Binary file not shown.

15
src/3rdparty/wasm/LICENSE vendored Normal file
View File

@ -0,0 +1,15 @@
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license (“Fonts”) and associated documentation files (the “Font Software”), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions:
The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces.
The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words “Bitstream” or the word “Vera”.
This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the “Bitstream Vera” names.
The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself.
THE FONT SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
Except as contained in this notice, the names of GNOME, the GNOME Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the GNOME Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org.

BIN
src/3rdparty/wasm/Vera.ttf vendored Normal file

Binary file not shown.

21
src/3rdparty/wasm/qt_attribution.json vendored Normal file
View File

@ -0,0 +1,21 @@
{
"Id": "vera_font",
"Name": "Vera",
"QDocModule": "qtcore",
"QtUsage": "Used for WebAssembly platform.",
"License": "Bitstream",
"LicenseFile": "LICENSE",
"Copyright": "Copyright (C) 2003 Bitstream,Inc"
},
{
"Id": "dejayvu",
"Name": "DejaVuSans",
"QDocModule": "qtcore",
"QtUsage": "Used for WebAssembly platform.",
"License": "Bitstream",
"LicenseFile": "LICENSE",
"Copyright": "Copyright (C) 2003 Bitstream,Inc"
}

View File

@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_TEXTCODEC
#if defined(Q_OS_MAC) || defined(Q_OS_ANDROID) || defined(Q_OS_QNX)
#if defined(Q_OS_MAC) || defined(Q_OS_ANDROID) || defined(Q_OS_QNX) || defined(Q_OS_WASM)
#define QT_LOCALE_IS_UTF8
#endif

View File

@ -481,7 +481,7 @@
},
"eventfd": {
"label": "eventfd",
"condition": "tests.eventfd",
"condition": "!config.wasm && tests.eventfd",
"output": [ "feature" ]
},
"futimens": {
@ -592,7 +592,7 @@
"poll_ppoll": {
"label": "Native ppoll()",
"emitIf": "!config.win32",
"condition": "tests.ppoll",
"condition": "!config.wasm && tests.ppoll",
"output": [ "privateFeature" ]
},
"poll_pollts": {

View File

@ -51,6 +51,8 @@
# define ARCH_PROCESSOR "avr32"
#elif defined(Q_PROCESSOR_BLACKFIN)
# define ARCH_PROCESSOR "bfin"
#elif defined(Q_PROCESSOR_WASM)
# define ARCH_PROCESSOR "wasm"
#elif defined(Q_PROCESSOR_X86_32)
# define ARCH_PROCESSOR "i386"
#elif defined(Q_PROCESSOR_X86_64)

View File

@ -206,6 +206,9 @@
# define Q_DECL_NS_RETURNS_AUTORELEASED __attribute__((ns_returns_autoreleased))
# endif
# endif
# ifdef __EMSCRIPTEN__
# define Q_CC_EMSCRIPTEN
# endif
# else
/* Plain GCC */
# if Q_CC_GNU >= 405

View File

@ -94,6 +94,10 @@
# include "private/qcore_unix_p.h"
#endif
#ifdef Q_OS_WASM
#include <emscripten/emscripten.h>
#endif
#if QT_CONFIG(regularexpression)
# ifdef __UCLIBC__
# if __UCLIBC_HAS_BACKTRACE__
@ -1690,6 +1694,37 @@ static bool win_message_handler(QtMsgType type, const QMessageLogContext &contex
}
#endif
#ifdef Q_OS_WASM
static bool wasm_default_message_handler(QtMsgType type,
const QMessageLogContext &context,
const QString &message)
{
if (shouldLogToStderr())
return false; // Leave logging up to stderr handler
QString formattedMessage = qFormatLogMessage(type, context, message);
int emOutputFlags = (EM_LOG_CONSOLE | EM_LOG_DEMANGLE);
QByteArray localMsg = message.toLocal8Bit();
switch (type) {
case QtDebugMsg:
break;
case QtInfoMsg:
break;
case QtWarningMsg:
emOutputFlags |= EM_LOG_WARN;
break;
case QtCriticalMsg:
emOutputFlags |= EM_LOG_ERROR;
break;
case QtFatalMsg:
emOutputFlags |= EM_LOG_ERROR;
}
emscripten_log(emOutputFlags, "%s\n", qPrintable(formattedMessage));
return true; // Prevent further output to stderr
}
#endif
#endif // Bootstrap check
// --------------------------------------------------------------------------
@ -1733,8 +1768,9 @@ static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &con
# elif defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
handledStderr |= android_default_message_handler(type, context, message);
# elif defined(QT_USE_APPLE_UNIFIED_LOGGING)
if (__builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *))
handledStderr |= AppleUnifiedLogger::messageHandler(type, context, message);
handledStderr |= AppleUnifiedLogger::messageHandler(type, context, message);
# elif defined Q_OS_WASM
handledStderr |= wasm_default_message_handler(type, context, message);
# endif
#endif

View File

@ -103,7 +103,7 @@ static inline OSVERSIONINFOEX determineWinOsVersion()
// GetVersionEx() has been deprecated in Windows 8.1 and will return
// only Windows 8 from that version on, so use the kernel API function.
pRtlGetVersion((LPOSVERSIONINFO) &result); // always returns STATUS_SUCCESS
pRtlGetVersion(reinterpret_cast<LPOSVERSIONINFO>(&result)); // always returns STATUS_SUCCESS
#else // !Q_OS_WINCE
GetVersionEx(&result);
#endif

View File

@ -320,6 +320,12 @@
# endif
# define Q_BYTE_ORDER Q_BIG_ENDIAN
// -- Web Assembly --
#elif defined(__EMSCRIPTEN__)
# define Q_PROCESSOR_WASM
# define Q_PROCESSOR_X86 6 // enables SIMD support
# define Q_BYTE_ORDER Q_LITTLE_ENDIAN
# define Q_PROCESSOR_WORDSIZE 8
#endif
/*

View File

@ -137,6 +137,8 @@
# define Q_OS_HPUX
#elif defined(__native_client__)
# define Q_OS_NACL
#elif defined(__EMSCRIPTEN__)
# define Q_OS_WASM
#elif defined(__linux__) || defined(__linux)
# define Q_OS_LINUX
#elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)

View File

@ -76,9 +76,7 @@
#endif
#if defined(Q_OS_DARWIN)
# if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(101200, 100000, 100000, 30000)
# include <sys/clonefile.h>
# endif
# include <sys/clonefile.h>
# include <copyfile.h>
// We cannot include <Foundation/Foundation.h> (it's an Objective-C header), but
// we need these declarations:
@ -860,7 +858,7 @@ QString QFileSystemEngine::resolveUserName(uint userId)
QVarLengthArray<char, 1024> buf(size_max);
#endif
#if !defined(Q_OS_INTEGRITY)
#if !defined(Q_OS_INTEGRITY) && !defined(Q_OS_WASM)
struct passwd *pw = 0;
#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_VXWORKS)
struct passwd entry;
@ -884,7 +882,7 @@ QString QFileSystemEngine::resolveGroupName(uint groupId)
QVarLengthArray<char, 1024> buf(size_max);
#endif
#if !defined(Q_OS_INTEGRITY)
#if !defined(Q_OS_INTEGRITY) && !defined(Q_OS_WASM)
struct group *gr = 0;
#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_VXWORKS) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID) && (__ANDROID_API__ >= 24))
size_max = sysconf(_SC_GETGR_R_SIZE_MAX);
@ -1258,20 +1256,18 @@ bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSy
//static
bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
{
#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(101200, 100000, 100000, 30000)
if (__builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *)) {
if (::clonefile(source.nativeFilePath().constData(),
target.nativeFilePath().constData(), 0) == 0)
return true;
error = QSystemError(errno, QSystemError::StandardLibraryError);
return false;
}
#if defined(Q_OS_DARWIN)
if (::clonefile(source.nativeFilePath().constData(),
target.nativeFilePath().constData(), 0) == 0)
return true;
error = QSystemError(errno, QSystemError::StandardLibraryError);
return false;
#else
Q_UNUSED(source);
Q_UNUSED(target);
#endif
error = QSystemError(ENOSYS, QSystemError::StandardLibraryError); //Function not implemented
return false;
#endif
}
//static
@ -1295,13 +1291,11 @@ bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSy
}
#endif
#if defined(Q_OS_DARWIN) && defined(RENAME_EXCL)
if (__builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *)) {
if (renameatx_np(AT_FDCWD, srcPath, AT_FDCWD, tgtPath, RENAME_EXCL) == 0)
return true;
if (errno != ENOTSUP) {
error = QSystemError(errno, QSystemError::StandardLibraryError);
return false;
}
if (renameatx_np(AT_FDCWD, srcPath, AT_FDCWD, tgtPath, RENAME_EXCL) == 0)
return true;
if (errno != ENOTSUP) {
error = QSystemError(errno, QSystemError::StandardLibraryError);
return false;
}
#endif

View File

@ -935,7 +935,7 @@ static bool tryFindFallback(const QFileSystemEntry &fname, QFileSystemMetaData &
bool QFileSystemEngine::fillMetaData(int fd, QFileSystemMetaData &data,
QFileSystemMetaData::MetaDataFlags what)
{
HANDLE fHandle = (HANDLE)_get_osfhandle(fd);
auto fHandle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
if (fHandle != INVALID_HANDLE_VALUE) {
return fillMetaData(fHandle, data, what);
}
@ -1014,7 +1014,8 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
WIN32_FIND_DATA findData;
// The memory structure for WIN32_FIND_DATA is same as WIN32_FILE_ATTRIBUTE_DATA
// for all members used by fillFindData().
bool ok = ::GetFileAttributesEx((wchar_t*)fname.nativeFilePath().utf16(), GetFileExInfoStandard,
bool ok = ::GetFileAttributesEx(reinterpret_cast<const wchar_t*>(fname.nativeFilePath().utf16()),
GetFileExInfoStandard,
reinterpret_cast<WIN32_FILE_ATTRIBUTE_DATA *>(&findData));
if (ok) {
data.fillFromFindData(findData, false, fname.isDriveRoot());
@ -1069,19 +1070,22 @@ static bool isDirPath(const QString &dirPath, bool *existed)
if (path.length() == 2 && path.at(1) == QLatin1Char(':'))
path += QLatin1Char('\\');
const QString longPath = QFSFileEnginePrivate::longFileName(path);
#ifndef Q_OS_WINRT
DWORD fileAttrib = ::GetFileAttributes((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16());
DWORD fileAttrib = ::GetFileAttributes(reinterpret_cast<const wchar_t*>(longPath.utf16()));
#else // Q_OS_WINRT
DWORD fileAttrib = INVALID_FILE_ATTRIBUTES;
WIN32_FILE_ATTRIBUTE_DATA data;
if (::GetFileAttributesEx((const wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(), GetFileExInfoStandard, &data))
if (::GetFileAttributesEx(reinterpret_cast<const wchar_t*>(longPath.utf16()),
GetFileExInfoStandard, &data)) {
fileAttrib = data.dwFileAttributes;
}
#endif // Q_OS_WINRT
if (fileAttrib == INVALID_FILE_ATTRIBUTES) {
int errorCode = GetLastError();
if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) {
WIN32_FIND_DATA findData;
if (getFindData(QFSFileEnginePrivate::longFileName(path), findData))
if (getFindData(longPath, findData))
fileAttrib = findData.dwFileAttributes;
}
}
@ -1411,7 +1415,7 @@ bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Per
if (mode == 0) // not supported
return false;
bool ret = (::_wchmod((wchar_t*)entry.nativeFilePath().utf16(), mode) == 0);
bool ret = ::_wchmod(reinterpret_cast<const wchar_t*>(entry.nativeFilePath().utf16()), mode) == 0;
if(!ret)
error = QSystemError(errno, QSystemError::StandardLibraryError);
return ret;

View File

@ -77,6 +77,10 @@
# include <ioLib.h>
#endif
#ifdef Q_OS_WASM
#include <emscripten.h>
#endif
#include <algorithm>
#include <stdlib.h>
@ -1544,6 +1548,13 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
perms |= QFile::ReadGroup | QFile::ReadOther;
QFile(confFile->name).setPermissions(perms);
}
#ifdef Q_OS_WASM
EM_ASM(
// Sync sandbox filesystem to persistent database filesystem. See QTBUG-70002
FS.syncfs(false, function(err) {
});
);
#endif
} else {
setStatus(QSettings::AccessError);
}

View File

@ -515,7 +515,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa
case REG_SZ: {
QString s;
if (dataSize) {
s = QString::fromWCharArray(((const wchar_t *)data.constData()));
s = QString::fromWCharArray(reinterpret_cast<const wchar_t *>(data.constData()));
}
if (value != 0)
*value = stringToVariant(s);
@ -527,7 +527,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa
if (dataSize) {
int i = 0;
for (;;) {
QString s = QString::fromWCharArray((const wchar_t *)data.constData() + i);
QString s = QString::fromWCharArray(reinterpret_cast<const wchar_t *>(data.constData()) + i);
i += s.length() + 1;
if (s.isEmpty())
@ -544,7 +544,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa
case REG_BINARY: {
QString s;
if (dataSize) {
s = QString::fromWCharArray((const wchar_t *)data.constData(), data.size() / 2);
s = QString::fromWCharArray(reinterpret_cast<const wchar_t *>(data.constData()), data.size() / 2);
}
if (value != 0)
*value = stringToVariant(s);
@ -555,7 +555,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa
case REG_DWORD: {
Q_ASSERT(data.size() == sizeof(int));
int i;
memcpy((char*)&i, data.constData(), sizeof(int));
memcpy(reinterpret_cast<char*>(&i), data.constData(), sizeof(int));
if (value != 0)
*value = i;
break;
@ -564,7 +564,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa
case REG_QWORD: {
Q_ASSERT(data.size() == sizeof(qint64));
qint64 i;
memcpy((char*)&i, data.constData(), sizeof(qint64));
memcpy(reinterpret_cast<char*>(&i), data.constData(), sizeof(qint64));
if (value != 0)
*value = i;
break;
@ -688,12 +688,12 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value)
if (type == REG_BINARY) {
QString s = variantToString(value);
regValueBuff = QByteArray((const char*)s.utf16(), s.length() * 2);
regValueBuff = QByteArray(reinterpret_cast<const char*>(s.utf16()), s.length() * 2);
} else {
QStringList::const_iterator it = l.constBegin();
for (; it != l.constEnd(); ++it) {
const QString &s = *it;
regValueBuff += QByteArray((const char*)s.utf16(), (s.length() + 1) * 2);
regValueBuff += QByteArray(reinterpret_cast<const char*>(s.utf16()), (s.length() + 1) * 2);
}
regValueBuff.append((char)0);
regValueBuff.append((char)0);
@ -705,7 +705,7 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value)
case QVariant::UInt: {
type = REG_DWORD;
qint32 i = value.toInt();
regValueBuff = QByteArray((const char*)&i, sizeof(qint32));
regValueBuff = QByteArray(reinterpret_cast<const char*>(&i), sizeof(qint32));
break;
}
@ -713,7 +713,7 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value)
case QVariant::ULongLong: {
type = REG_QWORD;
qint64 i = value.toLongLong();
regValueBuff = QByteArray((const char*)&i, sizeof(qint64));
regValueBuff = QByteArray(reinterpret_cast<const char*>(&i), sizeof(qint64));
break;
}
@ -725,11 +725,11 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value)
// string type. Otherwise we use REG_BINARY.
QString s = variantToString(value);
type = s.contains(QChar::Null) ? REG_BINARY : REG_SZ;
if (type == REG_BINARY) {
regValueBuff = QByteArray((const char*)s.utf16(), s.length() * 2);
} else {
regValueBuff = QByteArray((const char*)s.utf16(), (s.length() + 1) * 2);
}
int length = s.length();
if (type == REG_SZ)
++length;
regValueBuff = QByteArray(reinterpret_cast<const char *>(s.utf16()),
int(sizeof(wchar_t)) * length);
break;
}
}

View File

@ -59,36 +59,6 @@
// --------------------------------------------------------------------------
#if !defined(QT_BOOTSTRAPPED) && (QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_12) || !defined(Q_OS_MACOS))
#define QT_USE_APPLE_ACTIVITIES
#if defined(OS_ACTIVITY_OBJECT_API)
#error The file <os/activity.h> has already been included
#endif
// We runtime-check all use of the activity APIs, so we can safely build
// with them included, even if the deployment target is macOS 10.11
#if QT_MACOS_DEPLOYMENT_TARGET_BELOW(__MAC_10_12)
#undef __MAC_OS_X_VERSION_MIN_REQUIRED
#define __MAC_OS_X_VERSION_MIN_REQUIRED __MAC_10_12
#define DID_OVERRIDE_DEPLOYMENT_TARGET
#endif
#include <os/activity.h>
#if !OS_ACTIVITY_OBJECT_API
#error "Expected activity API to be available"
#endif
#if defined(DID_OVERRIDE_DEPLOYMENT_TARGET)
#undef __MAC_OS_X_VERSION_MIN_REQUIRED
#define __MAC_OS_X_VERSION_MIN_REQUIRED __MAC_10_11
#undef DID_OVERRIDE_DEPLOYMENT_TARGET
#endif
#endif
// --------------------------------------------------------------------------
#if defined(QT_BOOTSTRAPPED)
#include <ApplicationServices/ApplicationServices.h>
#else
@ -220,41 +190,31 @@ Q_CORE_EXPORT AppleApplication *qt_apple_sharedApplication();
// --------------------------------------------------------------------------
#if !defined(QT_BOOTSTRAPPED) && (QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_12) || !defined(Q_OS_MACOS))
#if !defined(QT_BOOTSTRAPPED)
#define QT_USE_APPLE_UNIFIED_LOGGING
QT_END_NAMESPACE
#include <os/log.h>
// The compiler isn't smart enough to realize that we're calling these functions
// guarded by __builtin_available, so we need to also tag each function with the
// runtime requirements.
#include <os/availability.h>
#define OS_LOG_AVAILABILITY API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT AppleUnifiedLogger
{
public:
static bool messageHandler(QtMsgType msgType, const QMessageLogContext &context, const QString &message,
const QString &subsystem = QString()) OS_LOG_AVAILABILITY;
const QString &subsystem = QString());
private:
static os_log_type_t logTypeForMessageType(QtMsgType msgType) OS_LOG_AVAILABILITY;
static os_log_t cachedLog(const QString &subsystem, const QString &category) OS_LOG_AVAILABILITY;
static os_log_type_t logTypeForMessageType(QtMsgType msgType);
static os_log_t cachedLog(const QString &subsystem, const QString &category);
};
#undef OS_LOG_AVAILABILITY
#endif
// --------------------------------------------------------------------------
#if defined(QT_USE_APPLE_ACTIVITIES)
#if !defined(QT_BOOTSTRAPPED)
QT_END_NAMESPACE
#include <os/availability.h>
#define OS_ACTIVITY_AVAILABILITY API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
#define OS_ACTIVITY_AVAILABILITY_CHECK __builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *)
#include <os/activity.h>
QT_BEGIN_NAMESPACE
template <typename T> using QAppleOsType = QAppleRefCounted<T, void *, os_retain, os_release>;
@ -263,7 +223,7 @@ class Q_CORE_EXPORT QAppleLogActivity
{
public:
QAppleLogActivity() : activity(nullptr) {}
QAppleLogActivity(os_activity_t activity) OS_ACTIVITY_AVAILABILITY : activity(activity) {}
QAppleLogActivity(os_activity_t activity) : activity(activity) {}
~QAppleLogActivity() { if (activity) leave(); }
QAppleLogActivity(const QAppleLogActivity &) = delete;
@ -284,21 +244,17 @@ public:
QAppleLogActivity&& enter()
{
if (activity) {
if (OS_ACTIVITY_AVAILABILITY_CHECK)
os_activity_scope_enter(static_cast<os_activity_t>(*this), &state);
}
if (activity)
os_activity_scope_enter(static_cast<os_activity_t>(*this), &state);
return std::move(*this);
}
void leave() {
if (activity) {
if (OS_ACTIVITY_AVAILABILITY_CHECK)
os_activity_scope_leave(&state);
}
if (activity)
os_activity_scope_leave(&state);
}
operator os_activity_t() OS_ACTIVITY_AVAILABILITY
operator os_activity_t()
{
return reinterpret_cast<os_activity_t>(static_cast<void *>(activity));
}
@ -312,9 +268,7 @@ private:
#define QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, parent) []() { \
if (!(condition)) \
return QAppleLogActivity(); \
if (OS_ACTIVITY_AVAILABILITY_CHECK) \
return QAppleLogActivity(os_activity_create(description, parent, OS_ACTIVITY_FLAG_DEFAULT)); \
return QAppleLogActivity(); \
return QAppleLogActivity(os_activity_create(description, parent, OS_ACTIVITY_FLAG_DEFAULT)); \
}()
#define QT_VA_ARGS_CHOOSE(_1, _2, _3, _4, _5, _6, _7, _8, _9, N, ...) N
@ -335,12 +289,7 @@ QT_MAC_WEAK_IMPORT(_os_activity_current);
#define QT_APPLE_SCOPED_LOG_ACTIVITY(...) QAppleLogActivity scopedLogActivity = QT_APPLE_LOG_ACTIVITY(__VA_ARGS__).enter();
#else
// No-ops for macOS 10.11. We don't need to provide QT_APPLE_SCOPED_LOG_ACTIVITY,
// as all the call sites for that are in code that's only built on 10.12 and above.
#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT(...)
#define QT_APPLE_LOG_ACTIVITY(...)
#endif // QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE
#endif // !defined(QT_BOOTSTRAPPED)
// -------------------------------------------------------------------------

View File

@ -118,6 +118,10 @@
# include <taskLib.h>
#endif
#ifdef Q_OS_WASM
#include <emscripten.h>
#endif
#ifdef QT_BOOTSTRAPPED
#include <private/qtrace_p.h>
#else
@ -486,6 +490,13 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint
QCoreApplicationPrivate::~QCoreApplicationPrivate()
{
#ifdef Q_OS_WASM
EM_ASM(
// unmount persistent directory as IDBFS
// see also QTBUG-70002
FS.unmount('/home/web_user');
);
#endif
#ifndef QT_NO_QOBJECT
cleanupThreadData();
#endif
@ -777,6 +788,17 @@ void QCoreApplicationPrivate::init()
Q_ASSERT_X(!QCoreApplication::self, "QCoreApplication", "there should be only one application object");
QCoreApplication::self = q;
#ifdef Q_OS_WASM
EM_ASM(
// mount and sync persistent filesystem to sandbox
FS.mount(IDBFS, {}, '/home/web_user');
FS.syncfs(true, function(err) {
if (err)
Module.print(err);
});
);
#endif
// Store app name/version (so they're still available after QCoreApplication is destroyed)
if (!coreappdata()->applicationNameSet)
coreappdata()->application = appName();

View File

@ -130,7 +130,7 @@ static void initThreadPipeFD(int fd)
bool QThreadPipe::init()
{
#if defined(Q_OS_NACL)
#if defined(Q_OS_NACL) || defined(Q_OS_WASM)
// do nothing.
#elif defined(Q_OS_VXWORKS)
qsnprintf(name, sizeof(name), "/pipe/qt_%08x", int(taskIdSelf()));

View File

@ -120,7 +120,7 @@ void WINAPI QT_WIN_CALLBACK qt_fast_timer_proc(uint timerId, uint /*reserved*/,
{
if (!timerId) // sanity check
return;
WinTimerInfo *t = (WinTimerInfo*)user;
auto t = reinterpret_cast<WinTimerInfo*>(user);
Q_ASSERT(t);
QCoreApplication::postEvent(t->dispatcher, new QTimerEvent(t->timerId));
}
@ -146,9 +146,9 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
}
#ifdef GWLP_USERDATA
QEventDispatcherWin32 *q = (QEventDispatcherWin32 *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
auto q = reinterpret_cast<QEventDispatcherWin32 *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
#else
QEventDispatcherWin32 *q = (QEventDispatcherWin32 *) GetWindowLong(hwnd, GWL_USERDATA);
auto q = reinterpret_cast<QEventDispatcherWin32 *>(GetWindowLong(hwnd, GWL_USERDATA));
#endif
QEventDispatcherWin32Private *d = 0;
if (q != 0)
@ -369,9 +369,9 @@ static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatch
}
#ifdef GWLP_USERDATA
SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)eventDispatcher);
SetWindowLongPtr(wnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(eventDispatcher));
#else
SetWindowLong(wnd, GWL_USERDATA, (LONG)eventDispatcher);
SetWindowLong(wnd, GWL_USERDATA, reinterpret_cast<LONG>(eventDispatcher));
#endif
return wnd;
@ -603,7 +603,7 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
if (haveMessage) {
// WinCE doesn't support hooks at all, so we have to call this by hand :(
if (!d->getMessageHook)
(void) qt_GetMessageHook(0, PM_REMOVE, (LPARAM) &msg);
(void) qt_GetMessageHook(0, PM_REMOVE, reinterpret_cast<LPARAM>(&msg));
if (d->internalHwnd == msg.hwnd && msg.message == WM_QT_SENDPOSTEDEVENTS) {
if (seenWM_QT_SENDPOSTEDEVENTS) {

View File

@ -48,6 +48,10 @@
#include "qeventloop_p.h"
#include <private/qthread_p.h>
#ifdef Q_OS_WASM
#include <emscripten.h>
#endif
QT_BEGIN_NAMESPACE
/*!
@ -208,6 +212,15 @@ int QEventLoop::exec(ProcessEventsFlags flags)
if (app && app->thread() == thread())
QCoreApplication::removePostedEvents(app, QEvent::Quit);
#ifdef Q_OS_WASM
// Partial support for nested event loops: Make the runtime throw a JavaSrcript
// exception, which returns control to the browser while preserving the C++ stack.
// Event processing then continues as normal. The sleep call below never returns.
// QTBUG-70185
if (d->threadData->loopLevel > 1)
emscripten_sleep(1);
#endif
while (!d->exit.loadAcquire())
processEvents(flags | WaitForMoreEvents | EventLoopExec);
@ -269,6 +282,17 @@ void QEventLoop::exit(int returnCode)
d->returnCode.store(returnCode);
d->exit.storeRelease(true);
d->threadData->eventDispatcher.load()->interrupt();
#ifdef Q_OS_WASM
// QEventLoop::exec() never returns in emscripten. We implement approximate behavior here.
// QTBUG-70185
if (d->threadData->loopLevel == 1) {
emscripten_force_exit(returnCode);
} else {
d->inExec = false;
--d->threadData->loopLevel;
}
#endif
}
/*!

View File

@ -60,6 +60,8 @@
#include <QtCore/qvarlengtharray.h>
QT_BEGIN_NAMESPACE
// ### TODO Qt6: add a proper namespace with Q_NAMESPACE and use scoped enums
// A namespace and scoped are needed to avoid enum clashes
enum PropertyFlags {
Invalid = 0x00000000,
@ -103,7 +105,7 @@ enum MethodFlags {
MethodRevisioned = 0x80
};
enum MetaObjectFlags {
enum MetaObjectFlags { // keep it in sync with QMetaObjectBuilder::MetaObjectFlag enum
DynamicMetaObject = 0x01,
RequiresVariantMetaObject = 0x02,
PropertyAccessInStaticMetaCall = 0x04 // since Qt 5.5, property code is in the static metacall

View File

@ -93,8 +93,11 @@ public:
};
Q_DECLARE_FLAGS(AddMembers, AddMember)
enum MetaObjectFlag {
DynamicMetaObject = 0x01
// ### TODO Qt6: remove me and use the MetaObjectFlags enum from qmetaobject_p.h
enum MetaObjectFlag { // keep it in sync with enum MetaObjectFlags from qmetaobject_p.h
DynamicMetaObject = 0x01,
RequiresVariantMetaObject = 0x02,
PropertyAccessInStaticMetaCall = 0x04 // since Qt 5.5, property code is in the static metacall
};
Q_DECLARE_FLAGS(MetaObjectFlags, MetaObjectFlag)

View File

@ -1054,6 +1054,120 @@ int QMetaType::registerType(const char *typeName, Deleter deleter,
return registerNormalizedType(normalizedTypeName, deleter, creator, destructor, constructor, size, flags, metaObject);
}
/*!
\internal
\since 5.12
Registers a user type for marshalling, with \a typeName, a \a
\a destructor, a \a constructor, and a \a size. Returns the
type's handle, or -1 if the type could not be registered.
*/
int QMetaType::registerType(const char *typeName,
TypedDestructor destructor,
TypedConstructor constructor,
int size,
TypeFlags flags,
const QMetaObject *metaObject)
{
#ifdef QT_NO_QOBJECT
NS(QByteArray) normalizedTypeName = typeName;
#else
NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
#endif
return registerNormalizedType(normalizedTypeName, destructor, constructor, size, flags, metaObject);
}
static int registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
QMetaType::Destructor destructor,
QMetaType::Constructor constructor,
QMetaType::TypedDestructor typedDestructor,
QMetaType::TypedConstructor typedConstructor,
int size, QMetaType::TypeFlags flags, const QMetaObject *metaObject)
{
QVector<QCustomTypeInfo> *ct = customTypes();
if (!ct || normalizedTypeName.isEmpty() || (!destructor && !typedDestructor) || (!constructor && !typedConstructor))
return -1;
int idx = qMetaTypeStaticType(normalizedTypeName.constData(),
normalizedTypeName.size());
int previousSize = 0;
QMetaType::TypeFlags::Int previousFlags = 0;
if (idx == QMetaType::UnknownType) {
QWriteLocker locker(customTypesLock());
int posInVector = -1;
idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
normalizedTypeName.size(),
&posInVector);
if (idx == QMetaType::UnknownType) {
QCustomTypeInfo inf;
inf.typeName = normalizedTypeName;
#ifndef QT_NO_DATASTREAM
inf.loadOp = 0;
inf.saveOp = 0;
#endif
inf.alias = -1;
inf.typedConstructor = typedConstructor;
inf.typedDestructor = typedDestructor;
inf.constructor = constructor;
inf.destructor = destructor;
inf.size = size;
inf.flags = flags;
inf.metaObject = metaObject;
if (posInVector == -1) {
idx = ct->size() + QMetaType::User;
ct->append(inf);
} else {
idx = posInVector + QMetaType::User;
ct->data()[posInVector] = inf;
}
return idx;
}
if (idx >= QMetaType::User) {
previousSize = ct->at(idx - QMetaType::User).size;
previousFlags = ct->at(idx - QMetaType::User).flags;
// Set new/additional flags in case of old library/app.
// Ensures that older code works in conjunction with new Qt releases
// requiring the new flags.
if (flags != previousFlags) {
QCustomTypeInfo &inf = ct->data()[idx - QMetaType::User];
inf.flags |= flags;
if (metaObject)
inf.metaObject = metaObject;
}
}
}
if (idx < QMetaType::User) {
previousSize = QMetaType::sizeOf(idx);
previousFlags = QMetaType::typeFlags(idx);
}
if (Q_UNLIKELY(previousSize != size)) {
qFatal("QMetaType::registerType: Binary compatibility break "
"-- Size mismatch for type '%s' [%i]. Previously registered "
"size %i, now registering size %i.",
normalizedTypeName.constData(), idx, previousSize, size);
}
// these flags cannot change in a binary compatible way:
const int binaryCompatibilityFlag = QMetaType::PointerToQObject | QMetaType::IsEnumeration | QMetaType::SharedPointerToQObject
| QMetaType::WeakPointerToQObject | QMetaType::TrackingPointerToQObject;
if (Q_UNLIKELY((previousFlags ^ flags) & binaryCompatibilityFlag)) {
const char *msg = "QMetaType::registerType: Binary compatibility break. "
"\nType flags for type '%s' [%i] don't match. Previously "
"registered TypeFlags(0x%x), now registering TypeFlags(0x%x). ";
qFatal(msg, normalizedTypeName.constData(), idx, previousFlags, int(flags));
}
return idx;
}
/*!
\internal
@ -1085,91 +1199,34 @@ int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
\note normalizedTypeName is not checked for conformance with
Qt's normalized format, so it must already conform.
### TODO Qt6: remove me
*/
int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
Destructor destructor,
Constructor constructor,
int size, TypeFlags flags, const QMetaObject *metaObject)
{
QVector<QCustomTypeInfo> *ct = customTypes();
if (!ct || normalizedTypeName.isEmpty() || !destructor || !constructor)
return -1;
return NS(registerNormalizedType)(normalizedTypeName, destructor, constructor, nullptr, nullptr, size, flags, metaObject);
}
int idx = qMetaTypeStaticType(normalizedTypeName.constData(),
normalizedTypeName.size());
/*!
\internal
\since 5.12
int previousSize = 0;
QMetaType::TypeFlags::Int previousFlags = 0;
if (idx == UnknownType) {
QWriteLocker locker(customTypesLock());
int posInVector = -1;
idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
normalizedTypeName.size(),
&posInVector);
if (idx == UnknownType) {
QCustomTypeInfo inf;
inf.typeName = normalizedTypeName;
#ifndef QT_NO_DATASTREAM
inf.loadOp = 0;
inf.saveOp = 0;
#endif
inf.alias = -1;
inf.constructor = constructor;
inf.destructor = destructor;
inf.size = size;
inf.flags = flags;
inf.metaObject = metaObject;
if (posInVector == -1) {
idx = ct->size() + User;
ct->append(inf);
} else {
idx = posInVector + User;
ct->data()[posInVector] = inf;
}
return idx;
}
Registers a user type for marshalling, with \a normalizedTypeName,
a \a destructor, a \a constructor, and a \a size. Returns the type's
handle, or -1 if the type could not be registered.
if (idx >= User) {
previousSize = ct->at(idx - User).size;
previousFlags = ct->at(idx - User).flags;
// Set new/additional flags in case of old library/app.
// Ensures that older code works in conjunction with new Qt releases
// requiring the new flags.
if (flags != previousFlags) {
QCustomTypeInfo &inf = ct->data()[idx - User];
inf.flags |= flags;
if (metaObject)
inf.metaObject = metaObject;
}
}
}
if (idx < User) {
previousSize = QMetaType::sizeOf(idx);
previousFlags = QMetaType::typeFlags(idx);
}
if (Q_UNLIKELY(previousSize != size)) {
qFatal("QMetaType::registerType: Binary compatibility break "
"-- Size mismatch for type '%s' [%i]. Previously registered "
"size %i, now registering size %i.",
normalizedTypeName.constData(), idx, previousSize, size);
}
// these flags cannot change in a binary compatible way:
const int binaryCompatibilityFlag = PointerToQObject | IsEnumeration | SharedPointerToQObject
| WeakPointerToQObject | TrackingPointerToQObject;
if (Q_UNLIKELY((previousFlags ^ flags) & binaryCompatibilityFlag)) {
const char *msg = "QMetaType::registerType: Binary compatibility break. "
"\nType flags for type '%s' [%i] don't match. Previously "
"registered TypeFlags(0x%x), now registering TypeFlags(0x%x). ";
qFatal(msg, normalizedTypeName.constData(), idx, previousFlags, int(flags));
}
return idx;
\note normalizedTypeName is not checked for conformance with
Qt's normalized format, so it must already conform.
*/
int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
TypedDestructor destructor,
TypedConstructor constructor,
int size, TypeFlags flags, const QMetaObject *metaObject)
{
return NS(registerNormalizedType)(normalizedTypeName, nullptr, nullptr, destructor, constructor, size, flags, metaObject);
}
/*!
@ -1850,14 +1907,19 @@ private:
static void *customTypeConstructor(const int type, void *where, const void *copy)
{
QMetaType::Constructor ctor;
QMetaType::TypedConstructor tctor;
const QVector<QCustomTypeInfo> * const ct = customTypes();
{
QReadLocker locker(customTypesLock());
if (Q_UNLIKELY(type < QMetaType::User || !ct || ct->count() <= type - QMetaType::User))
return 0;
ctor = ct->at(type - QMetaType::User).constructor;
const auto &typeInfo = ct->at(type - QMetaType::User);
ctor = typeInfo.constructor;
tctor = typeInfo.typedConstructor;
}
Q_ASSERT_X(ctor, "void *QMetaType::construct(int type, void *where, const void *copy)", "The type was not properly registered");
Q_ASSERT_X((ctor || tctor) , "void *QMetaType::construct(int type, void *where, const void *copy)", "The type was not properly registered");
if (Q_UNLIKELY(tctor))
return tctor(type, where, copy);
return ctor(where, copy);
}
@ -1943,14 +2005,19 @@ private:
static void customTypeDestructor(const int type, void *where)
{
QMetaType::Destructor dtor;
QMetaType::TypedDestructor tdtor;
const QVector<QCustomTypeInfo> * const ct = customTypes();
{
QReadLocker locker(customTypesLock());
if (Q_UNLIKELY(type < QMetaType::User || !ct || ct->count() <= type - QMetaType::User))
return;
dtor = ct->at(type - QMetaType::User).destructor;
const auto &typeInfo = ct->at(type - QMetaType::User);
dtor = typeInfo.destructor;
tdtor = typeInfo.typedDestructor;
}
Q_ASSERT_X(dtor, "void QMetaType::destruct(int type, void *where)", "The type was not properly registered");
Q_ASSERT_X((dtor || tdtor), "void QMetaType::destruct(int type, void *where)", "The type was not properly registered");
if (Q_UNLIKELY(tdtor))
return tdtor(type, where);
dtor(where);
}
@ -2363,10 +2430,12 @@ QMetaType QMetaType::typeInfo(const int type)
{
TypeInfo typeInfo(type);
QMetaTypeSwitcher::switcher<void>(typeInfo, type, 0);
return typeInfo.info.constructor ? QMetaType(static_cast<ExtensionFlag>(QMetaType::CreateEx | QMetaType::DestroyEx)
, static_cast<const QMetaTypeInterface *>(0) // typeInfo::info is a temporary variable, we can't return address of it.
, 0 // unused
, 0 // unused
return (typeInfo.info.constructor || typeInfo.info.typedConstructor)
? QMetaType(static_cast<ExtensionFlag>(QMetaType::CreateEx | QMetaType::DestroyEx |
(typeInfo.info.typedConstructor ? QMetaType::ConstructEx | QMetaType::DestructEx : 0))
, static_cast<const QMetaTypeInterface *>(nullptr) // typeInfo::info is a temporary variable, we can't return address of it.
, typeInfo.info.typedConstructor
, typeInfo.info.typedDestructor
, typeInfo.info.saveOp
, typeInfo.info.loadOp
, typeInfo.info.constructor
@ -2408,8 +2477,8 @@ QMetaType::QMetaType(const int typeId)
Copy constructs a QMetaType object.
*/
QMetaType::QMetaType(const QMetaType &other)
: m_creator_unused(other.m_creator_unused)
, m_deleter_unused(other.m_deleter_unused)
: m_typedConstructor(other.m_typedConstructor)
, m_typedDestructor(other.m_typedDestructor)
, m_saveOp(other.m_saveOp)
, m_loadOp(other.m_loadOp)
, m_constructor(other.m_constructor)
@ -2424,8 +2493,8 @@ QMetaType::QMetaType(const QMetaType &other)
QMetaType &QMetaType::operator =(const QMetaType &other)
{
m_creator_unused = other.m_creator_unused;
m_deleter_unused = other.m_deleter_unused;
m_typedConstructor = other.m_typedConstructor;
m_typedDestructor = other.m_typedDestructor;
m_saveOp = other.m_saveOp;
m_loadOp = other.m_loadOp;
m_constructor = other.m_constructor;
@ -2481,6 +2550,8 @@ void *QMetaType::createExtended(const void *copy) const
{
if (m_typeId == QMetaType::UnknownType)
return 0;
if (Q_UNLIKELY(m_typedConstructor && !m_constructor))
return m_typedConstructor(m_typeId, operator new(m_size), copy);
return m_constructor(operator new(m_size), copy);
}
@ -2495,7 +2566,10 @@ void *QMetaType::createExtended(const void *copy) const
*/
void QMetaType::destroyExtended(void *data) const
{
m_destructor(data);
if (Q_UNLIKELY(m_typedDestructor && !m_destructor))
m_typedDestructor(m_typeId, data);
else
m_destructor(data);
operator delete(data);
}
@ -2508,9 +2582,9 @@ void QMetaType::destroyExtended(void *data) const
*/
void *QMetaType::constructExtended(void *where, const void *copy) const
{
Q_UNUSED(where);
Q_UNUSED(copy);
return 0;
if (m_typedConstructor && !m_constructor)
return m_typedConstructor(m_typeId, where, copy);
return nullptr;
}
/*!
@ -2522,7 +2596,8 @@ void *QMetaType::constructExtended(void *where, const void *copy) const
*/
void QMetaType::destructExtended(void *data) const
{
Q_UNUSED(data);
if (m_typedDestructor && !m_destructor)
m_typedDestructor(m_typeId, data);
}
/*!

View File

@ -493,8 +493,12 @@ public:
typedef void (*Deleter)(void *);
typedef void *(*Creator)(const void *);
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
typedef void (*Destructor)(void *);
typedef void *(*Constructor)(void *, const void *);
typedef void *(*Constructor)(void *, const void *); // TODO Qt6: remove me
#endif
typedef void (*TypedDestructor)(int, void *);
typedef void *(*TypedConstructor)(int, void *, const void *);
typedef void (*SaveOperator)(QDataStream &, const void *);
typedef void (*LoadOperator)(QDataStream &, void *);
@ -513,6 +517,12 @@ public:
int size,
QMetaType::TypeFlags flags,
const QMetaObject *metaObject);
static int registerType(const char *typeName,
TypedDestructor destructor,
TypedConstructor constructor,
int size,
QMetaType::TypeFlags flags,
const QMetaObject *metaObject);
static bool unregisterType(int type);
static int registerNormalizedType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, Deleter deleter,
Creator creator,
@ -526,6 +536,11 @@ public:
int size,
QMetaType::TypeFlags flags,
const QMetaObject *metaObject);
static int registerNormalizedType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, TypedDestructor destructor,
TypedConstructor constructor,
int size,
QMetaType::TypeFlags flags,
const QMetaObject *metaObject);
static int registerTypedef(const char *typeName, int aliasId);
static int registerNormalizedTypedef(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, int aliasId);
static int type(const char *typeName);
@ -683,8 +698,8 @@ public:
private:
static QMetaType typeInfo(const int type);
inline QMetaType(const ExtensionFlag extensionFlags, const QMetaTypeInterface *info,
Creator creator,
Deleter deleter,
TypedConstructor creator,
TypedDestructor deleter,
SaveOperator saveOp,
LoadOperator loadOp,
Constructor constructor,
@ -731,8 +746,8 @@ public:
static void unregisterConverterFunction(int from, int to);
private:
Creator m_creator_unused;
Deleter m_deleter_unused;
TypedConstructor m_typedConstructor;
TypedDestructor m_typedDestructor;
SaveOperator m_saveOp;
LoadOperator m_loadOp;
Constructor m_constructor;
@ -2163,8 +2178,8 @@ QT_BEGIN_NAMESPACE
#undef Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER
inline QMetaType::QMetaType(const ExtensionFlag extensionFlags, const QMetaTypeInterface *info,
Creator creator,
Deleter deleter,
TypedConstructor creator,
TypedDestructor deleter,
SaveOperator saveOp,
LoadOperator loadOp,
Constructor constructor,
@ -2173,8 +2188,8 @@ inline QMetaType::QMetaType(const ExtensionFlag extensionFlags, const QMetaTypeI
uint theTypeFlags,
int typeId,
const QMetaObject *_metaObject)
: m_creator_unused(creator)
, m_deleter_unused(deleter)
: m_typedConstructor(creator)
, m_typedDestructor(deleter)
, m_saveOp(saveOp)
, m_loadOp(loadOp)
, m_constructor(constructor)

View File

@ -126,11 +126,13 @@ class QMetaTypeInterface
public:
QMetaType::SaveOperator saveOp;
QMetaType::LoadOperator loadOp;
QMetaType::Constructor constructor;
QMetaType::Constructor constructor; // TODO Qt6: remove me
QMetaType::Destructor destructor;
int size;
QMetaType::TypeFlags::Int flags;
const QMetaObject *metaObject;
QMetaType::TypedConstructor typedConstructor;
QMetaType::TypedDestructor typedDestructor;
};
#ifndef QT_NO_DATASTREAM
@ -161,7 +163,9 @@ public:
/*destructor*/(QtMetaTypePrivate::QMetaTypeFunctionHelper<Type, QtMetaTypePrivate::TypeDefinition<Type>::IsAvailable>::Destruct), \
/*size*/(QTypeInfo<Type>::sizeOf), \
/*flags*/QtPrivate::QMetaTypeTypeFlags<Type>::Flags, \
/*metaObject*/METAOBJECT_DELEGATE(Type) \
/*metaObject*/METAOBJECT_DELEGATE(Type), \
/*typedConstructor*/ nullptr, \
/*typedDestructor*/ nullptr \
}
@ -184,7 +188,9 @@ public:
/*destructor*/ 0, \
/*size*/ 0, \
/*flags*/ 0, \
/*metaObject*/ 0 \
/*metaObject*/ 0 , \
/*typedConstructor*/ nullptr, \
/*typedDestructor*/ nullptr \
}
namespace QtMetaTypePrivate {

View File

@ -101,7 +101,8 @@ HANDLE QSharedMemoryPrivate::handle()
#if defined(Q_OS_WINRT)
hand = OpenFileMappingFromApp(FILE_MAP_ALL_ACCESS, FALSE, reinterpret_cast<PCWSTR>(nativeKey.utf16()));
#else
hand = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, (wchar_t*)nativeKey.utf16());
hand = OpenFileMapping(FILE_MAP_ALL_ACCESS, false,
reinterpret_cast<const wchar_t*>(nativeKey.utf16()));
#endif
if (!hand) {
setErrorString(function);
@ -133,9 +134,11 @@ bool QSharedMemoryPrivate::create(int size)
// Create the file mapping.
#if defined(Q_OS_WINRT)
hand = CreateFileMappingFromApp(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, size, (PCWSTR)nativeKey.utf16());
hand = CreateFileMappingFromApp(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, size,
reinterpret_cast<PCWSTR>(nativeKey.utf16()));
#else
hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, size, (wchar_t*)nativeKey.utf16());
hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, size,
reinterpret_cast<const wchar_t*>(nativeKey.utf16()));
#endif
setErrorString(function);

View File

@ -86,9 +86,12 @@ HANDLE QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode)
// Create it if it doesn't already exists.
if (semaphore == 0) {
#if defined(Q_OS_WINRT)
semaphore = CreateSemaphoreEx(0, initialValue, MAXLONG, (wchar_t*)fileName.utf16(), 0, SEMAPHORE_ALL_ACCESS);
semaphore = CreateSemaphoreEx(0, initialValue, MAXLONG,
reinterpret_cast<const wchar_t*>(fileName.utf16()),
0, SEMAPHORE_ALL_ACCESS);
#else
semaphore = CreateSemaphore(0, initialValue, MAXLONG, (wchar_t*)fileName.utf16());
semaphore = CreateSemaphore(0, initialValue, MAXLONG,
reinterpret_cast<const wchar_t*>(fileName.utf16()));
#endif
if (semaphore == NULL)
setErrorString(QLatin1String("QSystemSemaphore::handle"));

View File

@ -151,7 +151,9 @@ void QMimeDatabasePrivate::loadProviders()
QVector<QMimeProviderBase *> QMimeDatabasePrivate::providers()
{
#ifndef Q_OS_WASM // stub implementation always returns true
Q_ASSERT(!mutex.tryLock()); // caller should have locked mutex
#endif
if (m_providers.isEmpty()) {
loadProviders();
m_lastCheck.start();

View File

@ -4,6 +4,7 @@ HEADERS += \
plugin/qfactoryinterface.h \
plugin/qpluginloader.h \
plugin/qplugin.h \
plugin/qplugin_p.h \
plugin/quuid.h \
plugin/qfactoryloader_p.h

View File

@ -47,9 +47,12 @@
#include <qdebug.h>
#include "qmutex.h"
#include "qplugin.h"
#include "qplugin_p.h"
#include "qpluginloader.h"
#include "private/qobject_p.h"
#include "private/qcoreapplication_p.h"
#include "qcbormap.h"
#include "qcborvalue.h"
#include "qjsondocument.h"
#include "qjsonvalue.h"
#include "qjsonobject.h"
@ -64,22 +67,86 @@ static inline int metaDataSignatureLength()
return sizeof("QTMETADATA ") - 1;
}
QJsonDocument qJsonFromRawLibraryMetaData(const char *raw, qsizetype sectionSize)
static QJsonDocument jsonFromCborMetaData(const char *raw, qsizetype size, QString *errMsg)
{
// extract the keys not stored in CBOR
int qt_metadataVersion = quint8(raw[0]);
int qt_version = qFromBigEndian<quint16>(raw + 1);
int qt_archRequirements = quint8(raw[3]);
if (Q_UNLIKELY(raw[-1] != '!' || qt_metadataVersion != 0)) {
*errMsg = QStringLiteral("Invalid metadata version");
return QJsonDocument();
}
raw += 4;
size -= 4;
QByteArray ba = QByteArray::fromRawData(raw, int(size));
QCborParserError err;
QCborValue metadata = QCborValue::fromCbor(ba, &err);
if (err.error != QCborError::NoError) {
*errMsg = QLatin1String("Metadata parsing error: ") + err.error.toString();
return QJsonDocument();
}
if (!metadata.isMap()) {
*errMsg = QStringLiteral("Unexpected metadata contents");
return QJsonDocument();
}
QJsonObject o;
o.insert(QLatin1String("version"), qt_version << 8);
o.insert(QLatin1String("debug"), bool(qt_archRequirements & 1));
o.insert(QLatin1String("archreq"), qt_archRequirements);
// convert the top-level map integer keys
for (auto it : metadata.toMap()) {
QString key;
if (it.first.isInteger()) {
switch (it.first.toInteger()) {
#define CONVERT_TO_STRING(IntKey, StringKey, Description) \
case int(IntKey): key = QStringLiteral(StringKey); break;
QT_PLUGIN_FOREACH_METADATA(CONVERT_TO_STRING)
#undef CONVERT_TO_STRING
case int(QtPluginMetaDataKeys::Requirements):
// special case: recreate the debug key
o.insert(QLatin1String("debug"), bool(it.second.toInteger() & 1));
key = QStringLiteral("archreq");
break;
}
} else {
key = it.first.toString();
}
if (!key.isEmpty())
o.insert(key, it.second.toJsonValue());
}
return QJsonDocument(o);
}
QJsonDocument qJsonFromRawLibraryMetaData(const char *raw, qsizetype sectionSize, QString *errMsg)
{
raw += metaDataSignatureLength();
sectionSize -= metaDataSignatureLength();
// the size of the embedded JSON object can be found 8 bytes into the data (see qjson_p.h)
uint size = qFromLittleEndian<uint>(raw + 8);
// but the maximum size of binary JSON is 128 MB
size = qMin(size, 128U * 1024 * 1024);
// and it doesn't include the size of the header (8 bytes)
size += 8;
// finally, it can't be bigger than the file or section size
size = qMin(sectionSize, qsizetype(size));
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (Q_UNLIKELY(raw[-1] == ' ')) {
// the size of the embedded JSON object can be found 8 bytes into the data (see qjson_p.h)
uint size = qFromLittleEndian<uint>(raw + 8);
// but the maximum size of binary JSON is 128 MB
size = qMin(size, 128U * 1024 * 1024);
// and it doesn't include the size of the header (8 bytes)
size += 8;
// finally, it can't be bigger than the file or section size
size = qMin(sectionSize, qsizetype(size));
QByteArray json(raw, size);
return QJsonDocument::fromBinaryData(json);
QByteArray json(raw, size);
return QJsonDocument::fromBinaryData(json);
}
#endif
return jsonFromCborMetaData(raw, sectionSize, errMsg);
}
class QFactoryLoaderPrivate : public QObjectPrivate

View File

@ -56,6 +56,7 @@
#include "QtCore/qobject.h"
#include "QtCore/qstringlist.h"
#include "QtCore/qcborvalue.h"
#include "QtCore/qjsonobject.h"
#include "QtCore/qjsondocument.h"
#include "QtCore/qmap.h"
@ -66,7 +67,7 @@
QT_BEGIN_NAMESPACE
QJsonDocument qJsonFromRawLibraryMetaData(const char *raw, qsizetype size);
QJsonDocument qJsonFromRawLibraryMetaData(const char *raw, qsizetype size, QString *errMsg);
class QFactoryLoaderPrivate;
class Q_CORE_EXPORT QFactoryLoader : public QObject

View File

@ -268,7 +268,7 @@ static bool findPatternUnloaded(const QString &library, QLibraryPrivate *lib)
*/
bool hasMetaData = false;
qsizetype pos = 0;
char pattern[] = "qTMETADATA ";
char pattern[] = "qTMETADATA ";
pattern[0] = 'Q'; // Ensure the pattern "QTMETADATA" is not found in this library should QPluginLoader ever encounter it.
const ulong plen = qstrlen(pattern);
#if defined (Q_OF_ELF) && defined(Q_CC_GNU)
@ -314,10 +314,14 @@ static bool findPatternUnloaded(const QString &library, QLibraryPrivate *lib)
bool ret = false;
if (pos >= 0) {
if (hasMetaData) {
const char *data = filedata + pos;
QJsonDocument doc = qJsonFromRawLibraryMetaData(data, qsizetype(fdlen));
if (pos >= 0 && hasMetaData) {
const char *data = filedata + pos;
QString errMsg;
QJsonDocument doc = qJsonFromRawLibraryMetaData(data, fdlen, &errMsg);
if (doc.isNull()) {
qWarning("Found invalid metadata in lib %s: %s",
qPrintable(library), qPrintable(errMsg));
} else {
lib->metaData = doc.object();
if (qt_debug_component())
qWarning("Found metadata in lib %s, metadata=\n%s\n",
@ -679,20 +683,26 @@ bool QLibrary::isLibrary(const QString &fileName)
#endif
}
typedef const char * (*QtPluginQueryVerificationDataFunction)();
static bool qt_get_metadata(QtPluginQueryVerificationDataFunction pfn, QLibraryPrivate *priv)
static bool qt_get_metadata(QLibraryPrivate *priv, QString *errMsg)
{
const char *szData = 0;
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
auto getMetaData = [](QFunctionPointer fptr) {
auto f = reinterpret_cast<const char * (*)()>(fptr);
return qMakePair<const char *, size_t>(f(), INT_MAX);
};
#else
auto getMetaData = [](QFunctionPointer fptr) {
auto f = reinterpret_cast<QPair<const char *, size_t> (*)()>(fptr);
return f();
};
#endif
QFunctionPointer pfn = priv->resolve("qt_plugin_query_metadata");
if (!pfn)
return false;
szData = pfn();
if (!szData)
return false;
// the data is already loaded, so the size doesn't matter
QJsonDocument doc = qJsonFromRawLibraryMetaData(szData, INT_MAX);
auto metaData = getMetaData(pfn);
QJsonDocument doc = qJsonFromRawLibraryMetaData(metaData.first, metaData.second, errMsg);
if (doc.isNull())
return false;
priv->metaData = doc.object();
@ -735,9 +745,7 @@ void QLibraryPrivate::updatePluginState()
} else {
// library is already loaded (probably via QLibrary)
// simply get the target function and call it.
QtPluginQueryVerificationDataFunction getMetaData = NULL;
getMetaData = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_metadata");
success = qt_get_metadata(getMetaData, this);
success = qt_get_metadata(this, &errorString);
}
if (!success) {

View File

@ -97,10 +97,10 @@ bool QLibraryPrivate::load_sys()
for (const QString &attempt : qAsConst(attempts)) {
#ifndef Q_OS_WINRT
pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(attempt).utf16());
pHnd = LoadLibrary(reinterpret_cast<const wchar_t*>(QDir::toNativeSeparators(attempt).utf16()));
#else // Q_OS_WINRT
QString path = QDir::toNativeSeparators(QDir::current().relativeFilePath(attempt));
pHnd = LoadPackagedLibrary((LPCWSTR)path.utf16(), 0);
pHnd = LoadPackagedLibrary(reinterpret_cast<LPCWSTR>(path.utf16()), 0);
if (pHnd)
qualifiedFileName = attempt;
#endif // !Q_OS_WINRT

View File

@ -56,6 +56,21 @@ QT_BEGIN_NAMESPACE
# endif
#endif
inline constexpr unsigned char qPluginArchRequirements()
{
return 0
#ifndef QT_NO_DEBUG
| 1
#endif
#ifdef __AVX2__
| 2
# ifdef __AVX512F__
| 4
# endif
#endif
;
}
typedef QObject *(*QtPluginInstanceFunction)();
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
typedef const char *(*QtPluginMetaDataFunction)();

View File

@ -0,0 +1,75 @@
/****************************************************************************
**
** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore 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 QPLUGIN_P_H
#define QPLUGIN_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of the QLibrary class. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include <private/qglobal_p.h>
QT_BEGIN_NAMESPACE
enum class QtPluginMetaDataKeys {
QtVersion,
Requirements,
IID,
ClassName,
MetaData
};
// F(IntKey, StringKey, Description)
// Keep this list sorted in the order moc should output.
#define QT_PLUGIN_FOREACH_METADATA(F) \
F(QtPluginMetaDataKeys::IID, "IID", "Plugin's Interface ID") \
F(QtPluginMetaDataKeys::ClassName, "className", "Plugin class name") \
F(QtPluginMetaDataKeys::MetaData, "MetaData", "Other meta data")
QT_END_NAMESPACE
#endif // QPLUGIN_P_H

View File

@ -475,10 +475,19 @@ QVector<QStaticPlugin> QPluginLoader::staticPlugins()
*/
QJsonObject QStaticPlugin::metaData() const
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
// the data is already loaded, so this doesn't matter
qsizetype rawMetaDataSize = INT_MAX;
const char *ptr = rawMetaData();
#else
auto ptr = static_cast<const char *>(rawMetaData);
#endif
return qJsonFromRawLibraryMetaData(rawMetaData(), rawMetaDataSize).object();
QString errMsg;
QJsonDocument doc = qJsonFromRawLibraryMetaData(ptr, rawMetaDataSize, &errMsg);
Q_ASSERT(doc.isObject());
Q_ASSERT(errMsg.isEmpty());
return doc.object();
}
QT_END_NAMESPACE

View File

@ -121,7 +121,7 @@ HINSTANCE QSystemLibrary::load(const wchar_t *libraryName, bool onlySystemDirect
fullPathAttempt.append(QLatin1Char('\\'));
}
fullPathAttempt.append(fileName);
HINSTANCE inst = ::LoadLibrary((const wchar_t *)fullPathAttempt.utf16());
HINSTANCE inst = ::LoadLibrary(reinterpret_cast<const wchar_t *>(fullPathAttempt.utf16()));
if (inst != 0)
return inst;
}

View File

@ -318,7 +318,8 @@ void qt_set_thread_name(HANDLE threadId, LPCSTR threadName)
__try
{
RaiseException(0x406D1388, 0, sizeof(info)/sizeof(DWORD), (const ULONG_PTR*)&info);
RaiseException(0x406D1388, 0, sizeof(info)/sizeof(DWORD),
reinterpret_cast<const ULONG_PTR*>(&info));
}
__except (EXCEPTION_CONTINUE_EXECUTION)
{
@ -365,7 +366,7 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi
#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINRT)
// sets the name of the current thread.
QByteArray objectName = thr->objectName().toLocal8Bit();
qt_set_thread_name((HANDLE)-1,
qt_set_thread_name(HANDLE(-1),
objectName.isEmpty() ?
thr->metaObject()->className() : objectName.constData());
#endif
@ -508,8 +509,9 @@ void QThread::start(Priority priority)
this, CREATE_SUSPENDED, &(d->id));
#else
// MSVC -MD or -MDd or MinGW build
d->handle = (Qt::HANDLE) CreateThread(NULL, d->stackSize, (LPTHREAD_START_ROUTINE)QThreadPrivate::start,
this, CREATE_SUSPENDED, reinterpret_cast<LPDWORD>(&d->id));
d->handle = CreateThread(nullptr, d->stackSize,
reinterpret_cast<LPTHREAD_START_ROUTINE>(QThreadPrivate::start),
this, CREATE_SUSPENDED, reinterpret_cast<LPDWORD>(&d->id));
#endif // Q_OS_WINRT
if (!d->handle) {

View File

@ -274,7 +274,7 @@ QSystemLocalePrivate::SubstitutionType QSystemLocalePrivate::substitution()
QString &QSystemLocalePrivate::substituteDigits(QString &string)
{
ushort zero = zeroDigit().unicode();
ushort *qch = (ushort *)string.data();
ushort *qch = reinterpret_cast<ushort *>(string.data());
for (ushort *end = qch + string.size(); qch != end; ++qch) {
if (*qch >= '0' && *qch <= '9')
*qch = zero + (*qch - '0');

View File

@ -190,7 +190,9 @@ static inline quint64 detectProcessorFeatures()
static int maxBasicCpuidSupported()
{
#if defined(Q_CC_GNU)
#if defined(Q_CC_EMSCRIPTEN)
return 6; // All features supported by Emscripten
#elif defined(Q_CC_GNU)
qregisterint tmp1;
# if Q_PROCESSOR_X86 < 5
@ -235,7 +237,7 @@ static int maxBasicCpuidSupported()
static void cpuidFeatures01(uint &ecx, uint &edx)
{
#if defined(Q_CC_GNU)
#if defined(Q_CC_GNU) && !defined(Q_CC_EMSCRIPTEN)
qregisterint tmp1;
asm ("xchg " PICreg", %2\n"
"cpuid\n"
@ -252,6 +254,9 @@ static void cpuidFeatures01(uint &ecx, uint &edx)
__CPUID(1, info);
ecx = info[2];
edx = info[3];
#else
Q_UNUSED(ecx);
Q_UNUSED(edx);
#endif
}
@ -261,7 +266,7 @@ inline void __cpuidex(int info[4], int, __int64) { memset(info, 0, 4*sizeof(int)
static void cpuidFeatures07_00(uint &ebx, uint &ecx, uint &edx)
{
#if defined(Q_CC_GNU)
#if defined(Q_CC_GNU) && !defined(Q_CC_EMSCRIPTEN)
qregisteruint rbx; // in case it's 64-bit
qregisteruint rcx = 0;
qregisteruint rdx = 0;
@ -294,7 +299,7 @@ inline quint64 _xgetbv(__int64) { return 0; }
#endif
static void xgetbv(uint in, uint &eax, uint &edx)
{
#if defined(Q_CC_GNU) || defined(Q_CC_GHS)
#if (defined(Q_CC_GNU) && !defined(Q_CC_EMSCRIPTEN)) || defined(Q_CC_GHS)
asm (".byte 0x0F, 0x01, 0xD0" // xgetbv instruction
: "=a" (eax), "=d" (edx)
: "c" (in));
@ -302,6 +307,10 @@ static void xgetbv(uint in, uint &eax, uint &edx)
quint64 result = _xgetbv(in);
eax = result;
edx = result >> 32;
#else
Q_UNUSED(in);
Q_UNUSED(eax);
Q_UNUSED(edx);
#endif
}

View File

@ -140,15 +140,15 @@ bool equalTzi(const TIME_ZONE_INFORMATION &tzi1, const TIME_ZONE_INFORMATION &tz
#ifdef QT_USE_REGISTRY_TIMEZONE
bool openRegistryKey(const QString &keyPath, HKEY *key)
{
return (RegOpenKeyEx(HKEY_LOCAL_MACHINE, (const wchar_t*)keyPath.utf16(), 0, KEY_READ, key)
== ERROR_SUCCESS);
return RegOpenKeyEx(HKEY_LOCAL_MACHINE, reinterpret_cast<const wchar_t*>(keyPath.utf16()),
0, KEY_READ, key) == ERROR_SUCCESS;
}
QString readRegistryString(const HKEY &key, const wchar_t *value)
{
wchar_t buffer[MAX_PATH] = {0};
DWORD size = sizeof(wchar_t) * MAX_PATH;
RegQueryValueEx(key, (LPCWSTR)value, NULL, NULL, (LPBYTE)buffer, &size);
RegQueryValueEx(key, value, nullptr, nullptr, reinterpret_cast<LPBYTE>(buffer), &size);
return QString::fromWCharArray(buffer);
}
@ -156,7 +156,7 @@ int readRegistryValue(const HKEY &key, const wchar_t *value)
{
DWORD buffer;
DWORD size = sizeof(buffer);
RegQueryValueEx(key, (LPCWSTR)value, NULL, NULL, (LPBYTE)&buffer, &size);
RegQueryValueEx(key, value, nullptr, nullptr, reinterpret_cast<LPBYTE>(&buffer), &size);
return buffer;
}
@ -167,7 +167,7 @@ QWinTimeZonePrivate::QWinTransitionRule readRegistryRule(const HKEY &key,
QWinTimeZonePrivate::QWinTransitionRule rule;
REG_TZI_FORMAT tzi;
DWORD tziSize = sizeof(tzi);
if (RegQueryValueEx(key, (LPCWSTR)value, NULL, NULL, (BYTE *)&tzi, &tziSize)
if (RegQueryValueEx(key, value, nullptr, nullptr, reinterpret_cast<BYTE *>(&tzi), &tziSize)
== ERROR_SUCCESS) {
rule.startYear = 0;
rule.standardTimeBias = tzi.Bias + tzi.StandardBias;
@ -192,12 +192,12 @@ TIME_ZONE_INFORMATION getRegistryTzi(const QByteArray &windowsId, bool *ok)
if (openRegistryKey(tziKeyPath, &key)) {
DWORD size = sizeof(tzi.DaylightName);
RegQueryValueEx(key, L"Dlt", NULL, NULL, (LPBYTE)tzi.DaylightName, &size);
RegQueryValueEx(key, L"Dlt", nullptr, nullptr, reinterpret_cast<LPBYTE>(tzi.DaylightName), &size);
size = sizeof(tzi.StandardName);
RegQueryValueEx(key, L"Std", NULL, NULL, (LPBYTE)tzi.StandardName, &size);
RegQueryValueEx(key, L"Std", nullptr, nullptr, reinterpret_cast<LPBYTE>(tzi.StandardName), &size);
if (RegQueryValueEx(key, L"TZI", NULL, NULL, (BYTE *) &regTzi, &regTziSize)
if (RegQueryValueEx(key, L"TZI", nullptr, nullptr, reinterpret_cast<BYTE *>(&regTzi), &regTziSize)
== ERROR_SUCCESS) {
tzi.Bias = regTzi.Bias;
tzi.StandardBias = regTzi.StandardBias;
@ -590,7 +590,7 @@ void QWinTimeZonePrivate::init(const QByteArray &ianaId)
for (int year = startYear; year <= endYear; ++year) {
bool ruleOk;
QWinTransitionRule rule = readRegistryRule(dynamicKey,
(LPCWSTR)QString::number(year).utf16(),
reinterpret_cast<LPCWSTR>(QString::number(year).utf16()),
&ruleOk);
if (ruleOk
// Don't repeat a recurrent rule:

View File

@ -72,6 +72,9 @@ struct Properties {
signed short mirrorDiff : 16;
ushort lowerCaseSpecial : 1;
signed short lowerCaseDiff : 15;
#ifdef Q_OS_WASM
unsigned char : 0; //wasm 64 packing trick
#endif
ushort upperCaseSpecial : 1;
signed short upperCaseDiff : 15;
ushort titleCaseSpecial : 1;
@ -80,6 +83,9 @@ struct Properties {
signed short caseFoldDiff : 15;
ushort unicodeVersion : 8; /* 5 used */
ushort nfQuickCheck : 8;
#ifdef Q_OS_WASM
unsigned char : 0; //wasm 64 packing trick
#endif
ushort graphemeBreakClass : 5; /* 5 used */
ushort wordBreakClass : 5; /* 5 used */
ushort sentenceBreakClass : 8; /* 4 used */

View File

@ -221,7 +221,7 @@ qtConfig(system-doubleconversion) {
}
# Note: libm should be present by default becaue this is C++
unix:!macx-icc:!vxworks:!haiku:!integrity: LIBS_PRIVATE += -lm
unix:!macx-icc:!vxworks:!haiku:!integrity:!wasm: LIBS_PRIVATE += -lm
TR_EXCLUDE += ../3rdparty/*

View File

@ -164,7 +164,8 @@
},
"sources": [
{ "type": "pkgConfig", "args": "freetype2" },
{ "type": "freetype", "libs": "-lfreetype" }
{ "type": "freetype", "libs": "-lfreetype", "condition": "!config.wasm" },
{ "type": "freetype", "libs": "-s USE_FREETYPE=1", "condition": "config.wasm" }
]
},
"fontconfig": {
@ -308,7 +309,8 @@
{ "libs": "-llibpng16", "condition": "config.msvc" },
{ "libs": "-llibpng", "condition": "config.msvc" },
{ "libs": "-lpng16", "condition": "!config.msvc" },
{ "libs": "-lpng", "condition": "!config.msvc" }
{ "libs": "-lpng", "condition": "!config.msvc" },
{ "libs": "-s USE_LIBPNG=1", "condition": "config.wasm" }
],
"use": [
{ "lib": "zlib", "condition": "features.system-zlib" }
@ -1111,7 +1113,7 @@
},
"opengles3": {
"label": "OpenGL ES 3.0",
"condition": "features.opengles2 && !features.angle && tests.opengles3",
"condition": "features.opengles2 && !features.angle && tests.opengles3 && !config.wasm",
"output": [
"publicFeature",
{ "type": "define", "name": "QT_OPENGL_ES_3" }
@ -1138,7 +1140,7 @@
"enable": "input.opengl == 'desktop'",
"disable": "input.opengl == 'es2' || input.opengl == 'dynamic' || input.opengl == 'no'",
"condition": "(config.win32 && !config.winrt && !features.opengles2 && (config.msvc || libs.opengl))
|| (!config.watchos && !config.win32 && libs.opengl)"
|| (!config.watchos && !config.win32 && !config.wasm && libs.opengl)"
},
"opengl-dynamic": {
"label": "Dynamic OpenGL",

View File

@ -55,6 +55,7 @@ defineTest(qtConfTest_qpaDefaultPlatform) {
else: qnx: name = qnx
else: integrity: name = integrityfb
else: haiku: name = haiku
else: wasm: name = webassembly
else: name = xcb
$${1}.value = $$name

View File

@ -114,6 +114,10 @@
# include <QtCore/QLibraryInfo>
#endif // Q_OS_WIN
#ifdef Q_OS_WASM
#include <emscripten.h>
#endif
#include <qtgui_tracepoints_p.h>
#include <ctype.h>
@ -1620,7 +1624,13 @@ QGuiApplicationPrivate::~QGuiApplicationPrivate()
qt_gl_set_global_share_context(0);
}
#endif
#ifdef Q_OS_WASM
EM_ASM(
// unmount persistent directory as IDBFS
// see QTBUG-70002
FS.unmount('/home/web_user');
);
#endif
platform_integration->destroy();
delete platform_theme;

View File

@ -977,8 +977,11 @@ bool QOpenGLContext::makeCurrent(QSurface *surface)
if (!surface->surfaceHandle())
return false;
if (!surface->supportsOpenGL()) {
#ifndef Q_OS_WASM // ### work around the WASM platform plugin using QOpenGLContext with raster surfaces.
// see QTBUG-70076
qWarning() << "QOpenGLContext::makeCurrent() called with non-opengl surface" << surface;
return false;
#endif
}
QOpenGLContext *previous = QOpenGLContextPrivate::setCurrentContext(this);

View File

@ -365,7 +365,7 @@ public:
QUrl url;
};
class TabletEvent : public InputEvent {
class Q_GUI_EXPORT TabletEvent : public InputEvent {
public:
static void handleTabletEvent(QWindow *w, const QPointF &local, const QPointF &global,
int device, int pointerType, Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt,

View File

@ -142,6 +142,14 @@ QT_BEGIN_NAMESPACE
#define GL_CONTEXT_LOST 0x0507
#endif
#ifndef GL_DEPTH_STENCIL_ATTACHMENT
#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
#endif
#ifndef GL_DEPTH_STENCIL
#define GL_DEPTH_STENCIL 0x84F9
#endif
/*!
@ -619,7 +627,11 @@ void QOpenGLFramebufferObjectPrivate::initDepthStencilAttachments(QOpenGLContext
// free existing attachments
if (depth_buffer_guard) {
#ifdef Q_OS_WASM
funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
#else
funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
#endif
depth_buffer_guard->free();
}
if (stencil_buffer_guard) {
@ -637,7 +649,35 @@ void QOpenGLFramebufferObjectPrivate::initDepthStencilAttachments(QOpenGLContext
// In practice, a combined depth-stencil buffer is supported by all desktop platforms, while a
// separate stencil buffer is not. On embedded devices however, a combined depth-stencil buffer
// might not be supported while separate buffers are, according to QTBUG-12861.
#ifdef Q_OS_WASM
// WebGL doesn't allow separately attach buffers to
// STENCIL_ATTACHMENT and DEPTH_ATTACHMENT
// QTBUG-69913
if (attachment == QOpenGLFramebufferObject::CombinedDepthStencil) {
funcs.glGenRenderbuffers(1, &depth_buffer);
funcs.glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer);
Q_ASSERT(funcs.glIsRenderbuffer(depth_buffer));
GLenum storageFormat = GL_DEPTH_STENCIL;
if (samples != 0 ) {
funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
storageFormat, dsSize.width(), dsSize.height());
} else {
funcs.glRenderbufferStorage(GL_RENDERBUFFER, storageFormat,
dsSize.width(), dsSize.height());
}
funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, depth_buffer);
valid = checkFramebufferStatus(ctx);
if (!valid) {
funcs.glDeleteRenderbuffers(1, &depth_buffer);
depth_buffer = 0;
}
}
#else
if (attachment == QOpenGLFramebufferObject::CombinedDepthStencil
&& funcs.hasOpenGLExtension(QOpenGLExtensions::PackedDepthStencil))
{
@ -729,11 +769,16 @@ void QOpenGLFramebufferObjectPrivate::initDepthStencilAttachments(QOpenGLContext
stencil_buffer = 0;
}
}
#endif //Q_OS_WASM
// The FBO might have become valid after removing the depth or stencil buffer.
valid = checkFramebufferStatus(ctx);
#ifdef Q_OS_WASM
if (depth_buffer) {
#else
if (depth_buffer && stencil_buffer) {
#endif
fbo_attachment = QOpenGLFramebufferObject::CombinedDepthStencil;
} else if (depth_buffer) {
fbo_attachment = QOpenGLFramebufferObject::Depth;

View File

@ -564,7 +564,10 @@ static void qt_qimageScaleRgba64_up_xy(QImageScaleInfo *isi, QRgba64 *dest,
for (int x = 0; x < dw; x++) {
const QRgba64 *pix = sptr + xpoints[x];
const int xap = xapoints[x];
*dptr = interpolate256(pix[0], 256 - xap, pix[1], xap);
if (xap > 0)
*dptr = interpolate256(pix[0], 256 - xap, pix[1], xap);
else
*dptr = pix[0];
dptr++;
}
}

View File

@ -1327,7 +1327,7 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy
resolveTable:
*isSymbolFont = (symbolTable > -1);
quint32 unicode_table;
quint32 unicode_table = 0;
if (!qSafeFromBigEndian(maps + 8 * tableToUse + 4, endPtr, &unicode_table))
return 0;

View File

@ -68,6 +68,13 @@ qtConfig(networkdiskcache) {
mac: LIBS_PRIVATE += -framework Security
wasm {
SOURCES += \
access/qnetworkreplywasmimpl.cpp
HEADERS += \
access/qnetworkreplywasmimpl_p.h
}
include($$PWD/../../3rdparty/zlib_dependency.pri)
qtConfig(http) {

View File

@ -82,6 +82,9 @@
#include <SystemConfiguration/SystemConfiguration.h>
#include <Security/SecKeychain.h>
#endif
#ifdef Q_OS_WASM
#include "qnetworkreplywasmimpl_p.h"
#endif
QT_BEGIN_NAMESPACE
@ -1344,6 +1347,16 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
bool isLocalFile = req.url().isLocalFile();
QString scheme = req.url().scheme();
#ifdef Q_OS_WASM
if (scheme == QLatin1String("http") || scheme == QLatin1String("https")) {
QNetworkReplyWasmImpl *reply = new QNetworkReplyWasmImpl(this);
QNetworkReplyWasmImplPrivate *priv = reply->d_func();
priv->manager = this;
priv->setup(op, req, outgoingData);
return reply;
}
#endif
// fast path for GET on file:// URLs
// The QNetworkAccessFileBackend will right now only be used for PUT
if (op == QNetworkAccessManager::GetOperation

View File

@ -195,6 +195,9 @@ private:
friend class QNetworkReplyHttpImplPrivate;
friend class QNetworkReplyFileImpl;
#ifdef Q_OS_WASM
friend class QNetworkReplyWasmImpl;
#endif
Q_DECLARE_PRIVATE(QNetworkAccessManager)
Q_PRIVATE_SLOT(d_func(), void _q_replyFinished())
Q_PRIVATE_SLOT(d_func(), void _q_replyEncrypted())

View File

@ -0,0 +1,640 @@
/****************************************************************************
**
** Copyright (C) 2018 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 "qnetworkreplywasmimpl_p.h"
#include "qnetworkrequest.h"
#include <QtCore/qtimer.h>
#include <QtCore/qdatetime.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qfileinfo.h>
#include <QtCore/qthread.h>
#include <private/qnetworkaccessmanager_p.h>
#include <private/qnetworkfile_p.h>
#include <iostream>
QT_BEGIN_NAMESPACE
QNetworkReplyWasmImplPrivate::QNetworkReplyWasmImplPrivate()
: QNetworkReplyPrivate()
, managerPrivate(0)
, downloadBufferReadPosition(0)
, downloadBufferCurrentSize(0)
, totalDownloadSize(0)
, percentFinished(0)
{
}
QNetworkReplyWasmImplPrivate::~QNetworkReplyWasmImplPrivate()
{
}
QNetworkReplyWasmImpl::~QNetworkReplyWasmImpl()
{
}
QNetworkReplyWasmImpl::QNetworkReplyWasmImpl(QObject *parent)
: QNetworkReply(*new QNetworkReplyWasmImplPrivate(), parent)
{
}
QByteArray QNetworkReplyWasmImpl::methodName() const
{
switch (operation()) {
case QNetworkAccessManager::HeadOperation:
return "HEAD";
case QNetworkAccessManager::GetOperation:
return "GET";
case QNetworkAccessManager::PutOperation:
return "PUT";
case QNetworkAccessManager::PostOperation:
return "POST";
case QNetworkAccessManager::DeleteOperation:
return "DELETE";
default:
break;
}
return QByteArray();
}
void QNetworkReplyWasmImpl::close()
{
QNetworkReply::close();
}
void QNetworkReplyWasmImpl::abort()
{
close();
}
qint64 QNetworkReplyWasmImpl::bytesAvailable() const
{
Q_D(const QNetworkReplyWasmImpl);
if (!d->isFinished)
return QNetworkReply::bytesAvailable();
return QNetworkReply::bytesAvailable() + d->downloadBufferCurrentSize - d->downloadBufferReadPosition;
}
bool QNetworkReplyWasmImpl::isSequential() const
{
return true;
}
qint64 QNetworkReplyWasmImpl::size() const
{
return QNetworkReply::size();
}
/*!
\internal
*/
qint64 QNetworkReplyWasmImpl::readData(char *data, qint64 maxlen)
{
Q_D(QNetworkReplyWasmImpl);
qint64 howMuch = qMin(maxlen, (d->downloadBuffer.size() - d->downloadBufferReadPosition));
memcpy(data, d->downloadBuffer.constData(), howMuch);
d->downloadBufferReadPosition += howMuch;
return howMuch;
}
void QNetworkReplyWasmImplPrivate::setup(QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice *data)
{
Q_Q(QNetworkReplyWasmImpl);
outgoingData = data;
request = req;
url = request.url();
operation = op;
q->QIODevice::open(QIODevice::ReadOnly);
if (outgoingData && outgoingData->isSequential()) {
bool bufferingDisallowed =
request.attribute(QNetworkRequest::DoNotBufferUploadDataAttribute, false).toBool();
if (bufferingDisallowed) {
// if a valid content-length header for the request was supplied, we can disable buffering
// if not, we will buffer anyway
if (!request.header(QNetworkRequest::ContentLengthHeader).isValid()) {
state = Buffering;
_q_bufferOutgoingData();
return;
}
} else {
// doSendRequest will be called when the buffering has finished.
state = Buffering;
_q_bufferOutgoingData();
return;
}
}
// No outgoing data (POST, ..)
doSendRequest();
}
void QNetworkReplyWasmImplPrivate::onLoadCallback(void *data, int statusCode, int statusReason, int readyState, int buffer, int bufferSize)
{
QNetworkReplyWasmImplPrivate *handler = reinterpret_cast<QNetworkReplyWasmImplPrivate*>(data);
const QString reasonStr = QString::fromUtf8(reinterpret_cast<char *>(statusReason));
switch (readyState) {
case 0://unsent
break;
case 1://opened
break;
case 2://headers received
break;
case 3://loading
break;
case 4: {//done
handler->q_func()->setAttribute(QNetworkRequest::HttpStatusCodeAttribute, statusCode);
if (!reasonStr.isEmpty())
handler->q_func()->setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, reasonStr);
if (statusCode >= 400) {
if (!reasonStr.isEmpty())
handler->emitReplyError(handler->statusCodeFromHttp(statusCode, handler->request.url()), reasonStr);
} else {
handler->dataReceived(reinterpret_cast<char *>(buffer), bufferSize);
}
}
break;
};
}
void QNetworkReplyWasmImplPrivate::onProgressCallback(void* data, int bytesWritten, int total, uint timestamp)
{
Q_UNUSED(timestamp);
QNetworkReplyWasmImplPrivate *handler = reinterpret_cast<QNetworkReplyWasmImplPrivate*>(data);
handler->emitDataReadProgress(bytesWritten, total);
}
void QNetworkReplyWasmImplPrivate::onRequestErrorCallback(void* data, int statusCode, int statusReason)
{
QString reasonStr = QString::fromUtf8(reinterpret_cast<char *>(statusReason));
QNetworkReplyWasmImplPrivate *handler = reinterpret_cast<QNetworkReplyWasmImplPrivate*>(data);
handler->q_func()->setAttribute(QNetworkRequest::HttpStatusCodeAttribute, statusCode);
if (!reasonStr.isEmpty())
handler->q_func()->setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, reasonStr);
if (statusCode >= 400) {
if (!reasonStr.isEmpty())
handler->emitReplyError(handler->statusCodeFromHttp(statusCode, handler->request.url()), reasonStr);
}
}
void QNetworkReplyWasmImplPrivate::onResponseHeadersCallback(void* data, int headers)
{
QNetworkReplyWasmImplPrivate *handler = reinterpret_cast<QNetworkReplyWasmImplPrivate*>(data);
handler->headersReceived(reinterpret_cast<char *>(headers));
}
void QNetworkReplyWasmImplPrivate::doSendRequest()
{
Q_Q(QNetworkReplyWasmImpl);
totalDownloadSize = 0;
jsRequest(QString::fromUtf8(q->methodName()), // GET POST
request.url().toString(),
(void *)&onLoadCallback,
(void *)&onProgressCallback,
(void *)&onRequestErrorCallback,
(void *)&onResponseHeadersCallback);
}
/* const QString &body, const QList<QPair<QByteArray, QByteArray> > &headers ,*/
void QNetworkReplyWasmImplPrivate::jsRequest(const QString &verb, const QString &url,
void *loadCallback, void *progressCallback,
void *errorCallback, void *onResponseHeadersCallback)
{
QString extraDataString;
QByteArray extraData;
if (outgoingData)
extraData = outgoingData->readAll();
if (extraData.size() > 0)
extraDataString.fromUtf8(extraData);
if (extraDataString.size() >= 0 && verb == QStringLiteral("POST") && extraDataString.startsWith(QStringLiteral("?")))
extraDataString.remove(QStringLiteral("?"));
// Probably a good idea to save any shared pointers as members in C++
// so the objects they point to survive as long as you need them
QStringList headersList;
for (auto header : request.rawHeaderList())
headersList << QString::fromUtf8(header + ":" + request.rawHeader(header));
EM_ASM_ARGS({
var verb = Pointer_stringify($0);
var url = Pointer_stringify($1);
var onLoadCallbackPointer = $2;
var onProgressCallbackPointer = $3;
var onErrorCallbackPointer = $4;
var onHeadersCallback = $5;
var handler = $8;
var dataToSend;
var extraRequestData = Pointer_stringify($6); // request parameters
var headersData = Pointer_stringify($7);
var xhr;
xhr = new XMLHttpRequest();
xhr.responseType = 'arraybuffer';
xhr.open(verb, url, true); //async
function handleError(xhrStatusCode, xhrStatusText) {
var errorPtr = allocate(intArrayFromString(xhrStatusText), 'i8', ALLOC_NORMAL);
Runtime.dynCall('viii', onErrorCallbackPointer, [handler, xhrStatusCode, errorPtr]);
_free(errorPtr);
}
if (headersData) {
var headers = headersData.split("&");
for (var i = 0; i < headers.length; i++) {
var header = headers[i].split(":")[0];
var value = headers[i].split(":")[1];
if (verb === 'POST' && value.toLowerCase().includes('json')) {
if (extraRequestData) {
xhr.responseType = 'json';
dataToSend = extraRequestData;
}
}
if (verb === 'POST' && value.toLowerCase().includes('form')) {
if (extraRequestData) {
var formData = new FormData();
var extra = extraRequestData.split("&");
for (var i = 0; i < extra.length; i++) {
formData.append(extra[i].split("=")[0],extra[i].split("=")[1]);
}
dataToSend = formData;
}
}
xhr.setRequestHeader(header, value);
}
}
xhr.onprogress = function(e) {
switch (xhr.status) {
case 200:
case 206:
case 300:
case 301:
case 302: {
var date = xhr.getResponseHeader('Last-Modified');
date = ((date != null) ? new Date(date).getTime() / 1000 : 0);
Runtime.dynCall('viiii', onProgressCallbackPointer, [handler, e.loaded, e.total, date]);
}
break;
}
};
xhr.onreadystatechange = function() {
if (this.readyState == this.HEADERS_RECEIVED) {
var responseStr = this.getAllResponseHeaders();
if (responseStr.length > 0) {
var ptr = allocate(intArrayFromString(responseStr), 'i8', ALLOC_NORMAL);
Runtime.dynCall('vii', onHeadersCallback, [handler, ptr]);
_free(ptr);
}
}
};
xhr.onload = function(e) {
if (xhr.status >= 300) { //error
handleError(xhr.status, xhr.statusText);
} else {
if (this.status == 200 || this.status == 203) {
var datalength;
var byteArray = 0;
var buffer;
if (this.responseType.length === 0 || this.responseType === 'document') {
byteArray = new Uint8Array(this.responseText);
} else if (this.responseType === 'json') {
var jsonResponse = JSON.stringify(this.response);
buffer = allocate(intArrayFromString(jsonResponse), 'i8', ALLOC_NORMAL);
datalength = jsonResponse.length;
} else if (this.responseType === 'arraybuffer') {
byteArray = new Uint8Array(xhr.response);
}
if (byteArray != 0 ) {
datalength = byteArray.length;
buffer = _malloc(datalength);
HEAPU8.set(byteArray, buffer);
}
var reasonPtr = allocate(intArrayFromString(this.statusText), 'i8', ALLOC_NORMAL);
Runtime.dynCall('viiiiii', onLoadCallbackPointer, [handler, this.status, reasonPtr, this.readyState, buffer, datalength]);
_free(buffer);
_free(reasonPtr);
}
}
};
xhr.onerror = function(e) {
handleError(xhr.status, xhr.statusText);
};
//TODO other operations, handle user/pass, handle binary data, data streaming
xhr.send(dataToSend);
}, verb.toLatin1().data(),
url.toLatin1().data(),
loadCallback,
progressCallback,
errorCallback,
onResponseHeadersCallback,
extraDataString.size() > 0 ? extraDataString.toLatin1().data() : extraData.data(),
headersList.join(QStringLiteral("&")).toLatin1().data(),
this
);
}
void QNetworkReplyWasmImplPrivate::emitReplyError(QNetworkReply::NetworkError errorCode, const QString &errorString)
{
Q_UNUSED(errorCode)
Q_Q(QNetworkReplyWasmImpl);
q->setError(errorCode, errorString);
emit q->error(errorCode);
q->setFinished(true);
emit q->finished();
}
void QNetworkReplyWasmImplPrivate::emitDataReadProgress(qint64 bytesReceived, qint64 bytesTotal)
{
Q_Q(QNetworkReplyWasmImpl);
totalDownloadSize = bytesTotal;
percentFinished = (bytesReceived / bytesTotal) * 100;
emit q->downloadProgress(bytesReceived, totalDownloadSize);
}
void QNetworkReplyWasmImplPrivate::dataReceived(char *buffer, int bufferSize)
{
Q_Q(QNetworkReplyWasmImpl);
if (bufferSize > 0)
q->setReadBufferSize(bufferSize);
bytesDownloaded = bufferSize;
if (percentFinished != 100)
downloadBufferCurrentSize += bufferSize;
else
downloadBufferCurrentSize = bufferSize;
totalDownloadSize = downloadBufferCurrentSize;
downloadBuffer.append(buffer, bufferSize);
if (downloadBufferCurrentSize == totalDownloadSize) {
q->setFinished(true);
emit q->finished();
}
}
//taken from qnetworkrequest.cpp
static int parseHeaderName(const QByteArray &headerName)
{
if (headerName.isEmpty())
return -1;
switch (tolower(headerName.at(0))) {
case 'c':
if (qstricmp(headerName.constData(), "content-type") == 0)
return QNetworkRequest::ContentTypeHeader;
else if (qstricmp(headerName.constData(), "content-length") == 0)
return QNetworkRequest::ContentLengthHeader;
else if (qstricmp(headerName.constData(), "cookie") == 0)
return QNetworkRequest::CookieHeader;
break;
case 'l':
if (qstricmp(headerName.constData(), "location") == 0)
return QNetworkRequest::LocationHeader;
else if (qstricmp(headerName.constData(), "last-modified") == 0)
return QNetworkRequest::LastModifiedHeader;
break;
case 's':
if (qstricmp(headerName.constData(), "set-cookie") == 0)
return QNetworkRequest::SetCookieHeader;
else if (qstricmp(headerName.constData(), "server") == 0)
return QNetworkRequest::ServerHeader;
break;
case 'u':
if (qstricmp(headerName.constData(), "user-agent") == 0)
return QNetworkRequest::UserAgentHeader;
break;
}
return -1; // nothing found
}
void QNetworkReplyWasmImplPrivate::headersReceived(char *buffer)
{
Q_Q(QNetworkReplyWasmImpl);
QString bufferString = QString::fromUtf8(buffer);
if (!bufferString.isEmpty()) {
QStringList headers = bufferString.split(QString::fromUtf8("\r\n"), QString::SkipEmptyParts);
for (int i = 0; i < headers.size(); i++) {
QString headerName = headers.at(i).split(QString::fromUtf8(": ")).at(0);
QString headersValue = headers.at(i).split(QString::fromUtf8(": ")).at(1);
if (headerName.isEmpty() || headersValue.isEmpty())
continue;
int headerIndex = parseHeaderName(headerName.toLocal8Bit());
if (headerIndex == -1)
q->setRawHeader(headerName.toLocal8Bit(), headersValue.toLocal8Bit());
else
q->setHeader(static_cast<QNetworkRequest::KnownHeaders>(headerIndex), (QVariant)headersValue);
}
}
emit q->metaDataChanged();
}
void QNetworkReplyWasmImplPrivate::_q_bufferOutgoingDataFinished()
{
Q_Q(QNetworkReplyWasmImpl);
// make sure this is only called once, ever.
//_q_bufferOutgoingData may call it or the readChannelFinished emission
if (state != Buffering)
return;
// disconnect signals
QObject::disconnect(outgoingData, SIGNAL(readyRead()), q, SLOT(_q_bufferOutgoingData()));
QObject::disconnect(outgoingData, SIGNAL(readChannelFinished()), q, SLOT(_q_bufferOutgoingDataFinished()));
// finally, start the request
doSendRequest();
}
void QNetworkReplyWasmImplPrivate::_q_bufferOutgoingData()
{
Q_Q(QNetworkReplyWasmImpl);
if (!outgoingDataBuffer) {
// first call, create our buffer
outgoingDataBuffer = QSharedPointer<QRingBuffer>::create();
QObject::connect(outgoingData, SIGNAL(readyRead()), q, SLOT(_q_bufferOutgoingData()));
QObject::connect(outgoingData, SIGNAL(readChannelFinished()), q, SLOT(_q_bufferOutgoingDataFinished()));
}
qint64 bytesBuffered = 0;
qint64 bytesToBuffer = 0;
// read data into our buffer
forever {
bytesToBuffer = outgoingData->bytesAvailable();
// unknown? just try 2 kB, this also ensures we always try to read the EOF
if (bytesToBuffer <= 0)
bytesToBuffer = 2*1024;
char *dst = outgoingDataBuffer->reserve(bytesToBuffer);
bytesBuffered = outgoingData->read(dst, bytesToBuffer);
if (bytesBuffered == -1) {
// EOF has been reached.
outgoingDataBuffer->chop(bytesToBuffer);
_q_bufferOutgoingDataFinished();
break;
} else if (bytesBuffered == 0) {
// nothing read right now, just wait until we get called again
outgoingDataBuffer->chop(bytesToBuffer);
break;
} else {
// don't break, try to read() again
outgoingDataBuffer->chop(bytesToBuffer - bytesBuffered);
}
}
}
//taken from qhttpthreaddelegate.cpp
QNetworkReply::NetworkError QNetworkReplyWasmImplPrivate::statusCodeFromHttp(int httpStatusCode, const QUrl &url)
{
QNetworkReply::NetworkError code;
// we've got an error
switch (httpStatusCode) {
case 400: // Bad Request
code = QNetworkReply::ProtocolInvalidOperationError;
break;
case 401: // Authorization required
code = QNetworkReply::AuthenticationRequiredError;
break;
case 403: // Access denied
code = QNetworkReply::ContentAccessDenied;
break;
case 404: // Not Found
code = QNetworkReply::ContentNotFoundError;
break;
case 405: // Method Not Allowed
code = QNetworkReply::ContentOperationNotPermittedError;
break;
case 407:
code = QNetworkReply::ProxyAuthenticationRequiredError;
break;
case 409: // Resource Conflict
code = QNetworkReply::ContentConflictError;
break;
case 410: // Content no longer available
code = QNetworkReply::ContentGoneError;
break;
case 418: // I'm a teapot
code = QNetworkReply::ProtocolInvalidOperationError;
break;
case 500: // Internal Server Error
code = QNetworkReply::InternalServerError;
break;
case 501: // Server does not support this functionality
code = QNetworkReply::OperationNotImplementedError;
break;
case 503: // Service unavailable
code = QNetworkReply::ServiceUnavailableError;
break;
default:
if (httpStatusCode > 500) {
// some kind of server error
code = QNetworkReply::UnknownServerError;
} else if (httpStatusCode >= 400) {
// content error we did not handle above
code = QNetworkReply::UnknownContentError;
} else {
qWarning("QNetworkAccess: got HTTP status code %d which is not expected from url: \"%s\"",
httpStatusCode, qPrintable(url.toString()));
code = QNetworkReply::ProtocolFailure;
}
};
return code;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,153 @@
/****************************************************************************
**
** Copyright (C) 2018 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 QNETWORKREPLYWASMIMPL_H
#define QNETWORKREPLYWASMIMPL_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 <QtCore/qfile.h>
#include <private/qtnetworkglobal_p.h>
#include <private/qabstractfileengine_p.h>
#include <emscripten.h>
#include <emscripten/html5.h>
QT_BEGIN_NAMESPACE
class QIODevice;
class QNetworkReplyWasmImplPrivate;
class QNetworkReplyWasmImpl: public QNetworkReply
{
Q_OBJECT
public:
QNetworkReplyWasmImpl(QObject *parent = nullptr);
~QNetworkReplyWasmImpl();
virtual void abort() override;
// reimplemented from QNetworkReply
virtual void close() override;
virtual qint64 bytesAvailable() const override;
virtual bool isSequential () const override;
qint64 size() const override;
virtual qint64 readData(char *data, qint64 maxlen) override;
void setup(QNetworkAccessManager::Operation op, const QNetworkRequest &request,
QIODevice *outgoingData);
Q_DECLARE_PRIVATE(QNetworkReplyWasmImpl)
Q_PRIVATE_SLOT(d_func(), void emitReplyError(QNetworkReply::NetworkError errorCode, const QString &errorString))
Q_PRIVATE_SLOT(d_func(), void emitDataReadProgress(qint64 done, qint64 total))
Q_PRIVATE_SLOT(d_func(), void dataReceived(char *buffer, int bufferSize))
private:
QByteArray methodName() const;
};
class QNetworkReplyWasmImplPrivate: public QNetworkReplyPrivate
{
public:
QNetworkReplyWasmImplPrivate();
~QNetworkReplyWasmImplPrivate();
QNetworkAccessManagerPrivate *managerPrivate;
void doSendRequest();
void jsRequest(const QString &verb, const QString &url, void *, void *, void *, void *);
static void onLoadCallback(void *data, int statusCode, int statusReason, int readyState, int textBuffer, int size);
static void onProgressCallback(void *data, int done, int bytesTotal, uint timestamp);
static void onRequestErrorCallback(void *data, int statusCode, int statusReason);
static void onStateChangedCallback(int status);
static void onResponseHeadersCallback(void *data, int headers);
void emitReplyError(QNetworkReply::NetworkError errorCode, const QString &);
void emitDataReadProgress(qint64 done, qint64 total);
void dataReceived(char *buffer, int bufferSize);
void headersReceived(char *buffer);
void setup(QNetworkAccessManager::Operation op, const QNetworkRequest &request,
QIODevice *outgoingData);
State state;
void _q_bufferOutgoingData();
void _q_bufferOutgoingDataFinished();
QSharedPointer<QAtomicInt> pendingDownloadData;
QSharedPointer<QAtomicInt> pendingDownloadProgress;
qint64 bytesDownloaded;
qint64 bytesBuffered;
qint64 downloadBufferReadPosition;
qint64 downloadBufferCurrentSize;
qint64 totalDownloadSize;
qint64 percentFinished;
QByteArray downloadBuffer;
QIODevice *outgoingData;
QSharedPointer<QRingBuffer> outgoingDataBuffer;
static QNetworkReply::NetworkError statusCodeFromHttp(int httpStatusCode, const QUrl &url);
Q_DECLARE_PUBLIC(QNetworkReplyWasmImpl)
};
QT_END_NAMESPACE
//Q_DECLARE_METATYPE(QNetworkRequest::KnownHeaders)
#endif // QNETWORKREPLYWASMIMPL_H

View File

@ -198,7 +198,7 @@
"label": "OpenSSL",
"enable": "input.openssl == 'yes' || input.openssl == 'linked' || input.openssl == 'runtime'",
"disable": "input.openssl == 'no' || input.ssl == 'no'",
"autoDetect": "!config.winrt",
"autoDetect": "!config.winrt && !config.wasm",
"condition": "!features.securetransport && (features.openssl-linked || libs.openssl_headers)",
"output": [
"privateFeature",
@ -288,6 +288,7 @@
"networkinterface": {
"label": "QNetworkInterface",
"purpose": "Supports enumerating a host's IP addresses and network interfaces.",
"condition": "!config.wasm",
"section": "Networking",
"output": [ "publicFeature", "feature" ]
},

View File

@ -92,13 +92,13 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
sockaddr *sa;
QT_SOCKLEN_T saSize;
if (address.protocol() == QAbstractSocket::IPv4Protocol) {
sa = (sockaddr *)&sa4;
sa = reinterpret_cast<sockaddr *>(&sa4);
saSize = sizeof(sa4);
memset(&sa4, 0, sizeof(sa4));
sa4.sin_family = AF_INET;
sa4.sin_addr.s_addr = htonl(address.toIPv4Address());
} else {
sa = (sockaddr *)&sa6;
sa = reinterpret_cast<sockaddr *>(&sa6);
saSize = sizeof(sa6);
memset(&sa6, 0, sizeof(sa6));
sa6.sin6_family = AF_INET6;
@ -132,14 +132,14 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
switch (p->ai_family) {
case AF_INET: {
QHostAddress addr;
addr.setAddress(ntohl(((sockaddr_in *) p->ai_addr)->sin_addr.s_addr));
addr.setAddress(ntohl(reinterpret_cast<sockaddr_in *>(p->ai_addr)->sin_addr.s_addr));
if (!addresses.contains(addr))
addresses.append(addr);
}
break;
case AF_INET6: {
QHostAddress addr;
addr.setAddress(((sockaddr_in6 *) p->ai_addr)->sin6_addr.s6_addr);
addr.setAddress(reinterpret_cast<const sockaddr_in6 *>(p->ai_addr)->sin6_addr.s6_addr);
if (!addresses.contains(addr))
addresses.append(addr);
}

View File

@ -74,15 +74,16 @@ static QHostAddress addressFromSockaddr(sockaddr *sa)
if (!sa)
return address;
if (sa->sa_family == AF_INET)
address.setAddress(htonl(((sockaddr_in *)sa)->sin_addr.s_addr));
else if (sa->sa_family == AF_INET6) {
address.setAddress(((sockaddr_in6 *)sa)->sin6_addr.s6_addr);
int scope = ((sockaddr_in6 *)sa)->sin6_scope_id;
if (scope)
address.setScopeId(QNetworkInterfaceManager::interfaceNameFromIndex(scope));
} else
if (sa->sa_family == AF_INET) {
address.setAddress(htonl(reinterpret_cast<const sockaddr_in *>(sa)->sin_addr.s_addr));
} else if (sa->sa_family == AF_INET6) {
auto sai6 = reinterpret_cast<const sockaddr_in6 *>(sa);
address.setAddress(sai6->sin6_addr.s6_addr);
if (sai6->sin6_scope_id)
address.setScopeId(QNetworkInterfaceManager::interfaceNameFromIndex(sai6->sin6_scope_id));
} else {
qWarning("Got unknown socket family %d", sa->sa_family);
}
return address;
}
@ -121,7 +122,7 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
ULONG retval = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAdapter, &bufSize);
if (retval == ERROR_BUFFER_OVERFLOW) {
// need more memory
pAdapter = (IP_ADAPTER_ADDRESSES *)malloc(bufSize);
pAdapter = reinterpret_cast<IP_ADAPTER_ADDRESSES *>(malloc(bufSize));
if (!pAdapter)
return interfaces;
// try again
@ -255,7 +256,7 @@ QString QHostInfo::localDomainName()
ULONG bufSize = sizeof info;
pinfo = &info;
if (GetNetworkParams(pinfo, &bufSize) == ERROR_BUFFER_OVERFLOW) {
pinfo = (FIXED_INFO *)malloc(bufSize);
pinfo = reinterpret_cast<FIXED_INFO *>(malloc(bufSize));
if (!pinfo)
return QString();
// try again

View File

@ -566,7 +566,7 @@ void QWindowsSystemProxy::init()
WINHTTP_AUTO_DETECT_TYPE_DNS_A;
} else {
autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
autoProxyOptions.lpszAutoConfigUrl = (LPCWSTR)autoConfigUrl.utf16();
autoProxyOptions.lpszAutoConfigUrl = reinterpret_cast<LPCWSTR>(autoConfigUrl.utf16());
}
}
@ -608,7 +608,7 @@ QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkPro
}
bool getProxySucceeded = ptrWinHttpGetProxyForUrl(sp->hHttpSession,
(LPCWSTR)urlQueryString.utf16(),
reinterpret_cast<LPCWSTR>(urlQueryString.utf16()),
&sp->autoProxyOptions,
&proxyInfo);
DWORD getProxyError = GetLastError();
@ -623,9 +623,10 @@ QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkPro
} else {
//pac file URL is specified as well, try using that
sp->autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
sp->autoProxyOptions.lpszAutoConfigUrl = (LPCWSTR)sp->autoConfigUrl.utf16();
sp->autoProxyOptions.lpszAutoConfigUrl =
reinterpret_cast<LPCWSTR>(sp->autoConfigUrl.utf16());
getProxySucceeded = ptrWinHttpGetProxyForUrl(sp->hHttpSession,
(LPCWSTR)urlQueryString.utf16(),
reinterpret_cast<LPCWSTR>(urlQueryString.utf16()),
&sp->autoProxyOptions,
&proxyInfo);
getProxyError = GetLastError();
@ -638,7 +639,7 @@ QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkPro
// But now we've to enable it (http://msdn.microsoft.com/en-us/library/aa383153%28v=VS.85%29.aspx)
sp->autoProxyOptions.fAutoLogonIfChallenged = TRUE;
getProxySucceeded = ptrWinHttpGetProxyForUrl(sp->hHttpSession,
(LPCWSTR)urlQueryString.utf16(),
reinterpret_cast<LPCWSTR>(urlQueryString.utf16()),
&sp->autoProxyOptions,
&proxyInfo);
getProxyError = GetLastError();

View File

@ -89,7 +89,7 @@ bool QLocalServerPrivate::addListener()
DWORD dwBufferSize = 0;
GetTokenInformation(hToken, TokenUser, 0, 0, &dwBufferSize);
tokenUserBuffer.fill(0, dwBufferSize);
PTOKEN_USER pTokenUser = (PTOKEN_USER)tokenUserBuffer.data();
auto pTokenUser = reinterpret_cast<PTOKEN_USER>(tokenUserBuffer.data());
if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwBufferSize, &dwBufferSize)) {
setError(QLatin1String("QLocalServerPrivate::addListener"));
CloseHandle(hToken);
@ -99,7 +99,7 @@ bool QLocalServerPrivate::addListener()
dwBufferSize = 0;
GetTokenInformation(hToken, TokenPrimaryGroup, 0, 0, &dwBufferSize);
tokenGroupBuffer.fill(0, dwBufferSize);
PTOKEN_PRIMARY_GROUP pTokenGroup = (PTOKEN_PRIMARY_GROUP)tokenGroupBuffer.data();
auto pTokenGroup = reinterpret_cast<PTOKEN_PRIMARY_GROUP>(tokenGroupBuffer.data());
if (!GetTokenInformation(hToken, TokenPrimaryGroup, pTokenGroup, dwBufferSize, &dwBufferSize)) {
setError(QLatin1String("QLocalServerPrivate::addListener"));
CloseHandle(hToken);
@ -140,7 +140,7 @@ bool QLocalServerPrivate::addListener()
aclSize = (aclSize + (sizeof(DWORD) - 1)) & 0xfffffffc;
aclBuffer.fill(0, aclSize);
PACL acl = (PACL)aclBuffer.data();
auto acl = reinterpret_cast<PACL>(aclBuffer.data());
InitializeAcl(acl, aclSize, ACL_REVISION_DS);
if (socketOptions & QLocalServer::UserAccessOption) {
@ -176,7 +176,7 @@ bool QLocalServerPrivate::addListener()
}
listener.handle = CreateNamedPipe(
(const wchar_t *)fullServerName.utf16(), // pipe name
reinterpret_cast<const wchar_t *>(fullServerName.utf16()), // pipe name
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
PIPE_TYPE_BYTE | // byte type pipe
PIPE_READMODE_BYTE | // byte-read mode
@ -299,7 +299,7 @@ void QLocalServerPrivate::_q_onNewConnection()
tryAgain = true;
// Make this the last thing so connected slots can wreak the least havoc
q->incomingConnection((quintptr)handle);
q->incomingConnection(reinterpret_cast<quintptr>(handle));
} else {
if (GetLastError() != ERROR_IO_INCOMPLETE) {
q->close();

View File

@ -155,7 +155,7 @@ void QLocalSocket::connectToServer(OpenMode openMode)
forever {
DWORD permissions = (openMode & QIODevice::ReadOnly) ? GENERIC_READ : 0;
permissions |= (openMode & QIODevice::WriteOnly) ? GENERIC_WRITE : 0;
localSocket = CreateFile((const wchar_t *)d->fullServerName.utf16(), // pipe name
localSocket = CreateFile(reinterpret_cast<const wchar_t *>(d->fullServerName.utf16()), // pipe name
permissions,
0, // no sharing
NULL, // default security attributes
@ -183,7 +183,7 @@ void QLocalSocket::connectToServer(OpenMode openMode)
}
// we have a valid handle
if (setSocketDescriptor((qintptr)localSocket, ConnectedState, openMode))
if (setSocketDescriptor(reinterpret_cast<qintptr>(localSocket), ConnectedState, openMode))
emit connected();
}
@ -371,7 +371,7 @@ void QLocalSocketPrivate::_q_canWrite()
qintptr QLocalSocket::socketDescriptor() const
{
Q_D(const QLocalSocket);
return (qintptr)d->handle;
return reinterpret_cast<qintptr>(d->handle);
}
qint64 QLocalSocket::readBufferSize() const

View File

@ -294,7 +294,8 @@ static inline QAbstractSocket::SocketType qt_socket_getType(qintptr socketDescri
{
int value = 0;
QT_SOCKLEN_T valueSize = sizeof(value);
if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_TYPE, (char *) &value, &valueSize) != 0) {
if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_TYPE,
reinterpret_cast<char *>(&value), &valueSize) != 0) {
WS_ERROR_DEBUG(WSAGetLastError());
} else {
if (value == SOCK_STREAM)
@ -361,7 +362,7 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc
#ifdef HANDLE_FLAG_INHERIT
if (socket != INVALID_SOCKET) {
// make non inheritable the old way
BOOL handleFlags = SetHandleInformation((HANDLE)socket, HANDLE_FLAG_INHERIT, 0);
BOOL handleFlags = SetHandleInformation(reinterpret_cast<HANDLE>(socket), HANDLE_FLAG_INHERIT, 0);
#ifdef QNATIVESOCKETENGINE_DEBUG
qDebug() << "QNativeSocketEnginePrivate::createNewSocket - set inheritable" << handleFlags;
#else
@ -1443,7 +1444,7 @@ qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len)
for (;;) {
WSABUF buf;
buf.buf = (char*)data + ret;
buf.buf = const_cast<char*>(data) + ret;
buf.len = bytesToSend;
DWORD flags = 0;
DWORD bytesWritten = 0;

View File

@ -103,6 +103,14 @@ extern QImage qt_gl_read_frame_buffer(const QSize&, bool, bool);
#define GL_DRAW_FRAMEBUFFER 0x8CA9
#endif
#ifndef GL_DEPTH_STENCIL_ATTACHMENT
#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
#endif
#ifndef GL_DEPTH_STENCIL
#define GL_DEPTH_STENCIL 0x84F9
#endif
/*!
\class QGLFramebufferObjectFormat
\inmodule QtOpenGL
@ -562,6 +570,7 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz,
funcs.glGenRenderbuffers(1, &depth_buffer);
funcs.glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer);
Q_ASSERT(funcs.glIsRenderbuffer(depth_buffer));
#ifndef Q_OS_WASM
if (samples != 0 && funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample))
funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
GL_DEPTH24_STENCIL8, size.width(), size.height());
@ -574,6 +583,19 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz,
GL_RENDERBUFFER, depth_buffer);
funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, stencil_buffer);
#else
// webgl does not allow separate depth and stencil attachments
if (samples != 0) {
funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
GL_DEPTH_STENCIL, size.width(), size.height());
} else {
funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL,
size.width(), size.height());
}
stencil_buffer = depth_buffer;
funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, depth_buffer);
#endif
valid = checkFramebufferStatus();
if (!valid) {

View File

@ -1608,7 +1608,8 @@ void QWindowsFontDatabase::removeApplicationFonts()
if (font.handle) {
RemoveFontMemResourceEx(font.handle);
} else {
RemoveFontResourceExW((LPCWSTR)font.fileName.utf16(), FR_PRIVATE, 0);
RemoveFontResourceExW(reinterpret_cast<LPCWSTR>(font.fileName.utf16()),
FR_PRIVATE, nullptr);
}
}
m_applicationFonts.clear();
@ -1652,7 +1653,8 @@ void QWindowsFontDatabase::refUniqueFont(const QString &uniqueFont)
// ### fixme Qt 6 (QTBUG-58610): See comment at QWindowsFontDatabase::systemDefaultFont()
HFONT QWindowsFontDatabase::systemFont()
{
static const HFONT stock_sysfont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
static const auto stock_sysfont =
reinterpret_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT));
return stock_sysfont;
}

View File

@ -111,9 +111,8 @@ QFixed QWindowsFontEngine::lineThickness() const
static OUTLINETEXTMETRIC *getOutlineTextMetric(HDC hdc)
{
int size;
size = GetOutlineTextMetrics(hdc, 0, 0);
OUTLINETEXTMETRIC *otm = (OUTLINETEXTMETRIC *)malloc(size);
const auto size = GetOutlineTextMetrics(hdc, 0, nullptr);
auto otm = reinterpret_cast<OUTLINETEXTMETRIC *>(malloc(size));
GetOutlineTextMetrics(hdc, size, otm);
return otm;
}
@ -1140,7 +1139,7 @@ QImage QWindowsFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed, const QTra
QImage rgbMask(mask->width(), mask->height(), QImage::Format_RGB32);
for (int y=0; y<mask->height(); ++y) {
uint *dest = (uint *) rgbMask.scanLine(y);
auto dest = reinterpret_cast<uint *>(rgbMask.scanLine(y));
const uint *src = reinterpret_cast<const uint *>(source.constScanLine(y));
for (int x=0; x<mask->width(); ++x) {
dest[x] = 0xffffffff - (0x00ffffff & src[x]);

View File

@ -116,8 +116,8 @@ static bool qt_filterEvent(NSEvent *event)
filterNativeEvent(q_macLocalEventType, static_cast<void*>(event), nullptr))
return true;
if ([event type] == NSApplicationDefined) {
switch (static_cast<short>([event subtype])) {
if (event.type == NSEventTypeApplicationDefined) {
switch (static_cast<short>(event.subtype)) {
case QtCocoaEventSubTypePostMessage:
qt_sendPostedMessage(event);
return true;
@ -137,7 +137,7 @@ static void qt_maybeSendKeyEquivalentUpEvent(NSEvent *event)
// and forward the key event to the key (focus) window.
// However, non-Qt windows will not (and should not) get
// any special treatment, only QWindow-owned NSWindows.
if (event.type == NSKeyUp && (event.modifierFlags & NSCommandKeyMask)) {
if (event.type == NSEventTypeKeyUp && (event.modifierFlags & NSEventModifierFlagCommand)) {
NSWindow *targetWindow = event.window;
if ([targetWindow.class conformsToProtocol:@protocol(QNSWindowProtocol)])
[targetWindow sendEvent:event];

View File

@ -267,13 +267,11 @@ QT_USE_NAMESPACE
inLaunch = false;
if (qEnvironmentVariableIsEmpty("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM")) {
if (__builtin_available(macOS 10.12, *)) {
// Move the application window to front to avoid launching behind the terminal.
// Ignoring other apps is necessary (we must ignore the terminal), but makes
// Qt apps play slightly less nice with other apps when lanching from Finder
// (See the activateIgnoringOtherApps docs.)
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
}
// Move the application window to front to avoid launching behind the terminal.
// Ignoring other apps is necessary (we must ignore the terminal), but makes
// Qt apps play slightly less nice with other apps when lanching from Finder
// (See the activateIgnoringOtherApps docs.)
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
}
}

View File

@ -67,11 +67,6 @@ QImage::Format QCocoaBackingStore::format() const
return QRasterBackingStore::format();
}
#if !QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_12)
static const NSCompositingOperation NSCompositingOperationCopy = NSCompositeCopy;
static const NSCompositingOperation NSCompositingOperationSourceOver = NSCompositeSourceOver;
#endif
/*!
Flushes the given \a region from the specified \a window onto the
screen.

View File

@ -293,25 +293,25 @@ static bool IsMouseOrKeyEvent( NSEvent* event )
switch( [event type] )
{
case NSLeftMouseDown:
case NSLeftMouseUp:
case NSRightMouseDown:
case NSRightMouseUp:
case NSMouseMoved: // ??
case NSLeftMouseDragged:
case NSRightMouseDragged:
case NSMouseEntered:
case NSMouseExited:
case NSKeyDown:
case NSKeyUp:
case NSFlagsChanged: // key modifiers changed?
case NSCursorUpdate: // ??
case NSScrollWheel:
case NSTabletPoint:
case NSTabletProximity:
case NSOtherMouseDown:
case NSOtherMouseUp:
case NSOtherMouseDragged:
case NSEventTypeLeftMouseDown:
case NSEventTypeLeftMouseUp:
case NSEventTypeRightMouseDown:
case NSEventTypeRightMouseUp:
case NSEventTypeMouseMoved: // ??
case NSEventTypeLeftMouseDragged:
case NSEventTypeRightMouseDragged:
case NSEventTypeMouseEntered:
case NSEventTypeMouseExited:
case NSEventTypeKeyDown:
case NSEventTypeKeyUp:
case NSEventTypeFlagsChanged: // key modifiers changed?
case NSEventTypeCursorUpdate: // ??
case NSEventTypeScrollWheel:
case NSEventTypeTabletPoint:
case NSEventTypeTabletProximity:
case NSEventTypeOtherMouseDown:
case NSEventTypeOtherMouseUp:
case NSEventTypeOtherMouseDragged:
#ifndef QT_NO_GESTURES
case NSEventTypeGesture: // touch events
case NSEventTypeMagnify:
@ -335,7 +335,7 @@ static inline void qt_mac_waitForMoreEvents(NSString *runLoopMode = NSDefaultRun
// at least one event occur. Setting 'dequeuing' to 'no' in the following call
// causes it to hang under certain circumstances (QTBUG-28283), so we tell it
// to dequeue instead, just to repost the event again:
NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
untilDate:[NSDate distantFuture]
inMode:runLoopMode
dequeue:YES];
@ -460,7 +460,7 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
// Dispatch all non-user events (but que non-user events up for later). In
// this case, we need more control over which events gets dispatched, and
// cannot use [NSApp runModalSession:session]:
event = [NSApp nextEventMatchingMask:NSAnyEventMask
event = [NSApp nextEventMatchingMask:NSEventMaskAny
untilDate:nil
inMode:NSModalPanelRunLoopMode
dequeue: YES];
@ -479,7 +479,7 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
} while (!d->interrupt && event);
} else do {
// INVARIANT: No modal window is executing.
event = [NSApp nextEventMatchingMask:NSAnyEventMask
event = [NSApp nextEventMatchingMask:NSEventMaskAny
untilDate:nil
inMode:NSDefaultRunLoopMode
dequeue: YES];
@ -936,7 +936,7 @@ void QCocoaEventDispatcherPrivate::cancelWaitForMoreEvents()
// In case the event dispatcher is waiting for more
// events somewhere, we post a dummy event to wake it up:
QMacAutoReleasePool pool;
[NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined location:NSZeroPoint
[NSApp postEvent:[NSEvent otherEventWithType:NSEventTypeApplicationDefined location:NSZeroPoint
modifierFlags:0 timestamp:0. windowNumber:0 context:nil
subtype:QtCocoaEventSubTypeWakeup data1:0 data2:0] atStart:NO];
}

View File

@ -515,8 +515,8 @@ static QString strippedText(QString s)
NSRect textRect = { { 0.0, 3.0 }, { 100.0, 25.0 } };
mTextField = [[NSTextField alloc] initWithFrame:textRect];
[[mTextField cell] setFont:[NSFont systemFontOfSize:
[NSFont systemFontSizeForControlSize:NSRegularControlSize]]];
[mTextField setAlignment:NSRightTextAlignment];
[NSFont systemFontSizeForControlSize:NSControlSizeRegular]]];
[mTextField setAlignment:NSTextAlignmentRight];
[mTextField setEditable:false];
[mTextField setSelectable:false];
[mTextField setBordered:false];

View File

@ -217,9 +217,6 @@ NSOpenGLPixelFormat *QCocoaGLContext::pixelFormatForSurfaceFormat(const QSurface
<< NSOpenGLPFASamples << NSOpenGLPixelFormatAttribute(format.samples());
}
if (format.stereo())
attrs << NSOpenGLPFAStereo;
// Allow rendering on GPUs without a connected display
attrs << NSOpenGLPFAAllowOfflineRenderers;
@ -277,6 +274,9 @@ void QCocoaGLContext::updateSurfaceFormat()
// Debug contexts not supported on macOS
m_format.setOption(QSurfaceFormat::DebugContext, false);
// Nor are stereo buffers (deprecated in macOS 10.12)
m_format.setOption(QSurfaceFormat::StereoBuffers, false);
// ------------------ Query the pixel format ------------------
NSOpenGLPixelFormat *pixelFormat = m_context.pixelFormat;
@ -306,8 +306,6 @@ void QCocoaGLContext::updateSurfaceFormat()
else
m_format.setSwapBehavior(QSurfaceFormat::SingleBuffer);
m_format.setOption(QSurfaceFormat::StereoBuffers, [pixelFormat qt_getAttribute:NSOpenGLPFAStereo]);
// ------------------- Query the context -------------------
m_format.setSwapInterval([m_context qt_getParameter:NSOpenGLCPSwapInterval]);

View File

@ -295,12 +295,12 @@ Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum)
Qt::MouseButton cocoaButton2QtButton(NSEvent *event)
{
switch (event.type) {
case NSMouseMoved:
case NSEventTypeMouseMoved:
return Qt::NoButton;
case NSRightMouseUp:
case NSRightMouseDown:
case NSRightMouseDragged:
case NSEventTypeRightMouseUp:
case NSEventTypeRightMouseDown:
case NSEventTypeRightMouseDragged:
return Qt::RightButton;
default:
@ -318,22 +318,22 @@ Qt::MouseButton cocoaButton2QtButton(NSEvent *event)
QEvent::Type cocoaEvent2QtMouseEvent(NSEvent *event)
{
switch (event.type) {
case NSLeftMouseDown:
case NSRightMouseDown:
case NSOtherMouseDown:
case NSEventTypeLeftMouseDown:
case NSEventTypeRightMouseDown:
case NSEventTypeOtherMouseDown:
return QEvent::MouseButtonPress;
case NSLeftMouseUp:
case NSRightMouseUp:
case NSOtherMouseUp:
case NSEventTypeLeftMouseUp:
case NSEventTypeRightMouseUp:
case NSEventTypeOtherMouseUp:
return QEvent::MouseButtonRelease;
case NSLeftMouseDragged:
case NSRightMouseDragged:
case NSOtherMouseDragged:
case NSEventTypeLeftMouseDragged:
case NSEventTypeRightMouseDragged:
case NSEventTypeOtherMouseDragged:
return QEvent::MouseMove;
case NSMouseMoved:
case NSEventTypeMouseMoved:
return QEvent::MouseMove;
default:
@ -432,7 +432,7 @@ QT_END_NAMESPACE
// FIXME: Not obvious, from Cocoa's documentation, that QString::toNSString() makes a deep copy
button.title = (NSString *)cleanTitle.toCFString();
((NSButtonCell *)button.cell).font =
[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]];
[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSControlSizeRegular]];
[self addSubview:button];
return button;
}

View File

@ -391,7 +391,7 @@ void QCocoaMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect,
if (view) {
// Finally, we need to synthesize an event.
NSEvent *menuEvent = [NSEvent mouseEventWithType:NSRightMouseDown
NSEvent *menuEvent = [NSEvent mouseEventWithType:NSEventTypeRightMouseDown
location:nsPos
modifierFlags:0
timestamp:0

View File

@ -61,13 +61,13 @@ static quint32 constructModifierMask(quint32 accel_key)
quint32 ret = 0;
const bool dontSwap = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta);
if ((accel_key & Qt::CTRL) == Qt::CTRL)
ret |= (dontSwap ? NSControlKeyMask : NSCommandKeyMask);
ret |= (dontSwap ? NSEventModifierFlagControl : NSEventModifierFlagCommand);
if ((accel_key & Qt::META) == Qt::META)
ret |= (dontSwap ? NSCommandKeyMask : NSControlKeyMask);
ret |= (dontSwap ? NSEventModifierFlagCommand : NSEventModifierFlagControl);
if ((accel_key & Qt::ALT) == Qt::ALT)
ret |= NSAlternateKeyMask;
ret |= NSEventModifierFlagOption;
if ((accel_key & Qt::SHIFT) == Qt::SHIFT)
ret |= NSShiftKeyMask;
ret |= NSEventModifierFlagShift;
return ret;
}
@ -343,7 +343,7 @@ NSMenuItem *QCocoaMenuItem::sync()
#endif
{
m_native.keyEquivalent = @"";
m_native.keyEquivalentModifierMask = NSCommandKeyMask;
m_native.keyEquivalentModifierMask = NSEventModifierFlagCommand;
}
NSImage *img = nil;

View File

@ -155,7 +155,7 @@
action:@selector(hideOtherApplications:)
keyEquivalent:@"h"];
hideAllOthersItem.target = self;
hideAllOthersItem.keyEquivalentModifierMask = NSCommandKeyMask | NSAlternateKeyMask;
hideAllOthersItem.keyEquivalentModifierMask = NSEventModifierFlagCommand | NSEventModifierFlagOption;
[appMenu addItem:hideAllOthersItem];
// Show All

View File

@ -225,7 +225,8 @@ static NSString *qt_mac_removePrivateUnicode(NSString *string)
CHECK_MENU_CLASS(menu);
// Interested only in Shift, Cmd, Ctrl & Alt Keys, so ignoring masks like, Caps lock, Num Lock ...
static const NSUInteger mask = NSShiftKeyMask | NSControlKeyMask | NSCommandKeyMask | NSAlternateKeyMask;
static const NSUInteger mask = NSEventModifierFlagShift | NSEventModifierFlagControl
| NSEventModifierFlagCommand | NSEventModifierFlagOption;
// Change the private unicode keys to the ones used in setting the "Key Equivalents"
NSString *characters = qt_mac_removePrivateUnicode(event.charactersIgnoringModifiers);

View File

@ -337,9 +337,9 @@ void QCocoaWindow::setVisible(bool visible)
// Since this isn't a native popup, the window manager doesn't close the popup when you click outside
NSWindow *nativeParentWindow = parentCocoaWindow->nativeWindow();
NSUInteger parentStyleMask = nativeParentWindow.styleMask;
if ((m_resizableTransientParent = (parentStyleMask & NSResizableWindowMask))
&& !(nativeParentWindow.styleMask & NSFullScreenWindowMask))
nativeParentWindow.styleMask &= ~NSResizableWindowMask;
if ((m_resizableTransientParent = (parentStyleMask & NSWindowStyleMaskResizable))
&& !(nativeParentWindow.styleMask & NSWindowStyleMaskFullScreen))
nativeParentWindow.styleMask &= ~NSWindowStyleMaskResizable;
}
}
@ -384,7 +384,9 @@ void QCocoaWindow::setVisible(bool visible)
((NSPanel *)m_view.window).worksWhenModal = YES;
if (!(parentCocoaWindow && window()->transientParent()->isActive()) && window()->type() == Qt::Popup) {
removeMonitor();
monitor = [NSEvent addGlobalMonitorForEventsMatchingMask:NSLeftMouseDownMask|NSRightMouseDownMask|NSOtherMouseDownMask|NSMouseMovedMask handler:^(NSEvent *e) {
NSEventMask eventMask = NSEventMaskLeftMouseDown | NSEventMaskRightMouseDown
| NSEventMaskOtherMouseDown | NSEventMaskMouseMoved;
monitor = [NSEvent addGlobalMonitorForEventsMatchingMask:eventMask handler:^(NSEvent *e) {
const auto button = cocoaButton2QtButton(e);
const auto buttons = currentlyPressedMouseButtons();
const auto eventType = cocoaEvent2QtMouseEvent(e);
@ -446,9 +448,9 @@ void QCocoaWindow::setVisible(bool visible)
if (parentCocoaWindow && window()->type() == Qt::Popup) {
NSWindow *nativeParentWindow = parentCocoaWindow->nativeWindow();
if (m_resizableTransientParent
&& !(nativeParentWindow.styleMask & NSFullScreenWindowMask))
&& !(nativeParentWindow.styleMask & NSWindowStyleMaskFullScreen))
// A window should not be resizable while a transient popup is open
nativeParentWindow.styleMask |= NSResizableWindowMask;
nativeParentWindow.styleMask |= NSWindowStyleMaskResizable;
}
}
@ -491,39 +493,39 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags)
const bool frameless = (flags & Qt::FramelessWindowHint) || windowIsPopupType(type);
// Remove zoom button by disabling resize for CustomizeWindowHint windows, except for
// Qt::Tool windows (e.g. dock windows) which should always be resizeable.
const bool resizeable = !(flags & Qt::CustomizeWindowHint) || (type == Qt::Tool);
// Qt::Tool windows (e.g. dock windows) which should always be resizable.
const bool resizable = !(flags & Qt::CustomizeWindowHint) || (type == Qt::Tool);
// Select base window type. Note that the value of NSBorderlessWindowMask is 0.
NSUInteger styleMask = (frameless || !resizeable) ? NSBorderlessWindowMask : NSResizableWindowMask;
NSUInteger styleMask = (frameless || !resizable) ? NSWindowStyleMaskBorderless : NSWindowStyleMaskResizable;
if (frameless) {
// No further customizations for frameless since there are no window decorations.
} else if (flags & Qt::CustomizeWindowHint) {
if (flags & Qt::WindowTitleHint)
styleMask |= NSTitledWindowMask;
styleMask |= NSWindowStyleMaskTitled;
if (flags & Qt::WindowCloseButtonHint)
styleMask |= NSClosableWindowMask;
styleMask |= NSWindowStyleMaskClosable;
if (flags & Qt::WindowMinimizeButtonHint)
styleMask |= NSMiniaturizableWindowMask;
styleMask |= NSWindowStyleMaskMiniaturizable;
if (flags & Qt::WindowMaximizeButtonHint)
styleMask |= NSResizableWindowMask;
styleMask |= NSWindowStyleMaskResizable;
} else {
styleMask |= NSClosableWindowMask | NSTitledWindowMask;
styleMask |= NSWindowStyleMaskClosable | NSWindowStyleMaskTitled;
if (type != Qt::Dialog)
styleMask |= NSMiniaturizableWindowMask;
styleMask |= NSWindowStyleMaskMiniaturizable;
}
if (type == Qt::Tool)
styleMask |= NSUtilityWindowMask;
styleMask |= NSWindowStyleMaskUtilityWindow;
if (m_drawContentBorderGradient)
styleMask |= NSTexturedBackgroundWindowMask;
styleMask |= NSWindowStyleMaskTexturedBackground;
// Don't wipe fullscreen state
if (m_view.window.styleMask & NSFullScreenWindowMask)
styleMask |= NSFullScreenWindowMask;
if (m_view.window.styleMask & NSWindowStyleMaskFullScreen)
styleMask |= NSWindowStyleMaskFullScreen;
return styleMask;
}
@ -630,7 +632,7 @@ void QCocoaWindow::applyWindowState(Qt::WindowStates requestedState)
const NSWindow *nsWindow = m_view.window;
if (nsWindow.styleMask & NSUtilityWindowMask
if (nsWindow.styleMask & NSWindowStyleMaskUtilityWindow
&& newState & (Qt::WindowMinimized | Qt::WindowFullScreen)) {
qWarning() << window()->type() << "windows can not be made" << newState;
handleWindowStateChanged(HandleUnconditionally);
@ -704,14 +706,14 @@ void QCocoaWindow::toggleMaximized()
// The NSWindow needs to be resizable, otherwise the window will
// not be possible to zoom back to non-zoomed state.
const bool wasResizable = window.styleMask & NSResizableWindowMask;
window.styleMask |= NSResizableWindowMask;
const bool wasResizable = window.styleMask & NSWindowStyleMaskResizable;
window.styleMask |= NSWindowStyleMaskResizable;
const id sender = window;
[window zoom:sender];
if (!wasResizable)
window.styleMask &= ~NSResizableWindowMask;
window.styleMask &= ~NSWindowStyleMaskResizable;
}
void QCocoaWindow::toggleFullScreen()
@ -735,13 +737,13 @@ void QCocoaWindow::windowWillEnterFullScreen()
// The NSWindow needs to be resizable, otherwise we'll end up with
// the normal window geometry, centered in the middle of the screen
// on a black background. The styleMask will be reset below.
m_view.window.styleMask |= NSResizableWindowMask;
m_view.window.styleMask |= NSWindowStyleMaskResizable;
}
bool QCocoaWindow::isTransitioningToFullScreen() const
{
NSWindow *window = m_view.window;
return window.styleMask & NSFullScreenWindowMask && !window.qt_fullScreen;
return window.styleMask & NSWindowStyleMaskFullScreen && !window.qt_fullScreen;
}
void QCocoaWindow::windowDidEnterFullScreen()
@ -765,7 +767,7 @@ void QCocoaWindow::windowWillExitFullScreen()
// The NSWindow needs to be resizable, otherwise we'll end up with
// a weird zoom animation. The styleMask will be reset below.
m_view.window.styleMask |= NSResizableWindowMask;
m_view.window.styleMask |= NSWindowStyleMaskResizable;
}
void QCocoaWindow::windowDidExitFullScreen()
@ -1707,7 +1709,7 @@ void QCocoaWindow::applyContentBorderThickness(NSWindow *window)
return;
if (!m_drawContentBorderGradient) {
window.styleMask = window.styleMask & ~NSTexturedBackgroundWindowMask;
window.styleMask = window.styleMask & ~NSWindowStyleMaskTexturedBackground;
[window.contentView.superview setNeedsDisplay:YES];
window.titlebarAppearsTransparent = NO;
return;
@ -1733,7 +1735,7 @@ void QCocoaWindow::applyContentBorderThickness(NSWindow *window)
int effectiveBottomContentBorderThickness = m_bottomContentBorderThickness;
[window setStyleMask:[window styleMask] | NSTexturedBackgroundWindowMask];
[window setStyleMask:[window styleMask] | NSWindowStyleMaskTexturedBackground];
window.titlebarAppearsTransparent = YES;
[window setContentBorderThickness:effectiveTopContentBorderThickness forEdge:NSMaxYEdge];

View File

@ -45,15 +45,15 @@
{
const bool dontSwapCtrlAndMeta = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta);
Qt::KeyboardModifiers qtMods =Qt::NoModifier;
if (modifierFlags & NSShiftKeyMask)
if (modifierFlags & NSEventModifierFlagShift)
qtMods |= Qt::ShiftModifier;
if (modifierFlags & NSControlKeyMask)
if (modifierFlags & NSEventModifierFlagShift)
qtMods |= dontSwapCtrlAndMeta ? Qt::ControlModifier : Qt::MetaModifier;
if (modifierFlags & NSAlternateKeyMask)
if (modifierFlags & NSEventModifierFlagOption)
qtMods |= Qt::AltModifier;
if (modifierFlags & NSCommandKeyMask)
if (modifierFlags & NSEventModifierFlagCommand)
qtMods |= dontSwapCtrlAndMeta ? Qt::MetaModifier : Qt::ControlModifier;
if (modifierFlags & NSNumericPadKeyMask)
if (modifierFlags & NSEventModifierFlagCommand)
qtMods |= Qt::KeypadModifier;
return qtMods;
}
@ -201,7 +201,7 @@
Q_UNUSED(sender);
NSEvent *currentEvent = [NSApp currentEvent];
if (!currentEvent || currentEvent.type != NSKeyDown)
if (!currentEvent || currentEvent.type != NSEventTypeKeyDown)
return;
// Handling the key event may recurse back here through interpretKeyEvents
@ -233,11 +233,11 @@
Qt::Key qt_code;
};
static qt_mac_enum_mapper modifier_key_symbols[] = {
{ NSShiftKeyMask, Qt::Key_Shift },
{ NSControlKeyMask, Qt::Key_Meta },
{ NSCommandKeyMask, Qt::Key_Control },
{ NSAlternateKeyMask, Qt::Key_Alt },
{ NSAlphaShiftKeyMask, Qt::Key_CapsLock },
{ NSEventModifierFlagShift, Qt::Key_Shift },
{ NSEventModifierFlagControl, Qt::Key_Meta },
{ NSEventModifierFlagCommand, Qt::Key_Control },
{ NSEventModifierFlagOption, Qt::Key_Alt },
{ NSEventModifierFlagCapsLock, Qt::Key_CapsLock },
{ 0ul, Qt::Key_unknown } };
for (int i = 0; modifier_key_symbols[i].mac_mask != 0u; ++i) {
uint mac_mask = modifier_key_symbols[i].mac_mask;

View File

@ -91,31 +91,26 @@
if (m_buttons != Qt::NoButton)
return;
NSEventType ty = [theEvent type];
switch (ty) {
case NSLeftMouseDown:
switch (theEvent.type) {
case NSEventTypeLeftMouseDown:
case NSEventTypeLeftMouseDragged:
m_frameStrutButtons |= Qt::LeftButton;
break;
case NSLeftMouseUp:
case NSEventTypeLeftMouseUp:
m_frameStrutButtons &= ~Qt::LeftButton;
break;
case NSRightMouseDown:
case NSEventTypeRightMouseDown:
case NSEventTypeRightMouseDragged:
m_frameStrutButtons |= Qt::RightButton;
break;
case NSLeftMouseDragged:
m_frameStrutButtons |= Qt::LeftButton;
break;
case NSRightMouseDragged:
m_frameStrutButtons |= Qt::RightButton;
break;
case NSRightMouseUp:
case NSEventTypeRightMouseUp:
m_frameStrutButtons &= ~Qt::RightButton;
break;
case NSOtherMouseDown:
m_frameStrutButtons |= cocoaButton2QtButton([theEvent buttonNumber]);
case NSEventTypeOtherMouseDown:
m_frameStrutButtons |= cocoaButton2QtButton(theEvent.buttonNumber);
break;
case NSOtherMouseUp:
m_frameStrutButtons &= ~cocoaButton2QtButton([theEvent buttonNumber]);
case NSEventTypeOtherMouseUp:
m_frameStrutButtons &= ~cocoaButton2QtButton(theEvent.buttonNumber);
default:
break;
}
@ -581,7 +576,7 @@
// knowing whether or not a NSEventPhaseEnded will be followed by a momentum phase.
// The best we can do is to look at the event queue and hope that the system has
// had time to emit a momentum phase event.
if ([NSApp nextEventMatchingMask:NSScrollWheelMask untilDate:[NSDate distantPast]
if ([NSApp nextEventMatchingMask:NSEventMaskScrollWheel untilDate:[NSDate distantPast]
inMode:@"QtMomementumEventSearchMode" dequeue:NO].momentumPhase == NSEventPhaseBegan) {
Q_ASSERT(pixelDelta.isNull() && angleDelta.isNull());
return; // Ignore this event, as it has a delta of 0,0

View File

@ -64,7 +64,7 @@ Q_GLOBAL_STATIC(QCocoaTabletDeviceDataHash, tabletDeviceDataHash)
return false;
NSEventType eventType = [theEvent type];
if (eventType != NSTabletPoint && [theEvent subtype] != NSTabletPointEventSubtype)
if (eventType != NSEventTypeTabletPoint && [theEvent subtype] != NSEventSubtypeTabletPoint)
return false; // Not a tablet event.
ulong timestamp = [theEvent timestamp] * 1000;
@ -82,7 +82,7 @@ Q_GLOBAL_STATIC(QCocoaTabletDeviceDataHash, tabletDeviceDataHash)
}
const QCocoaTabletDeviceData &deviceData = tabletDeviceDataHash->value(deviceId);
bool down = (eventType != NSMouseMoved);
bool down = (eventType != NSEventTypeMouseMoved);
qreal pressure;
if (down) {
@ -182,17 +182,17 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
deviceData.capabilityMask = [theEvent capabilityMask];
switch ([theEvent pointingDeviceType]) {
case NSUnknownPointingDevice:
case NSPointingDeviceTypeUnknown:
default:
deviceData.pointerType = QTabletEvent::UnknownPointer;
break;
case NSPenPointingDevice:
case NSPointingDeviceTypePen:
deviceData.pointerType = QTabletEvent::Pen;
break;
case NSCursorPointingDevice:
case NSPointingDeviceTypeCursor:
deviceData.pointerType = QTabletEvent::Cursor;
break;
case NSEraserPointingDevice:
case NSPointingDeviceTypeEraser:
deviceData.pointerType = QTabletEvent::Eraser;
break;
}

View File

@ -50,13 +50,13 @@ Q_LOGGING_CATEGORY(lcQpaEvents, "qt.qpa.events");
static bool isMouseEvent(NSEvent *ev)
{
switch ([ev type]) {
case NSLeftMouseDown:
case NSLeftMouseUp:
case NSRightMouseDown:
case NSRightMouseUp:
case NSMouseMoved:
case NSLeftMouseDragged:
case NSRightMouseDragged:
case NSEventTypeLeftMouseDown:
case NSEventTypeLeftMouseUp:
case NSEventTypeRightMouseDown:
case NSEventTypeRightMouseUp:
case NSEventTypeMouseMoved:
case NSEventTypeLeftMouseDragged:
case NSEventTypeRightMouseDragged:
return true;
default:
return false;
@ -186,16 +186,16 @@ static bool isMouseEvent(NSEvent *ev)
/*!
Borderless windows need a transparent background
Technically windows with NSTexturedBackgroundWindowMask (such
as windows with unified toolbars) need to draw the textured
Technically windows with NSWindowStyleMaskTexturedBackground
(such as windows with unified toolbars) need to draw the textured
background of the NSWindow, and can't have a transparent
background, but as NSBorderlessWindowMask is 0, you can't
have a window with NSTexturedBackgroundWindowMask that is
background, but as NSWindowStyleMaskBorderless is 0, you can't
have a window with NSWindowStyleMaskTexturedBackground that is
also borderless.
*/
- (NSColor *)backgroundColor
{
return self.styleMask == NSBorderlessWindowMask
return self.styleMask == NSWindowStyleMaskBorderless
? [NSColor clearColor] : qt_objcDynamicSuper();
}
@ -262,29 +262,20 @@ static bool isMouseEvent(NSEvent *ev)
NSEnumerator<NSWindow*> *windowEnumerator = nullptr;
NSApplication *application = [NSApplication sharedApplication];
#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_12)
if (__builtin_available(macOS 10.12, *)) {
// Unfortunately there's no NSWindowListOrderedBackToFront,
// so we have to manually reverse the order using an array.
NSMutableArray<NSWindow *> *windows = [NSMutableArray<NSWindow *> new];
[application enumerateWindowsWithOptions:NSWindowListOrderedFrontToBack
usingBlock:^(NSWindow *window, BOOL *) {
// For some reason AppKit will give us nil-windows, skip those
if (!window)
return;
// Unfortunately there's no NSWindowListOrderedBackToFront,
// so we have to manually reverse the order using an array.
NSMutableArray<NSWindow *> *windows = [NSMutableArray<NSWindow *> new];
[application enumerateWindowsWithOptions:NSWindowListOrderedFrontToBack
usingBlock:^(NSWindow *window, BOOL *) {
// For some reason AppKit will give us nil-windows, skip those
if (!window)
return;
[windows addObject:window];
}
];
[windows addObject:window];
}
];
windowEnumerator = windows.reverseObjectEnumerator;
} else
#endif
{
// No way to get ordered list of windows, so fall back to unordered,
// list, which typically corresponds to window creation order.
windowEnumerator = application.windows.objectEnumerator;
}
windowEnumerator = windows.reverseObjectEnumerator;
for (NSWindow *window in windowEnumerator) {
// We're meddling with normal and floating windows, so leave others alone

View File

@ -115,10 +115,8 @@ void QIOSIntegration::initialize()
m_touchDevice = new QTouchDevice;
m_touchDevice->setType(QTouchDevice::TouchScreen);
QTouchDevice::Capabilities touchCapabilities = QTouchDevice::Position | QTouchDevice::NormalizedPosition;
if (__builtin_available(iOS 9, *)) {
if (mainScreen.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)
touchCapabilities |= QTouchDevice::Pressure;
}
if (mainScreen.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)
touchCapabilities |= QTouchDevice::Pressure;
m_touchDevice->setCapabilities(touchCapabilities);
QWindowSystemInterface::registerTouchDevice(m_touchDevice);
#if QT_CONFIG(tabletevent)

Some files were not shown because too many files have changed in this diff Show More