From 29c0377f07f4942f9957ea87d59c252148dc9e5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Fri, 1 Jun 2018 15:13:30 +0200 Subject: [PATCH] WebAssembly for QtBase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is the squashed diff from wip/webassembly to dev. Done-with: Peng Wu Done-with: Sami Enne Done-with: Morten Johan Sørvig Started-by: Andrew Knight Change-Id: I6562433c0a38d6ec49ab675e0f104f2665f3392d Reviewed-by: Lorn Potter Reviewed-by: Eskil Abrahamsen Blomfeldt --- configure.json | 5 +- configure.pri | 11 +- mkspecs/features/toolchain.prf | 4 +- mkspecs/features/wasm/qt.prf | 12 + mkspecs/features/wasm/wasm.prf | 81 ++ mkspecs/wasm-emscripten/qmake.conf | 90 +++ mkspecs/wasm-emscripten/qplatformdefs.h | 181 +++++ .../include/double-conversion/utils.h | 2 +- src/3rdparty/wasm/DejaVuSans.ttf | Bin 0 -> 493564 bytes src/3rdparty/wasm/LICENSE | 15 + src/3rdparty/wasm/Vera.ttf | Bin 0 -> 65932 bytes src/3rdparty/wasm/qt_attribution.json | 21 + src/corelib/codecs/qtextcodec_p.h | 2 +- src/corelib/configure.json | 4 +- src/corelib/global/archdetect.cpp | 2 + src/corelib/global/qcompilerdetection.h | 3 + src/corelib/global/qlogging.cpp | 37 + src/corelib/global/qprocessordetection.h | 6 + src/corelib/global/qsystemdetection.h | 2 + src/corelib/io/qfilesystemengine_unix.cpp | 4 +- src/corelib/io/qsettings.cpp | 11 + src/corelib/kernel/qcoreapplication.cpp | 22 + src/corelib/kernel/qeventdispatcher_unix.cpp | 2 +- src/corelib/kernel/qeventloop.cpp | 24 + src/corelib/mimetypes/qmimedatabase.cpp | 2 + src/corelib/tools/qsimd.cpp | 17 +- src/corelib/tools/qunicodetables_p.h | 6 + src/corelib/tools/tools.pri | 2 +- src/gui/configure.json | 10 +- src/gui/configure.pri | 1 + src/gui/kernel/qguiapplication.cpp | 12 +- src/gui/kernel/qopenglcontext.cpp | 3 + src/gui/opengl/qopenglframebufferobject.cpp | 45 ++ src/network/access/access.pri | 7 + src/network/access/qnetworkaccessmanager.cpp | 13 + src/network/access/qnetworkaccessmanager.h | 3 + src/network/access/qnetworkreplywasmimpl.cpp | 640 ++++++++++++++++ src/network/access/qnetworkreplywasmimpl_p.h | 153 ++++ src/network/configure.json | 3 +- src/opengl/qglframebufferobject.cpp | 22 + src/plugins/platforms/platforms.pro | 2 + src/plugins/platforms/wasm/main.cpp | 54 ++ src/plugins/platforms/wasm/qtloader.js | 516 +++++++++++++ src/plugins/platforms/wasm/qtlogo.svg | 67 ++ .../platforms/wasm/qwasmbackingstore.cpp | 165 ++++ .../platforms/wasm/qwasmbackingstore.h | 70 ++ .../platforms/wasm/qwasmcompositor.cpp | 721 ++++++++++++++++++ src/plugins/platforms/wasm/qwasmcompositor.h | 169 ++++ src/plugins/platforms/wasm/qwasmcursor.cpp | 131 ++++ src/plugins/platforms/wasm/qwasmcursor.h | 43 ++ .../platforms/wasm/qwasmeventdispatcher.cpp | 181 +++++ .../platforms/wasm/qwasmeventdispatcher.h | 64 ++ .../platforms/wasm/qwasmeventtranslator.cpp | 522 +++++++++++++ .../platforms/wasm/qwasmeventtranslator.h | 210 +++++ .../platforms/wasm/qwasmfontdatabase.cpp | 86 +++ .../platforms/wasm/qwasmfontdatabase.h | 49 ++ .../platforms/wasm/qwasmintegration.cpp | 219 ++++++ src/plugins/platforms/wasm/qwasmintegration.h | 92 +++ .../platforms/wasm/qwasmopenglcontext.cpp | 147 ++++ .../platforms/wasm/qwasmopenglcontext.h | 63 ++ src/plugins/platforms/wasm/qwasmscreen.cpp | 118 +++ src/plugins/platforms/wasm/qwasmscreen.h | 82 ++ .../platforms/wasm/qwasmstylepixmaps_p.h | 183 +++++ src/plugins/platforms/wasm/qwasmtheme.cpp | 50 ++ src/plugins/platforms/wasm/qwasmtheme.h | 56 ++ src/plugins/platforms/wasm/qwasmwindow.cpp | 398 ++++++++++ src/plugins/platforms/wasm/qwasmwindow.h | 124 +++ src/plugins/platforms/wasm/wasm.json | 3 + src/plugins/platforms/wasm/wasm.pro | 65 ++ src/plugins/platforms/wasm/wasm_shell.html | 61 ++ src/widgets/dialogs/qfiledialog.cpp | 2 +- src/widgets/graphicsview/qgraphicsitem_p.h | 4 +- src/widgets/kernel/qopenglwidget.cpp | 10 + util/unicode/main.cpp | 8 + 74 files changed, 6191 insertions(+), 24 deletions(-) create mode 100644 mkspecs/features/wasm/qt.prf create mode 100644 mkspecs/features/wasm/wasm.prf create mode 100644 mkspecs/wasm-emscripten/qmake.conf create mode 100644 mkspecs/wasm-emscripten/qplatformdefs.h create mode 100644 src/3rdparty/wasm/DejaVuSans.ttf create mode 100644 src/3rdparty/wasm/LICENSE create mode 100644 src/3rdparty/wasm/Vera.ttf create mode 100644 src/3rdparty/wasm/qt_attribution.json create mode 100644 src/network/access/qnetworkreplywasmimpl.cpp create mode 100644 src/network/access/qnetworkreplywasmimpl_p.h create mode 100644 src/plugins/platforms/wasm/main.cpp create mode 100644 src/plugins/platforms/wasm/qtloader.js create mode 100644 src/plugins/platforms/wasm/qtlogo.svg create mode 100644 src/plugins/platforms/wasm/qwasmbackingstore.cpp create mode 100644 src/plugins/platforms/wasm/qwasmbackingstore.h create mode 100644 src/plugins/platforms/wasm/qwasmcompositor.cpp create mode 100644 src/plugins/platforms/wasm/qwasmcompositor.h create mode 100644 src/plugins/platforms/wasm/qwasmcursor.cpp create mode 100644 src/plugins/platforms/wasm/qwasmcursor.h create mode 100644 src/plugins/platforms/wasm/qwasmeventdispatcher.cpp create mode 100644 src/plugins/platforms/wasm/qwasmeventdispatcher.h create mode 100644 src/plugins/platforms/wasm/qwasmeventtranslator.cpp create mode 100644 src/plugins/platforms/wasm/qwasmeventtranslator.h create mode 100644 src/plugins/platforms/wasm/qwasmfontdatabase.cpp create mode 100644 src/plugins/platforms/wasm/qwasmfontdatabase.h create mode 100644 src/plugins/platforms/wasm/qwasmintegration.cpp create mode 100644 src/plugins/platforms/wasm/qwasmintegration.h create mode 100644 src/plugins/platforms/wasm/qwasmopenglcontext.cpp create mode 100644 src/plugins/platforms/wasm/qwasmopenglcontext.h create mode 100644 src/plugins/platforms/wasm/qwasmscreen.cpp create mode 100644 src/plugins/platforms/wasm/qwasmscreen.h create mode 100644 src/plugins/platforms/wasm/qwasmstylepixmaps_p.h create mode 100644 src/plugins/platforms/wasm/qwasmtheme.cpp create mode 100644 src/plugins/platforms/wasm/qwasmtheme.h create mode 100644 src/plugins/platforms/wasm/qwasmwindow.cpp create mode 100644 src/plugins/platforms/wasm/qwasmwindow.h create mode 100644 src/plugins/platforms/wasm/wasm.json create mode 100644 src/plugins/platforms/wasm/wasm.pro create mode 100644 src/plugins/platforms/wasm/wasm_shell.html diff --git a/configure.json b/configure.json index 1f45f2ccb29..8c8118f39a1 100644 --- a/configure.json +++ b/configure.json @@ -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": { diff --git a/configure.pri b/configure.pri index 03eacd3c079..805b985fa6f 100644 --- a/configure.pri +++ b/configure.pri @@ -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.") diff --git a/mkspecs/features/toolchain.prf b/mkspecs/features/toolchain.prf index bce3ef39545..4ecfb8d8896 100644 --- a/mkspecs/features/toolchain.prf +++ b/mkspecs/features/toolchain.prf @@ -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&" diff --git a/mkspecs/features/wasm/qt.prf b/mkspecs/features/wasm/qt.prf new file mode 100644 index 00000000000..9b9b58d3dee --- /dev/null +++ b/mkspecs/features/wasm/qt.prf @@ -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) + diff --git a/mkspecs/features/wasm/wasm.prf b/mkspecs/features/wasm/wasm.prf new file mode 100644 index 00000000000..278a6719c74 --- /dev/null +++ b/mkspecs/features/wasm/wasm.prf @@ -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 +} diff --git a/mkspecs/wasm-emscripten/qmake.conf b/mkspecs/wasm-emscripten/qmake.conf new file mode 100644 index 00000000000..c3b67310c82 --- /dev/null +++ b/mkspecs/wasm-emscripten/qmake.conf @@ -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) diff --git a/mkspecs/wasm-emscripten/qplatformdefs.h b/mkspecs/wasm-emscripten/qplatformdefs.h new file mode 100644 index 00000000000..c1a0d7b1a85 --- /dev/null +++ b/mkspecs/wasm-emscripten/qplatformdefs.h @@ -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 + +// We are hot - unistd.h should have turned on the specific APIs we requested + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifndef QT_NO_IPV6IFNAME +#include +#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 diff --git a/src/3rdparty/double-conversion/include/double-conversion/utils.h b/src/3rdparty/double-conversion/include/double-conversion/utils.h index ca7646d817e..ff00855bea3 100644 --- a/src/3rdparty/double-conversion/include/double-conversion/utils.h +++ b/src/3rdparty/double-conversion/include/double-conversion/utils.h @@ -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 diff --git a/src/3rdparty/wasm/DejaVuSans.ttf b/src/3rdparty/wasm/DejaVuSans.ttf new file mode 100644 index 0000000000000000000000000000000000000000..7e411a71beeb3087ff9a23027dd5aeb415766942 GIT binary patch literal 493564 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 z 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 literal 0 HcmV?d00001 diff --git a/src/3rdparty/wasm/LICENSE b/src/3rdparty/wasm/LICENSE new file mode 100644 index 00000000000..4f9e8544b74 --- /dev/null +++ b/src/3rdparty/wasm/LICENSE @@ -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. diff --git a/src/3rdparty/wasm/Vera.ttf b/src/3rdparty/wasm/Vera.ttf new file mode 100644 index 0000000000000000000000000000000000000000..58cd6b5e61eff273e920942e28041f8ddcf1e1b5 GIT binary patch literal 65932 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

B-* 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 405 diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index a931b432209..2aabaa2ffb3 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -94,6 +94,10 @@ # include "private/qcore_unix_p.h" #endif +#ifdef Q_OS_WASM +#include +#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 // -------------------------------------------------------------------------- @@ -1735,6 +1770,8 @@ static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &con # 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); +# elif defined Q_OS_WASM + handledStderr |= wasm_default_message_handler(type, context, message); # endif #endif diff --git a/src/corelib/global/qprocessordetection.h b/src/corelib/global/qprocessordetection.h index 9a3dfd776d1..aaa27dff4a7 100644 --- a/src/corelib/global/qprocessordetection.h +++ b/src/corelib/global/qprocessordetection.h @@ -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 /* diff --git a/src/corelib/global/qsystemdetection.h b/src/corelib/global/qsystemdetection.h index cacb95b6745..aabe46f3c27 100644 --- a/src/corelib/global/qsystemdetection.h +++ b/src/corelib/global/qsystemdetection.h @@ -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__) diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index 835e6a6a441..eebf36416e6 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -860,7 +860,7 @@ QString QFileSystemEngine::resolveUserName(uint userId) QVarLengthArray 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 +884,7 @@ QString QFileSystemEngine::resolveGroupName(uint groupId) QVarLengthArray 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); diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index 1134c6bb85e..391d2a49afa 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -77,6 +77,10 @@ # include #endif +#ifdef Q_OS_WASM +#include +#endif + #include #include @@ -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); } diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 0303916c113..1350a7aa946 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -118,6 +118,10 @@ # include #endif +#ifdef Q_OS_WASM +#include +#endif + #ifdef QT_BOOTSTRAPPED #include #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(); diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp index a28f2e3f0a9..535f86fefe5 100644 --- a/src/corelib/kernel/qeventdispatcher_unix.cpp +++ b/src/corelib/kernel/qeventdispatcher_unix.cpp @@ -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())); diff --git a/src/corelib/kernel/qeventloop.cpp b/src/corelib/kernel/qeventloop.cpp index f1d32b15d19..a6cc51621a4 100644 --- a/src/corelib/kernel/qeventloop.cpp +++ b/src/corelib/kernel/qeventloop.cpp @@ -48,6 +48,10 @@ #include "qeventloop_p.h" #include +#ifdef Q_OS_WASM +#include +#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 } /*! diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp index a58698af53b..10b5c8eafd9 100644 --- a/src/corelib/mimetypes/qmimedatabase.cpp +++ b/src/corelib/mimetypes/qmimedatabase.cpp @@ -151,7 +151,9 @@ void QMimeDatabasePrivate::loadProviders() QVector 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(); diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index 85efd3cded5..07a8b022bc4 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -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 } diff --git a/src/corelib/tools/qunicodetables_p.h b/src/corelib/tools/qunicodetables_p.h index f3fb6ec1b0e..3f2e91a9b2a 100644 --- a/src/corelib/tools/qunicodetables_p.h +++ b/src/corelib/tools/qunicodetables_p.h @@ -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 */ diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index 9ec6ea4894d..dc28e0e0a25 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -220,7 +220,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/* diff --git a/src/gui/configure.json b/src/gui/configure.json index 26a5ae9a3d0..4741ed345a4 100644 --- a/src/gui/configure.json +++ b/src/gui/configure.json @@ -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", diff --git a/src/gui/configure.pri b/src/gui/configure.pri index b40536e41db..2971fd136e8 100644 --- a/src/gui/configure.pri +++ b/src/gui/configure.pri @@ -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 diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 93e8b6ee8f0..bc1f83a9c8b 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -114,6 +114,10 @@ # include #endif // Q_OS_WIN +#ifdef Q_OS_WASM +#include +#endif + #include #include @@ -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; diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index 7bf941b9a1c..cd50294a6c3 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -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); diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp index 6486a447eed..cae3d516c45 100644 --- a/src/gui/opengl/qopenglframebufferobject.cpp +++ b/src/gui/opengl/qopenglframebufferobject.cpp @@ -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; diff --git a/src/network/access/access.pri b/src/network/access/access.pri index a129beda15c..b068f962835 100644 --- a/src/network/access/access.pri +++ b/src/network/access/access.pri @@ -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) { diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 96e3f92db1c..bec98a3f584 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -82,6 +82,9 @@ #include #include #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 diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h index a0ce3eddcd4..67b3a8b71b5 100644 --- a/src/network/access/qnetworkaccessmanager.h +++ b/src/network/access/qnetworkaccessmanager.h @@ -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()) diff --git a/src/network/access/qnetworkreplywasmimpl.cpp b/src/network/access/qnetworkreplywasmimpl.cpp new file mode 100644 index 00000000000..9c2ff8fb89d --- /dev/null +++ b/src/network/access/qnetworkreplywasmimpl.cpp @@ -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 +#include +#include +#include +#include + +#include +#include + +#include + +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(data); + + const QString reasonStr = QString::fromUtf8(reinterpret_cast(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(buffer), bufferSize); + } + } + break; + }; + } + +void QNetworkReplyWasmImplPrivate::onProgressCallback(void* data, int bytesWritten, int total, uint timestamp) +{ + Q_UNUSED(timestamp); + + QNetworkReplyWasmImplPrivate *handler = reinterpret_cast(data); + handler->emitDataReadProgress(bytesWritten, total); +} + +void QNetworkReplyWasmImplPrivate::onRequestErrorCallback(void* data, int statusCode, int statusReason) +{ + QString reasonStr = QString::fromUtf8(reinterpret_cast(statusReason)); + + QNetworkReplyWasmImplPrivate *handler = reinterpret_cast(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(data); + handler->headersReceived(reinterpret_cast(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 > &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(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::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 diff --git a/src/network/access/qnetworkreplywasmimpl_p.h b/src/network/access/qnetworkreplywasmimpl_p.h new file mode 100644 index 00000000000..a707390503a --- /dev/null +++ b/src/network/access/qnetworkreplywasmimpl_p.h @@ -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 + +#include +#include + +#include +#include + +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 pendingDownloadData; + QSharedPointer pendingDownloadProgress; + + qint64 bytesDownloaded; + qint64 bytesBuffered; + + qint64 downloadBufferReadPosition; + qint64 downloadBufferCurrentSize; + qint64 totalDownloadSize; + qint64 percentFinished; + QByteArray downloadBuffer; + + QIODevice *outgoingData; + QSharedPointer 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 diff --git a/src/network/configure.json b/src/network/configure.json index 32fcfb499f3..327131ba11f 100644 --- a/src/network/configure.json +++ b/src/network/configure.json @@ -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" ] }, diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp index 0b386ededc2..0b2ddf97fe5 100644 --- a/src/opengl/qglframebufferobject.cpp +++ b/src/opengl/qglframebufferobject.cpp @@ -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) { diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro index e61887618fc..5bf2b77421d 100644 --- a/src/plugins/platforms/platforms.pro +++ b/src/plugins/platforms/platforms.pro @@ -46,6 +46,8 @@ haiku { SUBDIRS += haiku } +wasm: SUBDIRS = wasm + qtConfig(mirclient): SUBDIRS += mirclient qtConfig(integrityfb): SUBDIRS += integrity diff --git a/src/plugins/platforms/wasm/main.cpp b/src/plugins/platforms/wasm/main.cpp new file mode 100644 index 00000000000..a4d23b4e0db --- /dev/null +++ b/src/plugins/platforms/wasm/main.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) 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.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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "qwasmintegration.h" + +QT_BEGIN_NAMESPACE + +class QWasmIntegrationPlugin : public QPlatformIntegrationPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "wasm.json") +public: + QPlatformIntegration *create(const QString &, const QStringList &) override; +}; + +QPlatformIntegration *QWasmIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (!system.compare(QStringLiteral("wasm"), Qt::CaseInsensitive)) + return new QWasmIntegration; + + return nullptr; +} + +QT_END_NAMESPACE + +#include "main.moc" diff --git a/src/plugins/platforms/wasm/qtloader.js b/src/plugins/platforms/wasm/qtloader.js new file mode 100644 index 00000000000..37a5308034c --- /dev/null +++ b/src/plugins/platforms/wasm/qtloader.js @@ -0,0 +1,516 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) 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.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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// QtLoader provides javascript API for managing Qt application modules. +// +// QtLoader provides API on top of Emscripten which supports common lifecycle +// tasks such as displaying placeholder content while the module downloads, +// handing application exits, and checking for browser wasm support. +// +// There are two usage modes: +// * Managed: QtLoader owns and manages the HTML display elements like +// the loader and canvas. +// * External: The embedding HTML page owns the display elements. QtLoader +// provides event callbacks which the page reacts to. +// +// Managed mode usage: +// +// var config = { +// containerElements : [$("container-id")]; +// } +// var qtLoader = QtLoader(config); +// qtLoader.loadEmscriptenModule("applicationName"); +// +// External mode.usage: +// +// var config = { +// showLoader: function() { +// loader.style.display = 'block' +// canvas.style.display = 'hidden' +// }, +// showCanvas: function() { +// loader.style.display = 'hidden' +// canvas.style.display = 'block' +// return canvas; +// } +// } +// var qtLoader = QtLoader(config); +// qtLoader.loadEmscriptenModule("applicationName"); +// +// Config keys +// +// containerElements : [container-element, ...] +// One or more HTML elements. QtLoader will display loader elements +// on these while loading the applicaton, and replace the loader with a +// canvas on load complete. +// showLoader : function(status, containerElement) +// Optional loading element constructor function. Implement to create +// a custom loading screen. This function may be called multiple times, +// while preparing the application binary. "status" is a string +// containing the loading sub-status, and may be either "Downloading", +// or "Compiling". The browser may be using streaming compilation, in +// which case the wasm module is compiled during downloading and the +// there is no separate compile step. +// showCanvas : function(containerElement) +// Optional canvas constructor function. Implement to create custom +// canvas elements. +// showExit : function(crashed, exitCode, containerElement) +// Optional exited element constructor function. +// showError : function(crashed, exitCode, containerElement) +// Optional error element constructor function. +// +// path : +// Prefix path for wasm file, realative to the loading HMTL file. +// restartMode : "DoNotRestart", "RestartOnExit", "RestartOnCrash" +// Controls whether the application should be reloaded on exits. The default is "DoNotRestart" +// restartType : "RestartModule", "ReloadPage" +// restartLimit : +// Restart attempts limit. The default is 10. +// stdoutEnabled : +// stderrEnabled : +// environment : +// key-value environment variable pairs. +// +// QtLoader object API +// +// webAssemblySupported : bool +// webGLSupported : bool +// canLoadQt : bool +// Reports if WebAssembly and WebGL are supported. These are requirements for +// running Qt applications. +// loadEmscriptenModule(applicationName) +// Loads the application from the given emscripten javascript module file and wasm file +// status +// One of "Created", "Loading", "Running", "Exited". +// crashed +// Set to true if there was an unclean exit. +// exitCode +// main()/emscripten_force_exit() return code. Valid on status change to +// "Exited", iff crashed is false. +// exitText +// Abort/exit message. + + +var Module = {} + +function QtLoader(config) +{ + function webAssemblySupported() { + return typeof WebAssembly !== "undefined" + } + + function webGLSupported() { + // We expect that WebGL is supported if WebAssembly is; however + // the GPU may be blacklisted. + try { + var canvas = document.createElement("canvas"); + return !!(window.WebGLRenderingContext && (canvas.getContext("webgl") || canvas.getContext("experimental-webgl"))); + } catch (e) { + return false; + } + } + + function canLoadQt() { + // The current Qt implementation requires WebAssembly (asm.js is not in use), + // and also WebGL (there is no raster fallback). + return webAssemblySupported() && webGLSupported(); + } + + function removeChildren(element) { + while (element.firstChild) element.removeChild(element.firstChild); + } + + // Set default state handler functions if needed + if (config.containerElements !== undefined) { + config.showError = config.showError || function(errorText, container) { + removeChildren(container); + var errorTextElement = document.createElement("text"); + errorTextElement.className = "QtError" + errorTextElement.innerHTML = errorText; + return errorTextElement; + } + + config.showLoader = config.showLoader || function(loadingState, container) { + removeChildren(container); + var loadingText = document.createElement("text"); + loadingText.className = "QtLoading" + loadingText.innerHTML = '

${loadingState}...

'; + return loadingText; + }; + + config.showCanvas = config.showCanvas || function(container) { + removeChildren(container); + var canvas = document.createElement("canvas"); + canvas.className = "QtCanvas" + canvas.style = "height: 100%; width: 100%;" + return canvas; + } + + config.showExit = config.showExit || function(crashed, exitCode, container) { + if (!crashed) + return undefined; + + removeChildren(container); + var fontSize = 54; + var crashSymbols = ["\u{1F615}", "\u{1F614}", "\u{1F644}", "\u{1F928}", "\u{1F62C}", + "\u{1F915}", "\u{2639}", "\u{1F62E}", "\u{1F61E}", "\u{1F633}"]; + var symbolIndex = Math.floor(Math.random() * crashSymbols.length); + var errorHtml = ` ${crashSymbols[symbolIndex]} ` + var errorElement = document.createElement("text"); + errorElement.className = "QtExit" + errorElement.innerHTML = errorHtml; + return errorElement; + } + } + + config.restartMode = config.restartMode || "DoNotRestart"; + config.restartLimit = config.restartLimit || 10; + + if (config.stdoutEnabled === undefined) config.stdoutEnabled = true; + if (config.stderrEnabled === undefined) config.stderrEnabled = true; + + // Make sure config.path is defined and ends with "/" if needed + if (config.path === undefined) + config.path = ""; + if (config.path.length > 0 && !config.path.endsWith("/")) + config.path = config.path.concat("/"); + + if (config.environment === undefined) + config.environment = {}; + + var publicAPI = {}; + publicAPI.webAssemblySupported = webAssemblySupported(); + publicAPI.webGLSupported = webGLSupported(); + publicAPI.canLoadQt = canLoadQt(); + publicAPI.canLoadApplication = canLoadQt(); + publicAPI.status = undefined; + publicAPI.loadEmscriptenModule = loadEmscriptenModule; + + restartCount = 0; + + function fetchResource(filePath) { + var fullPath = config.path + filePath; + return fetch(fullPath).then(function(response) { + if (!response.ok) { + self.error = response.status + " " + response.statusText + " " + response.url; + setStatus("Error"); + return Promise.reject(self.error) + } else { + return response; + } + }); + } + + function fetchText(filePath) { + return fetchResource(filePath).then(function(response) { + return response.text(); + }); + } + + function fetchThenCompileWasm(response) { + return response.arrayBuffer().then(function(data) { + self.loaderSubState = "Compiling"; + setStatus("Loading") // trigger loaderSubState udpate + return WebAssembly.compile(data); + }); + } + + function fetchCompileWasm(filePath) { + return fetchResource(filePath).then(function(response) { + if (typeof WebAssembly.compileStreaming !== "undefined") { + self.loaderSubState = "Downloading/Compiling"; + setStatus("Loading"); + return WebAssembly.compileStreaming(response).catch(function(error) { + // compileStreaming may/will fail if the server does not set the correct + // mime type (application/wasm) for the wasm file. Fall back to fetch, + // then compile in this case. + return fetchThenCompileWasm(response); + }); + } else { + // Fall back to fetch, then compile if compileStreaming is not supported + return fetchThenCompileWasm(response); + } + }); + } + + function loadEmscriptenModule(applicationName) { + + // Loading in qtloader.js goes through four steps: + // 1) Check prerequisites + // 2) Download resources + // 3) Configure the emscripten Module object + // 4) Start the emcripten runtime, after which emscripten takes over + + // Check for Wasm & WebGL support; set error and return before downloading resources if missing + if (!webAssemblySupported()) { + self.error = "Error: WebAssembly is not supported" + setStatus("Error"); + return; + } + if (!webGLSupported()) { + self.error = "Error: WebGL is not supported" + setStatus("Error"); + return; + } + + // Continue waiting if loadEmscriptenModule() is called again + if (publicAPI.status == "Loading") + return; + self.loaderSubState = "Downloading"; + setStatus("Loading"); + + // Fetch emscripten generated javascript runtime + var emscriptenModuleSource = undefined + var emscriptenModuleSourcePromise = fetchText(applicationName + ".js").then(function(source) { + emscriptenModuleSource = source + }); + + // Fetch and compile wasm module + var wasmModule = undefined; + var wasmModulePromise = fetchCompileWasm(applicationName + ".wasm").then(function (module) { + wasmModule = module; + }); + + // Wait for all resources ready + Promise.all([emscriptenModuleSourcePromise, wasmModulePromise]).then(function(){ + completeLoadEmscriptenModule(applicationName, emscriptenModuleSource, wasmModule); + }).catch(function(error) { + self.error = error; + setStatus("Error"); + }); + } + + function completeLoadEmscriptenModule(applicationName, emscriptenModuleSource, wasmModule) { + + // The wasm binary has been compiled into a module during resource download, + // and is ready to be instantiated. Define the instantiateWasm callback which + // emscripten will call to create the instance. + Module.instantiateWasm = function(imports, successCallback) { + return WebAssembly.instantiate(wasmModule, imports).then(function(instance) { + successCallback(instance); + return instance; + }, function(error) { + self.error = error; + setStatus("Error"); + }); + }; + + Module.locateFile = Module.locateFile || function(filename) { + return config.path + filename; + }; + + // Attach status callbacks + Module.setStatus = Module.setStatus || function(text) { + // Currently the only usable status update from this function + // is "Running..." + if (text.startsWith("Running")) + setStatus("Running"); + }; + Module.monitorRunDependencies = Module.monitorRunDependencies || function(left) { + // console.log("monitorRunDependencies " + left) + }; + + // Attach standard out/err callbacks. + Module.print = Module.print || function(text) { + if (config.stdoutEnabled) + console.log(text) + }; + Module.printErr = Module.printErr || function(text) { + // Filter out OpenGL getProcAddress warnings. Qt tries to resolve + // all possible function/extension names at startup which causes + // emscripten to spam the console log with warnings. + if (text.startsWith !== undefined && text.startsWith("bad name in getProcAddress:")) + return; + + if (config.stderrEnabled) + console.log(text) + }; + + // Error handling: set status to "Exited", update crashed and + // exitCode according to exit type. + // Emscripten will typically call printErr with the error text + // as well. Note that emscripten may also throw exceptions from + // async callbacks. These should be handled in window.onerror by user code. + Module.onAbort = Module.onAbort || function(text) { + publicAPI.crashed = true; + publicAPI.exitText = text; + setStatus("Exited"); + }; + Module.quit = Module.quit || function(code, exception) { + if (exception.name == "ExitStatus") { + // Clean exit with code + publicAPI.exitText = undefined + publicAPI.exitCode = code; + } else { + publicAPI.exitText = exception.toString(); + publicAPI.crashed = true; + } + setStatus("Exited"); + }; + + // Set environment variables + Module.preRun = Module.preRun || [] + Module.preRun.push(function() { + for (var [key, value] of Object.entries(config.environment)) { + Module.ENV[key.toUpperCase()] = value; + } + }); + + config.restart = function() { + + // Restart by reloading the page. This will wipe all state which means + // reload loops can't be prevented. + if (config.restartType == "ReloadPage") { + location.reload(); + } + + // Restart by readling the emscripten app module. + ++self.restartCount; + if (self.restartCount > config.restartLimit) { + self.error = "Error: This application has crashed too many times and has been disabled. Reload the page to try again." + setStatus("Error"); + return; + } + loadEmscriptenModule(applicationName); + }; + + publicAPI.exitCode = undefined; + publicAPI.exitText = undefined; + publicAPI.crashed = false; + + // Finally evaluate the emscripten application script, which will + // reference the global Module object created above. + self.eval(emscriptenModuleSource); // ES5 indirect global scope eval + } + + function setErrorContent() { + if (config.containerElements === undefined) { + if (config.showError !== undefined) + config.showError(self.error); + return; + } + + for (container of config.containerElements) { + var errorElement = config.showError(self.error, container); + container.appendChild(errorElement); + } + } + + function setLoaderContent() { + if (config.containerElements === undefined) { + if (config.showLoader !== undefined) + config.showLoader(self.loaderSubState); + return; + } + + for (container of config.containerElements) { + var loaderElement = config.showLoader(self.loaderSubState, container); + container.appendChild(loaderElement); + } + } + + function setCanvasContent() { + var firstCanvas; + if (config.containerElements === undefined) { + firstCanvas = config.showCanvas(); + } else { + for (container of config.containerElements) { + var canvasElement = config.showCanvas(container); + container.appendChild(canvasElement); + } + firstCanvas = config.containerElements[0].firstChild; + } + + if (Module.canvas === undefined) { + Module.canvas = firstCanvas; + } + } + + function setExitContent() { + + // publicAPI.crashed = true; + + if (publicAPI.status != "Exited") + return; + + if (config.containerElements === undefined) { + if (config.showExit !== undefined) + config.showExit(publicAPI.crashed, publicAPI.exitCode); + return; + } + + if (!publicAPI.crashed) + return; + + for (container of config.containerElements) { + var loaderElement = config.showExit(publicAPI.crashed, publicAPI.exitCode, container); + if (loaderElement !== undefined) + container.appendChild(loaderElement); + } + } + + var committedStatus = undefined; + function handleStatusChange() { + if (publicAPI.status != "Loading" && committedStatus == publicAPI.status) + return; + committedStatus = publicAPI.status; + + if (publicAPI.status == "Error") { + setErrorContent(); + } else if (publicAPI.status == "Loading") { + setLoaderContent(); + } else if (publicAPI.status == "Running") { + setCanvasContent(); + } else if (publicAPI.status == "Exited") { + if (config.restartMode == "RestartOnExit" || + config.restartMode == "RestartOnCrash" && publicAPI.crashed) { + committedStatus = undefined; + config.restart(); + } else { + setExitContent(); + } + } + + // Send status change notification + if (config.statusChanged) + config.statusChanged(publicAPI.status); + } + + function setStatus(status) { + if (status != "Loading" && publicAPI.status == status) + return; + publicAPI.status = status; + + window.setTimeout(function() { handleStatusChange(); }, 0); + } + + setStatus("Created"); + + return publicAPI; +} diff --git a/src/plugins/platforms/wasm/qtlogo.svg b/src/plugins/platforms/wasm/qtlogo.svg new file mode 100644 index 00000000000..cb8989bb793 --- /dev/null +++ b/src/plugins/platforms/wasm/qtlogo.svg @@ -0,0 +1,67 @@ + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/src/plugins/platforms/wasm/qwasmbackingstore.cpp b/src/plugins/platforms/wasm/qwasmbackingstore.cpp new file mode 100644 index 00000000000..5b40c448075 --- /dev/null +++ b/src/plugins/platforms/wasm/qwasmbackingstore.cpp @@ -0,0 +1,165 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) 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.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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwasmbackingstore.h" +#include "qwasmwindow.h" +#include "qwasmcompositor.h" + +#include +#include +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +QWasmBackingStore::QWasmBackingStore(QWasmCompositor *compositor, QWindow *window) + : QPlatformBackingStore(window) + , m_compositor(compositor) + , m_texture(new QOpenGLTexture(QOpenGLTexture::Target2D)) +{ + QWasmWindow *wasmWindow = static_cast(window->handle()); + if (wasmWindow) + wasmWindow->setBackingStore(this); +} + +QWasmBackingStore::~QWasmBackingStore() +{ +} + +QPaintDevice *QWasmBackingStore::paintDevice() +{ + return &m_image; +} + +void QWasmBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(window); + Q_UNUSED(region); + Q_UNUSED(offset); + + m_dirty |= region; + m_compositor->requestRedraw(); +} + +void QWasmBackingStore::updateTexture() +{ + if (m_dirty.isNull()) + return; + + if (!m_texture->isCreated()) { + m_texture->setMinificationFilter(QOpenGLTexture::Nearest); + m_texture->setMagnificationFilter(QOpenGLTexture::Nearest); + m_texture->setWrapMode(QOpenGLTexture::ClampToEdge); + m_texture->setData(m_image, QOpenGLTexture::DontGenerateMipMaps); + m_texture->create(); + } + m_texture->bind(); + + QRegion fixed; + QRect imageRect = m_image.rect(); + + for (const QRect &rect : m_dirty) { + + // Convert device-independent dirty region to device region + qreal dpr = m_image.devicePixelRatio(); + QRect deviceRect = QRect(rect.topLeft() * dpr, rect.size() * dpr); + + // intersect with image rect to be sure + QRect r = imageRect & deviceRect; + // if the rect is wide enough it is cheaper to just extend it instead of doing an image copy + if (r.width() >= imageRect.width() / 2) { + r.setX(0); + r.setWidth(imageRect.width()); + } + + fixed |= r; + } + + for (const QRect &rect : fixed) { + // if the sub-rect is full-width we can pass the image data directly to + // OpenGL instead of copying, since there is no gap between scanlines + if (rect.width() == imageRect.width()) { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE, + m_image.constScanLine(rect.y())); + } else { + glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE, + m_image.copy(rect).constBits()); + } + } + /* End of code taken from QEGLPlatformBackingStore */ + + m_dirty = QRegion(); +} + +void QWasmBackingStore::beginPaint(const QRegion ®ion) +{ + m_dirty |= region; + // Keep backing store device pixel ratio in sync with window + if (m_image.devicePixelRatio() != window()->devicePixelRatio()) + resize(backingStore()->size(), backingStore()->staticContents()); + + QPainter painter(&m_image); + painter.setCompositionMode(QPainter::CompositionMode_Source); + const QColor blank = Qt::transparent; + for (const QRect &rect : region) + painter.fillRect(rect, blank); +} + +void QWasmBackingStore::resize(const QSize &size, const QRegion &staticContents) +{ + Q_UNUSED(staticContents) + + m_image = QImage(size * window()->devicePixelRatio(), QImage::Format_RGB32); + m_image.setDevicePixelRatio(window()->devicePixelRatio()); + + if (m_texture->isCreated()) + m_texture->destroy(); +} + +QImage QWasmBackingStore::toImage() const +{ + // used by QPlatformBackingStore::composeAndFlush + return m_image; +} + +const QImage &QWasmBackingStore::getImageRef() const +{ + return m_image; +} + +const QOpenGLTexture *QWasmBackingStore::getUpdatedTexture() +{ + updateTexture(); + return m_texture.data(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/wasm/qwasmbackingstore.h b/src/plugins/platforms/wasm/qwasmbackingstore.h new file mode 100644 index 00000000000..6ffa262e3d5 --- /dev/null +++ b/src/plugins/platforms/wasm/qwasmbackingstore.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) 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.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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWASMBACKINGSTORE_H +#define QWASMBACKINGSTORE_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QOpenGLTexture; +class QRegion; +class QWasmCompositor; + +class QWasmBackingStore : public QPlatformBackingStore +{ +public: + QWasmBackingStore(QWasmCompositor *compositor, QWindow *window); + ~QWasmBackingStore(); + + QPaintDevice *paintDevice() override; + + void beginPaint(const QRegion &) override; + void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) override; + void resize(const QSize &size, const QRegion &staticContents) override; + QImage toImage() const override; + const QImage &getImageRef() const; + + const QOpenGLTexture *getUpdatedTexture(); + +protected: + void updateTexture(); + +private: + QWasmCompositor *m_compositor; + QImage m_image; + QScopedPointer m_texture; + QRegion m_dirty; +}; + +QT_END_NAMESPACE + +#endif // QWASMBACKINGSTORE_H diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp new file mode 100644 index 00000000000..f3ea0133250 --- /dev/null +++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp @@ -0,0 +1,721 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) 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.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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwasmcompositor.h" +#include "qwasmwindow.h" +#include "qwasmstylepixmaps_p.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +Q_GUI_EXPORT int qt_defaultDpiX(); + +QWasmCompositedWindow::QWasmCompositedWindow() + : window(nullptr) + , parentWindow(nullptr) + , flushPending(false) + , visible(false) +{ +} + +QWasmCompositor::QWasmCompositor() + : m_frameBuffer(nullptr) + , m_blitter(new QOpenGLTextureBlitter) + , m_needComposit(false) + , m_inFlush(false) + , m_inResize(false) + , m_isEnabled(true) + , m_targetDevicePixelRatio(1) +{ +} + +QWasmCompositor::~QWasmCompositor() +{ + delete m_frameBuffer; +} + +void QWasmCompositor::setEnabled(bool enabled) +{ + m_isEnabled = enabled; +} + +void QWasmCompositor::addWindow(QWasmWindow *window, QWasmWindow *parentWindow) +{ + QWasmCompositedWindow compositedWindow; + compositedWindow.window = window; + compositedWindow.parentWindow = parentWindow; + m_compositedWindows.insert(window, compositedWindow); + + if (parentWindow == 0) + m_windowStack.append(window); + else + m_compositedWindows[parentWindow].childWindows.append(window); + + notifyTopWindowChanged(window); +} + +void QWasmCompositor::removeWindow(QWasmWindow *window) +{ + QWasmWindow *platformWindow = m_compositedWindows[window].parentWindow; + + if (platformWindow) { + QWasmWindow *parentWindow = window; + m_compositedWindows[parentWindow].childWindows.removeAll(window); + } + + m_windowStack.removeAll(window); + m_compositedWindows.remove(window); + + notifyTopWindowChanged(window); +} + +void QWasmCompositor::setScreen(QWasmScreen *screen) +{ + m_screen = screen; +} + +void QWasmCompositor::setVisible(QWasmWindow *window, bool visible) +{ + QWasmCompositedWindow &compositedWindow = m_compositedWindows[window]; + if (compositedWindow.visible == visible) + return; + + compositedWindow.visible = visible; + compositedWindow.flushPending = true; + if (visible) + compositedWindow.damage = compositedWindow.window->geometry(); + else + m_globalDamage = compositedWindow.window->geometry(); // repaint previosly covered area. + + requestRedraw(); +} + +void QWasmCompositor::raise(QWasmWindow *window) +{ + if (m_compositedWindows.size() <= 1) + return; + + QWasmCompositedWindow &compositedWindow = m_compositedWindows[window]; + compositedWindow.damage = compositedWindow.window->geometry(); + m_windowStack.removeAll(window); + m_windowStack.append(window); + + notifyTopWindowChanged(window); +} + +void QWasmCompositor::lower(QWasmWindow *window) +{ + if (m_compositedWindows.size() <= 1) + return; + + m_windowStack.removeAll(window); + m_windowStack.prepend(window); + QWasmCompositedWindow &compositedWindow = m_compositedWindows[window]; + m_globalDamage = compositedWindow.window->geometry(); // repaint previosly covered area. + + notifyTopWindowChanged(window); +} + +void QWasmCompositor::setParent(QWasmWindow *window, QWasmWindow *parent) +{ + m_compositedWindows[window].parentWindow = parent; + + requestRedraw(); +} + +void QWasmCompositor::flush(QWasmWindow *window, const QRegion ®ion) +{ + QWasmCompositedWindow &compositedWindow = m_compositedWindows[window]; + compositedWindow.flushPending = true; + compositedWindow.damage = region; + + requestRedraw(); +} + +int QWasmCompositor::windowCount() const +{ + return m_windowStack.count(); +} + + +void QWasmCompositor::redrawWindowContent() +{ + // Redraw window content by sending expose events. This redraw + // will cause a backing store flush, which will call requestRedraw() + // to composit. + for (QWasmWindow *platformWindow : m_windowStack) { + QWindow *window = platformWindow->window(); + QWindowSystemInterface::handleExposeEvent( + window, QRect(QPoint(0, 0), window->geometry().size())); + } +} + +void QWasmCompositor::requestRedraw() +{ + if (m_needComposit) + return; + + m_needComposit = true; + QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest)); +} + +QWindow *QWasmCompositor::windowAt(QPoint p, int padding) const +{ + int index = m_windowStack.count() - 1; + // qDebug() << "window at" << "point" << p << "window count" << index; + + while (index >= 0) { + const QWasmCompositedWindow &compositedWindow = m_compositedWindows[m_windowStack.at(index)]; + //qDebug() << "windwAt testing" << compositedWindow.window << + + QRect geometry = compositedWindow.window->windowFrameGeometry() + .adjusted(-padding, -padding, padding, padding); + + if (compositedWindow.visible && geometry.contains(p)) + return m_windowStack.at(index)->window(); + --index; + } + + return 0; +} + +QWindow *QWasmCompositor::keyWindow() const +{ + return m_windowStack.at(m_windowStack.count() - 1)->window(); +} + +bool QWasmCompositor::event(QEvent *ev) +{ + if (ev->type() == QEvent::UpdateRequest) { + if (m_isEnabled) + frame(); + return true; + } + + return QObject::event(ev); +} + +void QWasmCompositor::blit(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, const QOpenGLTexture *texture, QRect targetGeometry) +{ + QMatrix4x4 m; + m.translate(-1.0f, -1.0f); + + m.scale(2.0f / (float)screen->geometry().width(), + 2.0f / (float)screen->geometry().height()); + + m.translate((float)targetGeometry.width() / 2.0f, + (float)-targetGeometry.height() / 2.0f); + + m.translate(targetGeometry.x(), screen->geometry().height() - targetGeometry.y()); + + m.scale(0.5f * (float)targetGeometry.width(), + 0.5f * (float)targetGeometry.height()); + + blitter->blit(texture->textureId(), m, QOpenGLTextureBlitter::OriginTopLeft); +} + +void QWasmCompositor::drawWindowContent(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window) +{ + QWasmBackingStore *backingStore = window->backingStore(); + + QOpenGLTexture const *texture = backingStore->getUpdatedTexture(); + + blit(blitter, screen, texture, window->geometry()); +} + +QPalette QWasmCompositor::makeWindowPalette() +{ + QPalette palette; + palette.setColor(QPalette::Active, QPalette::Highlight, + palette.color(QPalette::Active, QPalette::Highlight)); + palette.setColor(QPalette::Active, QPalette::Base, + palette.color(QPalette::Active, QPalette::Highlight)); + palette.setColor(QPalette::Inactive, QPalette::Highlight, + palette.color(QPalette::Inactive, QPalette::Dark)); + palette.setColor(QPalette::Inactive, QPalette::Base, + palette.color(QPalette::Inactive, QPalette::Dark)); + palette.setColor(QPalette::Inactive, QPalette::HighlightedText, + palette.color(QPalette::Inactive, QPalette::Window)); + + return palette; +} + +QRect QWasmCompositor::titlebarRect(QWasmTitleBarOptions tb, QWasmCompositor::SubControls subcontrol) +{ + QRect ret; + const int controlMargin = 2; + const int controlHeight = tb.rect.height() - controlMargin *2; + const int delta = controlHeight + controlMargin; + int offset = 0; + + bool isMinimized = tb.state & Qt::WindowMinimized; + bool isMaximized = tb.state & Qt::WindowMaximized; + + ret = tb.rect; + switch (subcontrol) { + case SC_TitleBarLabel: + if (tb.flags & Qt::WindowSystemMenuHint) + ret.adjust(delta, 0, -delta, 0); + break; + case SC_TitleBarCloseButton: + if (tb.flags & Qt::WindowSystemMenuHint) { + ret.adjust(0, 0, -delta, 0); + offset += delta; + } + break; + case SC_TitleBarMaxButton: + if (!isMaximized && tb.flags & Qt::WindowMaximizeButtonHint) { + ret.adjust(0, 0, -delta*2, 0); + offset += (delta +delta); + } + break; + case SC_TitleBarNormalButton: + if (isMinimized && (tb.flags & Qt::WindowMinimizeButtonHint)) + offset += delta; + else if (isMaximized && (tb.flags & Qt::WindowMaximizeButtonHint)) + ret.adjust(0, 0, -delta*2, 0); + offset += (delta +delta); + break; + case SC_TitleBarSysMenu: + if (tb.flags & Qt::WindowSystemMenuHint) { + ret.setRect(tb.rect.left() + controlMargin, tb.rect.top() + controlMargin, + controlHeight, controlHeight); + } + break; + default: + break; + }; + + if (subcontrol != SC_TitleBarLabel && subcontrol != SC_TitleBarSysMenu) { + ret.setRect(tb.rect.right() - offset, tb.rect.top() + controlMargin, + controlHeight, controlHeight); + } + + if (qApp->layoutDirection() == Qt::LeftToRight) + return ret; + + QRect rect = ret; + rect.translate(2 * (tb.rect.right() - ret.right()) + + ret.width() - tb.rect.width(), 0); + + return rect; +} + +int dpiScaled(qreal value) +{ + return value * (qreal(qt_defaultDpiX()) / 96.0); +} + +QWasmCompositor::QWasmTitleBarOptions QWasmCompositor::makeTitleBarOptions(const QWasmWindow *window) +{ + int width = window->windowFrameGeometry().width(); + int border = window->borderWidth(); + + QWasmTitleBarOptions titleBarOptions; + + titleBarOptions.rect = QRect(border, border, width - 2 * border, window->titleHeight()); + titleBarOptions.flags = window->window()->flags(); + titleBarOptions.state = window->window()->windowState(); + + bool isMaximized = titleBarOptions.state & Qt::WindowMaximized; // this gets reset when maximized + + if (titleBarOptions.flags & (Qt::WindowTitleHint)) + titleBarOptions.subControls |= SC_TitleBarLabel; + if (titleBarOptions.flags & Qt::WindowMaximizeButtonHint) { + if (isMaximized) + titleBarOptions.subControls |= SC_TitleBarNormalButton; + else + titleBarOptions.subControls |= SC_TitleBarMaxButton; + } + if (titleBarOptions.flags & Qt::WindowSystemMenuHint) { + titleBarOptions.subControls |= SC_TitleBarCloseButton; + titleBarOptions.subControls |= SC_TitleBarSysMenu; + } + + + titleBarOptions.palette = QWasmCompositor::makeWindowPalette(); + + if (window->window()->isActive()) + titleBarOptions.palette.setCurrentColorGroup(QPalette::Active); + else + titleBarOptions.palette.setCurrentColorGroup(QPalette::Inactive); + + if (window->activeSubControl() != QWasmCompositor::SC_None) + titleBarOptions.subControls = window->activeSubControl(); + + if (!window->window()->title().isEmpty()) + titleBarOptions.titleBarOptionsString = window->window()->title(); + + return titleBarOptions; +} + +void QWasmCompositor::drawWindowDecorations(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window) +{ + int width = window->windowFrameGeometry().width(); + int height = window->windowFrameGeometry().height(); + qreal dpr = window->devicePixelRatio(); + + QImage image(QSize(width * dpr, height * dpr), QImage::Format_RGB32); + image.setDevicePixelRatio(dpr); + QPainter painter(&image); + painter.fillRect(QRect(0, 0, width, height), painter.background()); + + QWasmTitleBarOptions titleBarOptions = makeTitleBarOptions(window); + + drawTitlebarWindow(titleBarOptions, &painter); + + QWasmFrameOptions frameOptions; + frameOptions.rect = QRect(0, 0, width, height); + frameOptions.lineWidth = dpiScaled(4.); + + drawFrameWindow(frameOptions, &painter); + + painter.end(); + + QOpenGLTexture texture(QOpenGLTexture::Target2D); + texture.setMinificationFilter(QOpenGLTexture::Nearest); + texture.setMagnificationFilter(QOpenGLTexture::Nearest); + texture.setWrapMode(QOpenGLTexture::ClampToEdge); + texture.setData(image, QOpenGLTexture::DontGenerateMipMaps); + texture.create(); + texture.bind(); + + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image.width(), image.height(), GL_RGBA, GL_UNSIGNED_BYTE, + image.constScanLine(0)); + + blit(blitter, screen, &texture, QRect(window->windowFrameGeometry().topLeft(), QSize(width, height))); +} + +void QWasmCompositor::drawFrameWindow(QWasmFrameOptions options, QPainter *painter) +{ + int x = options.rect.x(); + int y = options.rect.y(); + int w = options.rect.width(); + int h = options.rect.height(); + const QColor &c1 = options.palette.light().color(); + const QColor &c2 = options.palette.shadow().color(); + const QColor &c3 = options.palette.midlight().color(); + const QColor &c4 = options.palette.dark().color(); + const QBrush *fill = 0; + + const qreal devicePixelRatio = painter->device()->devicePixelRatioF(); + if (!qFuzzyCompare(devicePixelRatio, qreal(1))) { + const qreal inverseScale = qreal(1) / devicePixelRatio; + painter->scale(inverseScale, inverseScale); + x = qRound(devicePixelRatio * x); + y = qRound(devicePixelRatio * y); + w = qRound(devicePixelRatio * w); + h = qRound(devicePixelRatio * h); + } + + QPen oldPen = painter->pen(); + QPoint a[3] = { QPoint(x, y+h-2), QPoint(x, y), QPoint(x+w-2, y) }; + painter->setPen(c1); + painter->drawPolyline(a, 3); + QPoint b[3] = { QPoint(x, y+h-1), QPoint(x+w-1, y+h-1), QPoint(x+w-1, y) }; + painter->setPen(c2); + painter->drawPolyline(b, 3); + if (w > 4 && h > 4) { + QPoint c[3] = { QPoint(x+1, y+h-3), QPoint(x+1, y+1), QPoint(x+w-3, y+1) }; + painter->setPen(c3); + painter->drawPolyline(c, 3); + QPoint d[3] = { QPoint(x+1, y+h-2), QPoint(x+w-2, y+h-2), QPoint(x+w-2, y+1) }; + painter->setPen(c4); + painter->drawPolyline(d, 3); + if (fill) + painter->fillRect(QRect(x+2, y+2, w-4, h-4), *fill); + } + painter->setPen(oldPen); +} + +//from commonstyle.cpp +static QPixmap cachedPixmapFromXPM(const char * const *xpm) +{ + QPixmap result; + const QString tag = QString::asprintf("xpm:0x%p", static_cast(xpm)); + if (!QPixmapCache::find(tag, &result)) { + result = QPixmap(xpm); + QPixmapCache::insert(tag, result); + } + return result; +} + +void QWasmCompositor::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, + const QPixmap &pixmap) const +{ + qreal scale = pixmap.devicePixelRatio(); + QSize size = pixmap.size() / scale; + int x = rect.x(); + int y = rect.y(); + int w = size.width(); + int h = size.height(); + if ((alignment & Qt::AlignVCenter) == Qt::AlignVCenter) + y += rect.size().height()/2 - h/2; + else if ((alignment & Qt::AlignBottom) == Qt::AlignBottom) + y += rect.size().height() - h; + if ((alignment & Qt::AlignRight) == Qt::AlignRight) + x += rect.size().width() - w; + else if ((alignment & Qt::AlignHCenter) == Qt::AlignHCenter) + x += rect.size().width()/2 - w/2; + + QRect aligned = QRect(x, y, w, h); + QRect inter = aligned.intersected(rect); + + painter->drawPixmap(inter.x(), inter.y(), pixmap, inter.x() - aligned.x(), inter.y() - aligned.y(), inter.width() * scale, inter.height() *scale); +} + + +void QWasmCompositor::drawTitlebarWindow(QWasmTitleBarOptions tb, QPainter *painter) +{ + QRect ir; + if (tb.subControls.testFlag(SC_TitleBarLabel)) { + QColor left = tb.palette.highlight().color(); + QColor right = tb.palette.base().color(); + + QBrush fillBrush(left); + if (left != right) { + QPoint p1(tb.rect.x(), tb.rect.top() + tb.rect.height()/2); + QPoint p2(tb.rect.right(), tb.rect.top() + tb.rect.height()/2); + QLinearGradient lg(p1, p2); + lg.setColorAt(0, left); + lg.setColorAt(1, right); + fillBrush = lg; + } + + painter->fillRect(tb.rect, fillBrush); + ir = titlebarRect(tb, SC_TitleBarLabel); + painter->setPen(tb.palette.highlightedText().color()); + painter->drawText(ir.x() + 2, ir.y(), ir.width() - 2, ir.height(), + Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, tb.titleBarOptionsString); + } // SC_TitleBarLabel + + bool down = false; + QPixmap pixmap; + + if (tb.subControls.testFlag(SC_TitleBarCloseButton) + && tb.flags & Qt::WindowSystemMenuHint) { + ir = titlebarRect(tb, SC_TitleBarCloseButton); + down = tb.subControls & SC_TitleBarCloseButton && (tb.state & State_Sunken); + pixmap = cachedPixmapFromXPM(qt_close_xpm).scaled(QSize(10, 10)); + drawItemPixmap(painter, ir, Qt::AlignCenter, pixmap); + } //SC_TitleBarCloseButton + + if (tb.subControls.testFlag(SC_TitleBarMaxButton) + && tb.flags & Qt::WindowMaximizeButtonHint + && !(tb.state & Qt::WindowMaximized)) { + ir = titlebarRect(tb, SC_TitleBarMaxButton); + down = tb.subControls & SC_TitleBarMaxButton && (tb.state & State_Sunken); + pixmap = cachedPixmapFromXPM(qt_maximize_xpm).scaled(QSize(10, 10)); + drawItemPixmap(painter, ir, Qt::AlignCenter, pixmap); + } //SC_TitleBarMaxButton + + bool drawNormalButton = (tb.subControls & SC_TitleBarNormalButton) + && (((tb.flags & Qt::WindowMinimizeButtonHint) + && (tb.flags & Qt::WindowMinimized)) + || ((tb.flags & Qt::WindowMaximizeButtonHint) + && (tb.flags & Qt::WindowMaximized))); + + if (drawNormalButton) { + ir = titlebarRect(tb, SC_TitleBarNormalButton); + down = tb.subControls & SC_TitleBarNormalButton && (tb.state & State_Sunken); + pixmap = cachedPixmapFromXPM(qt_normalizeup_xpm).scaled( QSize(10, 10)); + + drawItemPixmap(painter, ir, Qt::AlignCenter, pixmap); + } // SC_TitleBarNormalButton + + if (tb.subControls & SC_TitleBarSysMenu && tb.flags & Qt::WindowSystemMenuHint) { + ir = titlebarRect(tb, SC_TitleBarSysMenu); + pixmap = cachedPixmapFromXPM(qt_menu_xpm).scaled(QSize(10, 10)); + drawItemPixmap(painter, ir, Qt::AlignCenter, pixmap); + } +} + +void QWasmCompositor::drawShadePanel(QWasmTitleBarOptions options, QPainter *painter) +{ + int lineWidth = 1; + QPalette palette = options.palette; + const QBrush *fill = &options.palette.brush(QPalette::Button); + + int x = options.rect.x(); + int y = options.rect.y(); + int w = options.rect.width(); + int h = options.rect.height(); + + const qreal devicePixelRatio = painter->device()->devicePixelRatioF(); + if (!qFuzzyCompare(devicePixelRatio, qreal(1))) { + const qreal inverseScale = qreal(1) / devicePixelRatio; + painter->scale(inverseScale, inverseScale); + + x = qRound(devicePixelRatio * x); + y = qRound(devicePixelRatio * y); + w = qRound(devicePixelRatio * w); + h = qRound(devicePixelRatio * h); + lineWidth = qRound(devicePixelRatio * lineWidth); + } + + QColor shade = palette.dark().color(); + QColor light = palette.light().color(); + + if (fill) { + if (fill->color() == shade) + shade = palette.shadow().color(); + if (fill->color() == light) + light = palette.midlight().color(); + } + QPen oldPen = painter->pen(); + QVector lines; + lines.reserve(2*lineWidth); + + painter->setPen(light); + int x1, y1, x2, y2; + int i; + x1 = x; + y1 = y2 = y; + x2 = x + w - 2; + for (i = 0; i < lineWidth; i++) // top shadow + lines << QLineF(x1, y1++, x2--, y2++); + + x2 = x1; + y1 = y + h - 2; + for (i = 0; i < lineWidth; i++) // left shado + lines << QLineF(x1++, y1, x2++, y2--); + + painter->drawLines(lines); + lines.clear(); + painter->setPen(shade); + x1 = x; + y1 = y2 = y+h-1; + x2 = x+w-1; + for (i=0; idrawLines(lines); + if (fill) // fill with fill color + painter->fillRect(x+lineWidth, y+lineWidth, w-lineWidth*2, h-lineWidth*2, *fill); + painter->setPen(oldPen); // restore pen + +} + +void QWasmCompositor::drawWindow(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window) +{ + if (window->window()->type() != Qt::Popup) + drawWindowDecorations(blitter, screen, window); + drawWindowContent(blitter, screen, window); +} + +void QWasmCompositor::frame() +{ + if (!m_needComposit) + return; + + m_needComposit = false; + + if (m_windowStack.empty() || !m_screen) + return; + + QWasmWindow *someWindow = nullptr; + + foreach (QWasmWindow *window, m_windowStack) { + if (window->window()->surfaceClass() == QSurface::Window + && qt_window_private(static_cast(window->window()))->receivedExpose) { + someWindow = window; + break; + } + } + + if (!someWindow) + return; + + if (m_context.isNull()) { + m_context.reset(new QOpenGLContext()); + //mContext->setFormat(mScreen->format()); + m_context->setScreen(m_screen->screen()); + m_context->create(); + } + + m_context->makeCurrent(someWindow->window()); + + if (!m_blitter->isCreated()) + m_blitter->create(); + + qreal dpr = m_screen->devicePixelRatio(); + glViewport(0, 0, m_screen->geometry().width() * dpr, m_screen->geometry().height() * dpr); + + m_context->functions()->glClearColor(0.2, 0.2, 0.2, 1.0); + m_context->functions()->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + + m_blitter->bind(); + m_blitter->setRedBlueSwizzle(true); + + foreach (QWasmWindow *window, m_windowStack) { + QWasmCompositedWindow &compositedWindow = m_compositedWindows[window]; + + if (!compositedWindow.visible) + continue; + + drawWindow(m_blitter.data(), m_screen, window); + } + + m_blitter->release(); + + if (someWindow && someWindow->window()->surfaceType() == QSurface::OpenGLSurface) + m_context->swapBuffers(someWindow->window()); +} + +void QWasmCompositor::notifyTopWindowChanged(QWasmWindow *window) +{ + QWindow *modalWindow; + bool blocked = QGuiApplicationPrivate::instance()->isWindowBlocked(window->window(), &modalWindow); + + if (blocked) { + raise(static_cast(modalWindow->handle())); + return; + } + + requestRedraw(); + QWindowSystemInterface::handleWindowActivated(window->window()); +} diff --git a/src/plugins/platforms/wasm/qwasmcompositor.h b/src/plugins/platforms/wasm/qwasmcompositor.h new file mode 100644 index 00000000000..4e5ed46cec5 --- /dev/null +++ b/src/plugins/platforms/wasm/qwasmcompositor.h @@ -0,0 +1,169 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) 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.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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWASMCOMPOSITOR_H +#define QWASMCOMPOSITOR_H + +#include +#include + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QWasmWindow; +class QWasmScreen; +class QOpenGLContext; +class QOpenGLTextureBlitter; + +class QWasmCompositedWindow +{ +public: + QWasmCompositedWindow(); + + QWasmWindow *window; + QWasmWindow *parentWindow; + QRegion damage; + bool flushPending; + bool visible; + QList childWindows; +}; + +class QWasmCompositor : public QObject +{ + Q_OBJECT +public: + QWasmCompositor(); + ~QWasmCompositor(); + + enum QWasmSubControl { + SC_None = 0x00000000, + SC_TitleBarSysMenu = 0x00000001, + SC_TitleBarMinButton = 0x00000002, + SC_TitleBarMaxButton = 0x00000004, + SC_TitleBarCloseButton = 0x00000008, + SC_TitleBarNormalButton = 0x00000010, + SC_TitleBarLabel = 0x00000100 + }; + Q_DECLARE_FLAGS(SubControls, QWasmSubControl) + + enum QWasmStateFlag { + State_None = 0x00000000, + State_Enabled = 0x00000001, + State_Raised = 0x00000002, + State_Sunken = 0x00000004 + }; + Q_DECLARE_FLAGS(StateFlags, QWasmStateFlag) + + struct QWasmTitleBarOptions { + QRect rect; + Qt::WindowFlags flags; + int state; + QPalette palette; + QString titleBarOptionsString; + QWasmCompositor::SubControls subControls; + }; + + struct QWasmFrameOptions { + QRect rect; + int lineWidth; + QPalette palette; + }; + + void setEnabled(bool enabled); + + void addWindow(QWasmWindow *window, QWasmWindow *parentWindow = nullptr); + void removeWindow(QWasmWindow *window); + void setScreen(QWasmScreen *screen); + + void setVisible(QWasmWindow *window, bool visible); + void raise(QWasmWindow *window); + void lower(QWasmWindow *window); + void setParent(QWasmWindow *window, QWasmWindow *parent); + + void flush(QWasmWindow *surface, const QRegion ®ion); + + int windowCount() const; + + void redrawWindowContent(); + void requestRedraw(); + + QWindow *windowAt(QPoint p, int padding = 0) const; + QWindow *keyWindow() const; + + bool event(QEvent *event); + + static QWasmTitleBarOptions makeTitleBarOptions(const QWasmWindow *window); + static QRect titlebarRect(QWasmTitleBarOptions tb, QWasmCompositor::SubControls subcontrol); + +private slots: + void frame(); + +private: + void createFrameBuffer(); + void flushCompletedCallback(int32_t); + void notifyTopWindowChanged(QWasmWindow *window); + void drawWindow(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window); + void drawWindowContent(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window); + void blit(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, const QOpenGLTexture *texture, QRect targetGeometry); + + void drawWindowDecorations(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window); + void drwPanelButton(); + + QImage *m_frameBuffer; + QScopedPointer m_context; + QScopedPointer m_blitter; + QWasmScreen *m_screen; + + QHash m_compositedWindows; + QList m_windowStack; + QRegion m_globalDamage; // damage caused by expose, window close, etc. + bool m_needComposit; + bool m_inFlush; + bool m_inResize; + bool m_isEnabled; + QSize m_targetSize; + qreal m_targetDevicePixelRatio; + + static QPalette makeWindowPalette(); + + void drawFrameWindow(QWasmFrameOptions options, QPainter *painter); + void drawTitlebarWindow(QWasmTitleBarOptions options, QPainter *painter); + void drawShadePanel(QWasmTitleBarOptions options, QPainter *painter); + void drawItemPixmap(QPainter *painter, const QRect &rect, + int alignment, const QPixmap &pixmap) const; +}; +Q_DECLARE_OPERATORS_FOR_FLAGS(QWasmCompositor::SubControls) + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/wasm/qwasmcursor.cpp b/src/plugins/platforms/wasm/qwasmcursor.cpp new file mode 100644 index 00000000000..54804a55b34 --- /dev/null +++ b/src/plugins/platforms/wasm/qwasmcursor.cpp @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) 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.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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwasmcursor.h" + +#include + +#include + +void QWasmCursor::changeCursor(QCursor *windowCursor, QWindow *window) +{ + if (windowCursor == nullptr) + return; + + // FIXME: The HTML5 plugin sets the cursor on the native canvas; when using multiple windows + // multiple cursors need to be managed taking mouse postion and stacking into account. + Q_UNUSED(window); + + // Bitmap and custom cursors are not implemented (will fall back to "auto") + if (windowCursor->shape() == Qt::BitmapCursor || windowCursor->shape() >= Qt::CustomCursor) + qWarning() << "QWasmCursor: bitmap and custom cursors are not supported"; + + QByteArray htmlCursorName = cursorShapeToHtml(windowCursor->shape()); + + if (htmlCursorName.isEmpty()) + htmlCursorName = "auto"; + + // Set cursor on the main canvas + EM_ASM_ARGS({ + if (Module['canvas']) { + Module['canvas'].style['cursor'] = Pointer_stringify($0); + } + }, htmlCursorName.constData()); +} + +QByteArray QWasmCursor::cursorShapeToHtml(Qt::CursorShape shape) +{ + QByteArray cursorName; + + switch (shape) { + case Qt::ArrowCursor: + cursorName = "default"; + break; + case Qt::UpArrowCursor: + break; + case Qt::CrossCursor: + cursorName = "crosshair"; + break; + case Qt::WaitCursor: + cursorName = "wait"; + break; + case Qt::IBeamCursor: + cursorName = "text"; + break; + case Qt::SizeVerCursor: + cursorName = "ns-resize"; + break; + case Qt::SizeHorCursor: + cursorName = "ew-resize"; + break; + case Qt::SizeBDiagCursor: + cursorName = "nesw-resize"; + break; + case Qt::SizeFDiagCursor: + cursorName = "nwse-resize"; + break; + case Qt::SizeAllCursor: + break; // no equivalent? + case Qt::BlankCursor: + cursorName = "none"; + break; + case Qt::SplitVCursor: + cursorName = "row-resize"; + break; + case Qt::SplitHCursor: + cursorName = "col-resize"; + break; + case Qt::PointingHandCursor: + cursorName = "pointer"; + break; + case Qt::ForbiddenCursor: + cursorName = "not-allowed"; + break; + case Qt::WhatsThisCursor: + cursorName = "help"; + break; + case Qt::BusyCursor: + cursorName = "wait"; + break; + case Qt::OpenHandCursor: + break; // no equivalent? + case Qt::ClosedHandCursor: + break; // no equivalent? + case Qt::DragCopyCursor: + break; // no equivalent? + case Qt::DragMoveCursor: + break; // no equivalent? + case Qt::DragLinkCursor: + break; // no equivalent? + default: + break; + } + + return cursorName; +} diff --git a/src/plugins/platforms/wasm/qwasmcursor.h b/src/plugins/platforms/wasm/qwasmcursor.h new file mode 100644 index 00000000000..516e07aa311 --- /dev/null +++ b/src/plugins/platforms/wasm/qwasmcursor.h @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) 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.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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWASMCURSOR_H +#define QWASMCURSOR_H + +#include + +class QWasmCursor : public QPlatformCursor +{ +public: + void changeCursor(QCursor *windowCursor, QWindow *window) override; + + QByteArray cursorShapeToHtml(Qt::CursorShape shape); +}; + +#endif diff --git a/src/plugins/platforms/wasm/qwasmeventdispatcher.cpp b/src/plugins/platforms/wasm/qwasmeventdispatcher.cpp new file mode 100644 index 00000000000..41355d72aef --- /dev/null +++ b/src/plugins/platforms/wasm/qwasmeventdispatcher.cpp @@ -0,0 +1,181 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) 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.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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwasmeventdispatcher.h" + +#include + +#include + +class QWasmEventDispatcherPrivate : public QEventDispatcherUNIXPrivate +{ + +}; + +QWasmEventDispatcher *g_htmlEventDispatcher; + +QWasmEventDispatcher::QWasmEventDispatcher(QObject *parent) + : QUnixEventDispatcherQPA(parent) +{ + + g_htmlEventDispatcher = this; +} + +QWasmEventDispatcher::~QWasmEventDispatcher() +{ + g_htmlEventDispatcher = nullptr; +} + +bool QWasmEventDispatcher::registerRequestUpdateCallback(std::function callback) +{ + if (!g_htmlEventDispatcher || !g_htmlEventDispatcher->m_hasMainLoop) + return false; + + g_htmlEventDispatcher->m_requestUpdateCallbacks.append(callback); + emscripten_resume_main_loop(); + return true; +} + +void QWasmEventDispatcher::maintainTimers() +{ + if (!g_htmlEventDispatcher || !g_htmlEventDispatcher->m_hasMainLoop) + return; + + g_htmlEventDispatcher->doMaintainTimers(); +} + +bool QWasmEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) +{ + // WaitForMoreEvents is not supported (except for in combination with EventLoopExec below), + // and we don't want the unix event dispatcher base class to attempt to wait either. + flags &= ~QEventLoop::WaitForMoreEvents; + + // Handle normal processEvents. + if (!(flags & QEventLoop::EventLoopExec)) + return QUnixEventDispatcherQPA::processEvents(flags); + + // Handle processEvents from QEventLoop::exec(): + // + // At this point the application has created its root objects on + // the stack and has called app.exec() which has called into this + // function via QEventLoop. + // + // The application now expects that exec() will not return until + // app exit time. However, the browser expects that we return + // control to it periodically, also after initial setup in main(). + + // EventLoopExec for nested event loops is not supported. + Q_ASSERT(!m_hasMainLoop); + m_hasMainLoop = true; + + // Call emscripten_set_main_loop_arg() with a callback which processes + // events. Also set simulateInfiniteLoop to true which makes emscripten + // return control to the browser without unwinding the C++ stack. + auto callback = [](void *eventDispatcher) { + QWasmEventDispatcher *that = static_cast(eventDispatcher); + + // Save and clear updateRequest callbacks so we can register new ones + auto requestUpdateCallbacksCopy = that->m_requestUpdateCallbacks; + that->m_requestUpdateCallbacks.clear(); + + // Repaint all windows + for (auto callback : qAsConst(requestUpdateCallbacksCopy)) + callback(); + + // Pause main loop if no updates were requested. Updates will be + // restarted again by registerRequestUpdateCallback(). + if (that->m_requestUpdateCallbacks.isEmpty()) + emscripten_pause_main_loop(); + + that->doMaintainTimers(); + }; + int fps = 0; // update using requestAnimationFrame + int simulateInfiniteLoop = 1; + emscripten_set_main_loop_arg(callback, this, fps, simulateInfiniteLoop); + + // Note: the above call never returns, not even at app exit + return false; +} + +void QWasmEventDispatcher::doMaintainTimers() +{ + Q_D(QWasmEventDispatcher); + + // This functon schedules native timers in order to wake up to + // process events and activate Qt timers. This is done using the + // emscripten_async_call() API which schedules a new timer. + // There is unfortunately no way to cancel or update a current + // native timer. + + // Schedule a zero-timer to continue processing any pending events. + if (!m_hasZeroTimer && hasPendingEvents()) { + auto callback = [](void *eventDispatcher) { + QWasmEventDispatcher *that = static_cast(eventDispatcher); + that->m_hasZeroTimer = false; + that->QUnixEventDispatcherQPA::processEvents(QEventLoop::AllEvents); + + // Processing events may have posted new events or created new timers + that->doMaintainTimers(); + }; + + emscripten_async_call(callback, this, 0); + m_hasZeroTimer = true; + return; + } + + auto timespecToNanosec = [](timespec ts) -> uint64_t { return ts.tv_sec * 1000 + ts.tv_nsec / (1000 * 1000); }; + + // Get current time and time-to-first-Qt-timer. This polls for system + // time, and we use this time as the current time for the duration of this call. + timespec toWait; + bool hasTimers = d->timerList.timerWait(toWait); + if (!hasTimers) + return; // no timer needed + + uint64_t currentTime = timespecToNanosec(d->timerList.currentTime); + uint64_t toWaitDuration = timespecToNanosec(toWait); + + // The currently scheduled timer target is stored in m_currentTargetTime. + // We can re-use it if the new target is equivalent or later. + uint64_t newTargetTime = currentTime + toWaitDuration; + if (newTargetTime >= m_currentTargetTime) + return; // existing timer is good + + // Schedule a native timer with a callback which processes events (and timers) + auto callback = [](void *eventDispatcher) { + QWasmEventDispatcher *that = static_cast(eventDispatcher); + that->m_currentTargetTime = std::numeric_limits::max(); + that->QUnixEventDispatcherQPA::processEvents(QEventLoop::AllEvents); + + // Processing events may have posted new events or created new timers + that->doMaintainTimers(); + }; + emscripten_async_call(callback, this, toWaitDuration); + m_currentTargetTime = newTargetTime; +} diff --git a/src/plugins/platforms/wasm/qwasmeventdispatcher.h b/src/plugins/platforms/wasm/qwasmeventdispatcher.h new file mode 100644 index 00000000000..5300b3de73a --- /dev/null +++ b/src/plugins/platforms/wasm/qwasmeventdispatcher.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) 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.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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWASMEVENTDISPATCHER_H +#define QWASMEVENTDISPATCHER_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QWasmEventDispatcherPrivate; + +class QWasmEventDispatcher : public QUnixEventDispatcherQPA +{ + Q_DECLARE_PRIVATE(QWasmEventDispatcher) +public: + explicit QWasmEventDispatcher(QObject *parent = nullptr); + ~QWasmEventDispatcher(); + + static bool registerRequestUpdateCallback(std::function callback); + static void maintainTimers(); + +protected: + bool processEvents(QEventLoop::ProcessEventsFlags flags) override; + void doMaintainTimers(); + +private: + bool m_hasMainLoop = false; + bool m_hasZeroTimer = false; + uint64_t m_currentTargetTime = std::numeric_limits::max(); + QVector> m_requestUpdateCallbacks; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp new file mode 100644 index 00000000000..6545eda4e35 --- /dev/null +++ b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp @@ -0,0 +1,522 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) 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.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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwasmeventtranslator.h" +#include "qwasmeventdispatcher.h" +#include "qwasmcompositor.h" +#include "qwasmintegration.h" + +#include +#include +#include +#include +#include + +#include + +#include + +QT_BEGIN_NAMESPACE + +// macOS CTRL <-> META switching. We most likely want to enable +// the existing switching code in QtGui, but for now do it here. +static bool g_usePlatformMacCtrlMetaSwitching = false; + +QWasmEventTranslator::QWasmEventTranslator(QObject *parent) + : QObject(parent) + , draggedWindow(nullptr) + , pressedButtons(Qt::NoButton) + , resizeMode(QWasmWindow::ResizeNone) +{ + emscripten_set_keydown_callback(0, (void *)this, 1, &keyboard_cb); + emscripten_set_keyup_callback(0, (void *)this, 1, &keyboard_cb); + + emscripten_set_mousedown_callback(0, (void *)this, 1, &mouse_cb); + emscripten_set_mouseup_callback(0, (void *)this, 1, &mouse_cb); + emscripten_set_mousemove_callback(0, (void *)this, 1, &mouse_cb); + + emscripten_set_focus_callback(0, (void *)this, 1, &focus_cb); + + emscripten_set_wheel_callback(0, (void *)this, 1, &wheel_cb); + + touchDevice = new QTouchDevice; + touchDevice->setType(QTouchDevice::TouchScreen); + touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::NormalizedPosition); + QWindowSystemInterface::registerTouchDevice(touchDevice); + + emscripten_set_touchstart_callback("#canvas", (void *)this, 1, &touchCallback); + emscripten_set_touchend_callback("#canvas", (void *)this, 1, &touchCallback); + emscripten_set_touchmove_callback("#canvas", (void *)this, 1, &touchCallback); + emscripten_set_touchcancel_callback("#canvas", (void *)this, 1, &touchCallback); + + // The Platform Detect: expand coverage and move as needed + enum Platform { + GenericPlatform, + MacOSPlatform + }; + Platform platform = + Platform(EM_ASM_INT("if (navigator.platform.includes(\"Mac\")) return 1; return 0;")); + + g_usePlatformMacCtrlMetaSwitching = (platform == MacOSPlatform); +} + +template +QFlags QWasmEventTranslator::translatKeyModifier(const Event *event) +{ + QFlags keyModifier = Qt::NoModifier; + if (event->shiftKey) + keyModifier |= Qt::ShiftModifier; + if (event->ctrlKey) { + if (g_usePlatformMacCtrlMetaSwitching) + keyModifier |= Qt::MetaModifier; + else + keyModifier |= Qt::ControlModifier; + } + if (event->altKey) + keyModifier |= Qt::AltModifier; + if (event->metaKey) { + if (g_usePlatformMacCtrlMetaSwitching) + keyModifier |= Qt::ControlModifier; + else + keyModifier |= Qt::MetaModifier; + } + return keyModifier; +} + +QFlags QWasmEventTranslator::translateKeyboardEventModifier(const EmscriptenKeyboardEvent *keyEvent) +{ + QFlags keyModifier = translatKeyModifier(keyEvent); + if (keyEvent->location == DOM_KEY_LOCATION_NUMPAD) { + keyModifier |= Qt::KeypadModifier; + } + + return keyModifier; +} + +QFlags QWasmEventTranslator::translateMouseEventModifier(const EmscriptenMouseEvent *mouseEvent) +{ + return translatKeyModifier(mouseEvent); +} + +int QWasmEventTranslator::keyboard_cb(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData) +{ + Q_UNUSED(userData) + + bool alphanumeric; + Qt::Key qtKey = translateEmscriptKey(keyEvent, &alphanumeric); + + QEvent::Type keyType = QEvent::None; + switch (eventType) { + case EMSCRIPTEN_EVENT_KEYPRESS: + case EMSCRIPTEN_EVENT_KEYDOWN: //down + keyType = QEvent::KeyPress; + break; + case EMSCRIPTEN_EVENT_KEYUP: //up + keyType = QEvent::KeyRelease; + break; + default: + break; + }; + + if (keyType == QEvent::None) + return 0; + + QString keyText = alphanumeric ? QString(keyEvent->key) : QString(); + bool accepted = QWindowSystemInterface::handleKeyEvent( + 0, keyType, qtKey, translateKeyboardEventModifier(keyEvent), keyText); + QWasmEventDispatcher::maintainTimers(); + return accepted ? 1 : 0; +} + +Qt::Key QWasmEventTranslator::translateEmscriptKey(const EmscriptenKeyboardEvent *emscriptKey, bool *outAlphanumeric) +{ + Qt::Key qtKey; + if (outAlphanumeric) + *outAlphanumeric = false; + + switch (emscriptKey->keyCode) { + case KeyMultiply: qtKey = Qt::Key_Asterisk; *outAlphanumeric = true; break; + case KeyAdd: qtKey = Qt::Key_Plus; *outAlphanumeric = true; break; + case KeyMinus: qtKey = Qt::Key_Minus; *outAlphanumeric = true; break; + case KeySubtract: qtKey = Qt::Key_Minus; *outAlphanumeric = true; break; + case KeyDecimal: qtKey = Qt::Key_Period; *outAlphanumeric = true; break; + case KeyDivide: qtKey = Qt::Key_Slash; *outAlphanumeric = true; break; + case KeyNumPad0: qtKey = Qt::Key_0; *outAlphanumeric = true; break; + case KeyNumPad1: qtKey = Qt::Key_1; *outAlphanumeric = true; break; + case KeyNumPad2: qtKey = Qt::Key_2; *outAlphanumeric = true; break; + case KeyNumPad3: qtKey = Qt::Key_3; *outAlphanumeric = true; break; + case KeyNumPad4: qtKey = Qt::Key_4; *outAlphanumeric = true; break; + case KeyNumPad5: qtKey = Qt::Key_5; *outAlphanumeric = true; break; + case KeyNumPad6: qtKey = Qt::Key_6; *outAlphanumeric = true; break; + case KeyNumPad7: qtKey = Qt::Key_7; *outAlphanumeric = true; break; + case KeyNumPad8: qtKey = Qt::Key_8; *outAlphanumeric = true; break; + case KeyNumPad9: qtKey = Qt::Key_9; *outAlphanumeric = true; break; + case KeyComma: qtKey = Qt::Key_Comma; *outAlphanumeric = true; break; + case KeyPeriod: qtKey = Qt::Key_Period; *outAlphanumeric = true; break; + case KeySlash: qtKey = Qt::Key_Slash; *outAlphanumeric = true; break; + case KeySemiColon: qtKey = Qt::Key_Semicolon; *outAlphanumeric = true; break; + case KeyEquals: qtKey = Qt::Key_Equal; *outAlphanumeric = true; break; + case KeyOpenBracket: qtKey = Qt::Key_BracketLeft; *outAlphanumeric = true; break; + case KeyCloseBracket: qtKey = Qt::Key_BracketRight; *outAlphanumeric = true; break; + case KeyBackSlash: qtKey = Qt::Key_Backslash; *outAlphanumeric = true; break; + case KeyMeta: + Q_FALLTHROUGH(); + case KeyMetaRight: + qtKey = Qt::Key_Meta; + break; + case KeyTab: qtKey = Qt::Key_Tab; break; + case KeyClear: qtKey = Qt::Key_Clear; break; + case KeyBackSpace: qtKey = Qt::Key_Backspace; break; + case KeyEnter: qtKey = Qt::Key_Return; break; + case KeyShift: qtKey = Qt::Key_Shift; break; + case KeyControl: qtKey = Qt::Key_Control; break; + case KeyAlt: qtKey = Qt::Key_Alt; break; + case KeyCapsLock: qtKey = Qt::Key_CapsLock; break; + case KeyEscape: qtKey = Qt::Key_Escape; break; + case KeyPageUp: qtKey = Qt::Key_PageUp; break; + case KeyPageDown: qtKey = Qt::Key_PageDown; break; + case KeyEnd: qtKey = Qt::Key_End; break; + case KeyHome: qtKey = Qt::Key_Home; break; + case KeyLeft: qtKey = Qt::Key_Left; break; + case KeyUp: qtKey = Qt::Key_Up; break; + case KeyRight: qtKey = Qt::Key_Right; break; + case KeyDown: qtKey = Qt::Key_Down; break; + case KeyBrightnessDown: qtKey = Qt::Key_MonBrightnessDown; break; + case KeyBrightnessUp: qtKey = Qt::Key_MonBrightnessUp; break; + case KeyMediaTrackPrevious: qtKey = Qt::Key_MediaPrevious; break; + case KeyMediaPlayPause: qtKey = Qt::Key_MediaTogglePlayPause; break; + case KeyMediaTrackNext: qtKey = Qt::Key_MediaNext; break; + case KeyAudioVolumeMute: qtKey = Qt::Key_VolumeMute; break; + case KeyAudioVolumeDown: qtKey = Qt::Key_VolumeDown; break; + case KeyAudioVolumeUp: qtKey = Qt::Key_VolumeUp; break; + case KeyDelete: qtKey = Qt::Key_Delete; break; + + case KeyF1: qtKey = Qt::Key_F1; break; + case KeyF2: qtKey = Qt::Key_F2; break; + case KeyF3: qtKey = Qt::Key_F3; break; + case KeyF4: qtKey = Qt::Key_F4; break; + case KeyF5: qtKey = Qt::Key_F5; break; + case KeyF6: qtKey = Qt::Key_F6; break; + case KeyF7: qtKey = Qt::Key_F7; break; + case KeyF8: qtKey = Qt::Key_F8; break; + case KeyF9: qtKey = Qt::Key_F9; break; + case KeyF10: qtKey = Qt::Key_F10; break; + case KeyF11: qtKey = Qt::Key_F11; break; + case KeyF12: qtKey = Qt::Key_F12; break; + case 124: qtKey = Qt::Key_F13; break; + case 125: qtKey = Qt::Key_F14; break; + + case KeySpace: + default: + if (outAlphanumeric) + *outAlphanumeric = true; + qtKey = static_cast(emscriptKey->keyCode); + break; + } + + // Handle Mac command key. Using event->keyCode as above is + // no reliable since the codes differ between browsers. + if (qstrncmp(emscriptKey->key, "Meta", 4) == 0) { + qtKey = Qt::Key_Meta; + *outAlphanumeric = false; + } + + if (g_usePlatformMacCtrlMetaSwitching) { + if (qtKey == Qt::Key_Meta) + qtKey = Qt::Key_Control; + else if (qtKey == Qt::Key_Control) + qtKey = Qt::Key_Meta; + } + + return qtKey; +} + +Qt::MouseButton QWasmEventTranslator::translateMouseButton(unsigned short button) +{ + if (button == 0) + return Qt::LeftButton; + else if (button == 1) + return Qt::MiddleButton; + else if (button == 2) + return Qt::RightButton; + + return Qt::NoButton; +} + +int QWasmEventTranslator::mouse_cb(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData) +{ + QWasmEventTranslator *translator = (QWasmEventTranslator*)userData; + translator->processMouse(eventType,mouseEvent); + QWasmEventDispatcher::maintainTimers(); + return 0; +} + +void resizeWindow(QWindow *window, QWasmWindow::ResizeMode mode, + QRect startRect, QPoint amount) +{ + if (mode == QWasmWindow::ResizeNone) + return; + + bool top = mode == QWasmWindow::ResizeTopLeft || + mode == QWasmWindow::ResizeTop || + mode == QWasmWindow::ResizeTopRight; + + bool bottom = mode == QWasmWindow::ResizeBottomLeft || + mode == QWasmWindow::ResizeBottom || + mode == QWasmWindow::ResizeBottomRight; + + bool left = mode == QWasmWindow::ResizeLeft || + mode == QWasmWindow::ResizeTopLeft || + mode == QWasmWindow::ResizeBottomLeft; + + bool right = mode == QWasmWindow::ResizeRight || + mode == QWasmWindow::ResizeTopRight || + mode == QWasmWindow::ResizeBottomRight; + + int x1 = startRect.left(); + int y1 = startRect.top(); + int x2 = startRect.right(); + int y2 = startRect.bottom(); + + if (left) + x1 += amount.x(); + if (top) + y1 += amount.y(); + if (right) + x2 += amount.x(); + if (bottom) + y2 += amount.y(); + + int w = x2-x1; + int h = y2-y1; + + if (w < window->minimumWidth()) { + if (left) + x1 -= window->minimumWidth() - w; + + w = window->minimumWidth(); + } + + if (h < window->minimumHeight()) { + if (top) + y1 -= window->minimumHeight() - h; + + h = window->minimumHeight(); + } + + window->setGeometry(x1, y1, w, h); +} + +void QWasmEventTranslator::processMouse(int eventType, const EmscriptenMouseEvent *mouseEvent) +{ + auto timestamp = mouseEvent->timestamp; + QPoint point(mouseEvent->canvasX, mouseEvent->canvasY); + + QEvent::Type buttonEventType = QEvent::None; + + Qt::MouseButton button = translateMouseButton(mouseEvent->button); + Qt::KeyboardModifiers modifiers = translateMouseEventModifier(mouseEvent); + + QWindow *window2 = QWasmIntegration::get()->compositor()->windowAt(point, 5); + QWasmWindow *htmlWindow = static_cast(window2->handle()); + bool onFrame = false; + if (window2 && !window2->geometry().contains(point)) + onFrame = true; + + QPoint localPoint(point.x() - window2->geometry().x(), point.y() - window2->geometry().y()); + + switch (eventType) { + case 5: //down + { + if (window2) + window2->raise(); + + pressedButtons.setFlag(button); + + if (mouseEvent->button == 0) { + pressedWindow = window2; + buttonEventType = QEvent::MouseButtonPress; + if (htmlWindow && window2->flags().testFlag(Qt::WindowTitleHint) && htmlWindow->isPointOnTitle(point)) + draggedWindow = window2; + else if (htmlWindow && htmlWindow->isPointOnResizeRegion(point)) { + draggedWindow = window2; + resizeMode = htmlWindow->resizeModeAtPoint(point); + resizePoint = point; + resizeStartRect = window2->geometry(); + } + } + + htmlWindow->injectMousePressed(localPoint, point, button, modifiers); + break; + } + case 6: //up + { + pressedButtons.setFlag(translateMouseButton(mouseEvent->button), false); + buttonEventType = QEvent::MouseButtonRelease; + QWasmWindow *oldWindow = nullptr; + + if (mouseEvent->button == 0 && pressedWindow) { + oldWindow = static_cast(pressedWindow->handle()); + pressedWindow = nullptr; + } + + + if (mouseEvent->button == 0) { + draggedWindow = nullptr; + resizeMode = QWasmWindow::ResizeNone; + } + + if (oldWindow) + oldWindow->injectMouseReleased(localPoint, point, button, modifiers); + break; + } + case 8://move //drag event + { + buttonEventType = QEvent::MouseMove; + if (resizeMode == QWasmWindow::ResizeNone && draggedWindow) { + draggedWindow->setX(draggedWindow->x() + mouseEvent->movementX); + draggedWindow->setY(draggedWindow->y() + mouseEvent->movementY); + } + + if (resizeMode != QWasmWindow::ResizeNone) { + QPoint delta = QPoint(mouseEvent->canvasX, mouseEvent->canvasY) - resizePoint; + resizeWindow(draggedWindow, resizeMode, resizeStartRect, delta); + } + break; + } + default: + break; + }; + + if (window2 && !onFrame) { + QWindowSystemInterface::handleMouseEvent( + window2, timestamp, localPoint, point, pressedButtons, button, buttonEventType, modifiers); + } +} + +int QWasmEventTranslator::focus_cb(int /*eventType*/, const EmscriptenFocusEvent */*focusEvent*/, void */*userData*/) +{ + return 0; +} + +int QWasmEventTranslator::wheel_cb(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData) +{ + Q_UNUSED(eventType) + Q_UNUSED(userData) + + EmscriptenMouseEvent mouseEvent = wheelEvent->mouse; + + int scrollFactor = 0; + switch (wheelEvent->deltaMode) { + case DOM_DELTA_PIXEL://chrome safari + scrollFactor = 1; + break; + case DOM_DELTA_LINE: //firefox + scrollFactor = 12; + break; + case DOM_DELTA_PAGE: + scrollFactor = 20; + break; + }; + + Qt::KeyboardModifiers modifiers = translateMouseEventModifier(&mouseEvent); + auto timestamp = mouseEvent.timestamp; + QPoint globalPoint(mouseEvent.canvasX, mouseEvent.canvasY); + + QWindow *window2 = QWasmIntegration::get()->compositor()->windowAt(globalPoint, 5); + + QPoint localPoint(globalPoint.x() - window2->geometry().x(), globalPoint.y() - window2->geometry().y()); + + QPoint pixelDelta; + + if (wheelEvent->deltaY != 0) pixelDelta.setY(wheelEvent->deltaY * scrollFactor); + if (wheelEvent->deltaX != 0) pixelDelta.setX(wheelEvent->deltaX * scrollFactor); + + QWindowSystemInterface::handleWheelEvent(window2, timestamp, localPoint, globalPoint, QPoint(), pixelDelta, modifiers); + return 1; +} + +int QWasmEventTranslator::touchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData) +{ + QList touchPointList; + touchPointList.reserve(touchEvent->numTouches); + QWindow *window2; + + for (int i = 0; i < touchEvent->numTouches; i++) { + + const EmscriptenTouchPoint *touches = &touchEvent->touches[i]; + + QPoint point(touches->canvasX, touches->canvasY); + window2 = QWasmIntegration::get()->compositor()->windowAt(point, 5); + + QWindowSystemInterface::TouchPoint touchPoint; + + auto cX = point.x(); + auto cY = point.y(); + touchPoint.area = QRect(0, 0, 8, 8); + touchPoint.area.moveCenter(QPointF(cX,cY)); // simulate area + + touchPoint.id = touches->identifier; + touchPoint.normalPosition = QPointF(cX / window2->width(), cY / window2->height()); + + switch (eventType) { + case EMSCRIPTEN_EVENT_TOUCHSTART: + touchPoint.state = Qt::TouchPointPressed; + break; + case EMSCRIPTEN_EVENT_TOUCHEND: + touchPoint.state = Qt::TouchPointReleased; + break; + case EMSCRIPTEN_EVENT_TOUCHMOVE: + touchPoint.state = Qt::TouchPointMoved; + break; + default: + Q_UNREACHABLE(); + } + + touchPointList.append(touchPoint); + } + + QWasmEventTranslator *wasmEventTranslator = (QWasmEventTranslator*)userData; + QFlags keyModifier = translatKeyModifier(touchEvent); + + if (eventType != EMSCRIPTEN_EVENT_TOUCHCANCEL) + QWindowSystemInterface::handleTouchEvent(window2, wasmEventTranslator->getTimestamp(), wasmEventTranslator->touchDevice, touchPointList, keyModifier); + else + QWindowSystemInterface::handleTouchCancelEvent(window2, wasmEventTranslator->getTimestamp(), wasmEventTranslator->touchDevice, keyModifier); + + QCoreApplication::processEvents(); + return 1; +} + +quint64 QWasmEventTranslator::getTimestamp() +{ + return QDeadlineTimer::current().deadlineNSecs() / 1000; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.h b/src/plugins/platforms/wasm/qwasmeventtranslator.h new file mode 100644 index 00000000000..11430a57a21 --- /dev/null +++ b/src/plugins/platforms/wasm/qwasmeventtranslator.h @@ -0,0 +1,210 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) 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.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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWASMEVENTTRANSLATOR_H +#define QWASMEVENTTRANSLATOR_H + +#include +#include +#include +#include +#include "qwasmwindow.h" +#include + +QT_BEGIN_NAMESPACE + +class QWindow; + +class QWasmEventTranslator : public QObject +{ + Q_OBJECT + + enum KeyCode { + // numpad + KeyNumPad0 = 0x60, + KeyNumPad1 = 0x61, + KeyNumPad2 = 0x62, + KeyNumPad3 = 0x63, + KeyNumPad4 = 0x64, + KeyNumPad5 = 0x65, + KeyNumPad6 = 0x66, + KeyNumPad7 = 0x67, + KeyNumPad8 = 0x68, + KeyNumPad9 = 0x69, + KeyMultiply = 0x6A, + KeyAdd = 0x6B, + KeySeparator = 0x6C, + KeySubtract = 0x6D, + KeyDecimal = 0x6E, + KeyDivide = 0x6F, + KeyMeta = 0x5B, + KeyMetaRight = 0x5C, + //////// + KeyClear = 0x90, + KeyEnter = 0xD, + KeyBackSpace = 0x08, + KeyCancel = 0x03, + KeyTab = 0x09, + KeyShift = 0x10, + KeyControl = 0x11, + KeyAlt = 0x12, + KeyPause = 0x13, + KeyCapsLock = 0x14, + KeyEscape = 0x1B, + KeySpace = 0x20, + KeyPageUp = 0x21, + KeyPageDown = 0x22, + KeyEnd = 0x23, + KeyHome = 0x24, + KeyLeft = 0x25, + KeyUp = 0x26, + KeyRight = 0x27, + KeyDown = 0x28, + KeyComma = 0xBC, + KeyPeriod = 0xBE, + KeySlash = 0xBF, + KeyZero = 0x30, + KeyOne = 0x31, + KeyTwo = 0x32, + KeyThree = 0x33, + KeyFour = 0x34, + KeyFive = 0x35, + KeySix = 0x36, + KeySeven = 0x37, + KeyEight = 0x38, + KeyNine = 0x39, + KeyBrightnessDown = 0xD8, + KeyBrightnessUp = 0xD9, + KeyMediaTrackPrevious = 0xB1, + KeyMediaPlayPause = 0xB3, + KeyMediaTrackNext = 0xB0, + KeyAudioVolumeMute = 0xAD, + KeyAudioVolumeDown = 0xAE, + KeyAudioVolumeUp = 0xAF, + KeySemiColon = 0xBA, + KeyEquals = 0xBB, + KeyMinus = 0xBD, + KeyA = 0x41, + KeyB = 0x42, + KeyC = 0x43, + KeyD = 0x44, + KeyE = 0x45, + KeyF = 0x46, + KeyG = 0x47, + KeyH = 0x48, + KeyI = 0x49, + KeyJ = 0x4A, + KeyK = 0x4B, + KeyL = 0x4C, + KeyM = 0x4D, + KeyN = 0x4E, + KeyO = 0x4F, + KeyP = 0x50, + KeyQ = 0x51, + KeyR = 0x52, + KeyS = 0x53, + KeyT = 0x54, + KeyU = 0x55, + KeyV = 0x56, + KeyW = 0x57, + KeyX = 0x58, + KeyY = 0x59, + KeyZ = 0x5A, + KeyOpenBracket = 0xDB, + KeyBackSlash = 0xDC, + KeyCloseBracket = 0xDD, + KeyF1 = 0x70, + KeyF2 = 0x71, + KeyF3 = 0x72, + KeyF4 = 0x73, + KeyF5 = 0x74, + KeyF6 = 0x75, + KeyF7 = 0x76, + KeyF8 = 0x77, + KeyF9 = 0x78, + KeyF10 = 0x79, + KeyF11 = 0x7A, + KeyF12 = 0x7B, + KeyDelete = 0x2E, + KeyNumLock = 0x90, + KeyScrollLock = 0x91, + KeyPrintScreen = 0x9A, + KeyInsert = 0x9B, + KeyHelp = 0x9C, + KeyBackQuote = 0xC0, + KeyQuote = 0xDE, + KeyFinal = 0x18, + KeyConvert = 0x1C, + KeyNonConvert = 0x1D, + KeyAccept = 0x1E, + KeyModeChange = 0x1F, + KeyKana = 0x15, + KeyKanji = 0x19, + KeyUndefined = 0x0 + }; + +public: + + explicit QWasmEventTranslator(QObject *parent = 0); + + static int keyboard_cb(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData); + static int mouse_cb(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData); + static int focus_cb(int eventType, const EmscriptenFocusEvent *focusEvent, void *userData); + static int wheel_cb(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData); + + static int touchCallback(int eventType, const EmscriptenTouchEvent *ev, void *userData); + + void processEvents(); + +Q_SIGNALS: + void getWindowAt(const QPoint &point, QWindow **window); +private: + static Qt::Key translateEmscriptKey(const EmscriptenKeyboardEvent *emscriptKey, bool *outAlphanumretic); + template + static QFlags translatKeyModifier(const Event *event); + static QFlags translateKeyboardEventModifier(const EmscriptenKeyboardEvent *keyEvent); + static QFlags translateMouseEventModifier(const EmscriptenMouseEvent *mouseEvent); + static Qt::MouseButton translateMouseButton(unsigned short button); + + void processMouse(int eventType, const EmscriptenMouseEvent *mouseEvent); + +private: + QWindow *draggedWindow; + QWindow *pressedWindow; + Qt::MouseButtons pressedButtons; + + QWasmWindow::ResizeMode resizeMode; + QPoint resizePoint; + QRect resizeStartRect; + QTouchDevice *touchDevice; + quint64 getTimestamp(); +}; + +QT_END_NAMESPACE +#endif // QWASMEVENTTRANSLATOR_H diff --git a/src/plugins/platforms/wasm/qwasmfontdatabase.cpp b/src/plugins/platforms/wasm/qwasmfontdatabase.cpp new file mode 100644 index 00000000000..0c72dfddc4a --- /dev/null +++ b/src/plugins/platforms/wasm/qwasmfontdatabase.cpp @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) 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.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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwasmfontdatabase.h" + +#include + +QT_BEGIN_NAMESPACE + +void QWasmFontDatabase::populateFontDatabase() +{ + // Load font file from resources. Currently + // all fonts needs to be bundled with the nexe + // as Qt resources. + QStringList fontFileNames = QStringList() << QStringLiteral(":/fonts/Vera.ttf") + << QStringLiteral(":/fonts/DejaVuSans.ttf"); + + foreach (const QString &fontFileName, fontFileNames) { + QFile theFont(fontFileName); + if (!theFont.open(QIODevice::ReadOnly)) + break; + + QFreeTypeFontDatabase::addTTFile(theFont.readAll(), fontFileName.toLatin1()); + } +} + +QFontEngine *QWasmFontDatabase::fontEngine(const QFontDef &fontDef, void *handle) +{ + return QFreeTypeFontDatabase::fontEngine(fontDef, handle); +} + +QStringList QWasmFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, + QFont::StyleHint styleHint, + QChar::Script script) const +{ + QStringList fallbacks + = QFreeTypeFontDatabase::fallbacksForFamily(family, style, styleHint, script); + + // Add the vera.ttf font (loaded in populateFontDatabase above) as a falback font + // to all other fonts (except itself). + const QString veraFontFamily = QStringLiteral("Bitstream Vera Sans"); + if (family != veraFontFamily) + fallbacks.append(veraFontFamily); + + return fallbacks; +} + +QStringList QWasmFontDatabase::addApplicationFont(const QByteArray &fontData, + const QString &fileName) +{ + return QFreeTypeFontDatabase::addApplicationFont(fontData, fileName); +} + +void QWasmFontDatabase::releaseHandle(void *handle) +{ + QFreeTypeFontDatabase::releaseHandle(handle); +} + + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/wasm/qwasmfontdatabase.h b/src/plugins/platforms/wasm/qwasmfontdatabase.h new file mode 100644 index 00000000000..891f12859e0 --- /dev/null +++ b/src/plugins/platforms/wasm/qwasmfontdatabase.h @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) 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.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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWASMFONTDATABASE_H +#define QWASMFONTDATABASE_H + +#include + +QT_BEGIN_NAMESPACE + +class QWasmFontDatabase : public QFreeTypeFontDatabase +{ +public: + void populateFontDatabase() override; + QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) override; + QStringList fallbacksForFamily(const QString &family, QFont::Style style, + QFont::StyleHint styleHint, + QChar::Script script) const override; + QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName) override; + void releaseHandle(void *handle) override; +}; +QT_END_NAMESPACE +#endif diff --git a/src/plugins/platforms/wasm/qwasmintegration.cpp b/src/plugins/platforms/wasm/qwasmintegration.cpp new file mode 100644 index 00000000000..accc1fd2fe7 --- /dev/null +++ b/src/plugins/platforms/wasm/qwasmintegration.cpp @@ -0,0 +1,219 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) 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.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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwasmintegration.h" +#include "qwasmeventtranslator.h" +#include "qwasmeventdispatcher.h" +#include "qwasmcompositor.h" +#include "qwasmopenglcontext.h" +#include "qwasmtheme.h" + +#include "qwasmwindow.h" +#ifndef QT_NO_OPENGL +# include "qwasmbackingstore.h" +#endif +#include "qwasmfontdatabase.h" +#if defined(Q_OS_UNIX) +#include +#endif +#include +#include +#include +#include + +#include + +// this is where EGL headers are pulled in, make sure it is last +#include "qwasmscreen.h" + +using namespace emscripten; +QT_BEGIN_NAMESPACE + +void browserBeforeUnload() +{ + QWasmIntegration::QWasmBrowserExit(); +} + +EMSCRIPTEN_BINDINGS(my_module) +{ + function("browserBeforeUnload", &browserBeforeUnload); +} + +static QWasmIntegration *globalHtml5Integration; +QWasmIntegration *QWasmIntegration::get() { return globalHtml5Integration; } + +QWasmIntegration::QWasmIntegration() + : m_fontDb(nullptr), + m_compositor(new QWasmCompositor), + m_screen(new QWasmScreen(m_compositor)), + m_eventDispatcher(nullptr) +{ + + globalHtml5Integration = this; + + updateQScreenAndCanvasRenderSize(); + screenAdded(m_screen); + emscripten_set_resize_callback(0, (void *)this, 1, uiEvent_cb); + + m_eventTranslator = new QWasmEventTranslator; + + EM_ASM(// exit app if browser closes + window.onbeforeunload = function () { + Module.browserBeforeUnload(); + }; + ); +} + +QWasmIntegration::~QWasmIntegration() +{ + delete m_compositor; + destroyScreen(m_screen); + delete m_fontDb; + delete m_eventTranslator; +} + +void QWasmIntegration::QWasmBrowserExit() +{ + QCoreApplication *app = QCoreApplication::instance(); + app->quit(); +} + +bool QWasmIntegration::hasCapability(QPlatformIntegration::Capability cap) const +{ + switch (cap) { + case ThreadedPixmaps: return true; + case OpenGL: return true; + case ThreadedOpenGL: return true; + case RasterGLSurface: return true; + case MultipleWindows: return true; + case WindowManagement: return true; + default: return QPlatformIntegration::hasCapability(cap); + } +} + +QPlatformWindow *QWasmIntegration::createPlatformWindow(QWindow *window) const +{ + return new QWasmWindow(window, m_compositor, m_backingStores.value(window)); +} + +QPlatformBackingStore *QWasmIntegration::createPlatformBackingStore(QWindow *window) const +{ +#ifndef QT_NO_OPENGL + QWasmBackingStore *backingStore = new QWasmBackingStore(m_compositor, window); + m_backingStores.insert(window, backingStore); + return backingStore; +#else + return nullptr; +#endif +} + +#ifndef QT_NO_OPENGL +QPlatformOpenGLContext *QWasmIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const +{ + return new QWasmOpenGLContext(context->format()); +} +#endif + +QPlatformFontDatabase *QWasmIntegration::fontDatabase() const +{ + if (m_fontDb == nullptr) + m_fontDb = new QWasmFontDatabase; + + return m_fontDb; +} + +QAbstractEventDispatcher *QWasmIntegration::createEventDispatcher() const +{ + return new QWasmEventDispatcher; +} + +QVariant QWasmIntegration::styleHint(QPlatformIntegration::StyleHint hint) const +{ + return QPlatformIntegration::styleHint(hint); +} + +QStringList QWasmIntegration::themeNames() const +{ + return QStringList() << QLatin1String("webassembly"); +} + +QPlatformTheme *QWasmIntegration::createPlatformTheme(const QString &name) const +{ + if (name == QLatin1String("webassembly")) + return new QWasmTheme; + return QPlatformIntegration::createPlatformTheme(name); +} + +int QWasmIntegration::uiEvent_cb(int eventType, const EmscriptenUiEvent *e, void *userData) +{ + Q_UNUSED(e) + Q_UNUSED(userData) + + if (eventType == EMSCRIPTEN_EVENT_RESIZE) { + // This resize event is called when the HTML window is resized. Depending + // on the page layout the the canvas might also have been resized, so we + // update the Qt screen size (and canvas render size). + updateQScreenAndCanvasRenderSize(); + } + + return 0; +} + +static void set_canvas_size(double width, double height) +{ + EM_ASM_({ + var canvas = Module.canvas; + canvas.width = $0; + canvas.height = $1; + }, width, height); +} + +void QWasmIntegration::updateQScreenAndCanvasRenderSize() +{ + // The HTML canvas has two sizes: the CSS size and the canvas render size. + // The CSS size is determined according to standard CSS rules, while the + // render size is set using the "width" and "height" attributes. The render + // size must be set manually and is not auto-updated on CSS size change. + // Setting the render size to a value larger than the CSS size enables high-dpi + // rendering. + + double css_width; + double css_height; + emscripten_get_element_css_size(0, &css_width, &css_height); + QSizeF cssSize(css_width, css_height); + + QWasmScreen *screen = QWasmIntegration::get()->m_screen; + QSizeF canvasSize = cssSize * screen->devicePixelRatio(); + + set_canvas_size(canvasSize.width(), canvasSize.height()); + screen->setGeometry(QRect(QPoint(0, 0), cssSize.toSize())); + QWasmIntegration::get()->m_compositor->redrawWindowContent(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/wasm/qwasmintegration.h b/src/plugins/platforms/wasm/qwasmintegration.h new file mode 100644 index 00000000000..ebc3d9d4311 --- /dev/null +++ b/src/plugins/platforms/wasm/qwasmintegration.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) 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.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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWASMINTEGRATION_H +#define QWASMINTEGRATION_H + +#include "qwasmwindow.h" + +#include +#include + +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +class QWasmEventTranslator; +class QWasmFontDatabase; +class QWasmWindow; +class QWasmEventDispatcher; +class QWasmScreen; +class QWasmCompositor; +class QWasmBackingStore; + +class QWasmIntegration : public QObject, public QPlatformIntegration +{ + Q_OBJECT +public: + QWasmIntegration(); + ~QWasmIntegration(); + + bool hasCapability(QPlatformIntegration::Capability cap) const override; + QPlatformWindow *createPlatformWindow(QWindow *window) const override; + QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override; +#ifndef QT_NO_OPENGL + QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override; +#endif + QPlatformFontDatabase *fontDatabase() const override; + QAbstractEventDispatcher *createEventDispatcher() const override; + QVariant styleHint(QPlatformIntegration::StyleHint hint) const override; + QStringList themeNames() const override; + QPlatformTheme *createPlatformTheme(const QString &name) const override; + + static QWasmIntegration *get(); + QWasmScreen *screen() { return m_screen; } + QWasmCompositor *compositor() { return m_compositor; } + QWasmEventTranslator *eventTranslator() { return m_eventTranslator; } + + static void QWasmBrowserExit(); + static void updateQScreenAndCanvasRenderSize(); + +private: + mutable QWasmFontDatabase *m_fontDb; + QWasmCompositor *m_compositor; + mutable QWasmScreen *m_screen; + mutable QWasmEventTranslator *m_eventTranslator; + mutable QWasmEventDispatcher *m_eventDispatcher; + static int uiEvent_cb(int eventType, const EmscriptenUiEvent *e, void *userData); + mutable QHash m_backingStores; +}; + +QT_END_NAMESPACE + +#endif // QWASMINTEGRATION_H diff --git a/src/plugins/platforms/wasm/qwasmopenglcontext.cpp b/src/plugins/platforms/wasm/qwasmopenglcontext.cpp new file mode 100644 index 00000000000..73af3d18782 --- /dev/null +++ b/src/plugins/platforms/wasm/qwasmopenglcontext.cpp @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) 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.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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwasmopenglcontext.h" + +#include + +QT_BEGIN_NAMESPACE + +QWasmOpenGLContext::QWasmOpenGLContext(const QSurfaceFormat &format) + : m_requestedFormat(format) +{ + m_requestedFormat.setRenderableType(QSurfaceFormat::OpenGLES); +} + +QWasmOpenGLContext::~QWasmOpenGLContext() +{ + if (m_context) + emscripten_webgl_destroy_context(m_context); +} + +void QWasmOpenGLContext::maybeRecreateEmscriptenContext(QPlatformSurface *surface) +{ + // Native emscripten contexts are tied to a single surface. Recreate + // the context if the surface is changed. + if (surface != m_surface) { + m_surface = surface; + + // Destroy existing context + if (m_context) + emscripten_webgl_destroy_context(m_context); + + // Create new context + const char *canvasId = 0; // (use default canvas) FIXME: get the actual canvas from the surface. + m_context = createEmscriptenContext(canvasId, m_requestedFormat); + + // Register context-lost callback. + auto callback = [](int eventType, const void *reserved, void *userData) -> EM_BOOL + { + Q_UNUSED(eventType); + Q_UNUSED(reserved); + // The application may get contex-lost if e.g. moved to the background. Set + // m_contextLost which will make isValid() return false. Application code will + // then detect this and recrate the the context, resulting in a new QWasmOpenGLContext + // instance. + reinterpret_cast(userData)->m_contextLost = true; + return true; + }; + bool capture = true; + emscripten_set_webglcontextlost_callback(canvasId, this, capture, callback); + } +} + +EMSCRIPTEN_WEBGL_CONTEXT_HANDLE QWasmOpenGLContext::createEmscriptenContext(const char *canvasId, QSurfaceFormat format) +{ + EmscriptenWebGLContextAttributes attributes; + emscripten_webgl_init_context_attributes(&attributes); // Populate with default attributes + + attributes.preferLowPowerToHighPerformance = false; + attributes.failIfMajorPerformanceCaveat = false; + attributes.antialias = true; + attributes.enableExtensionsByDefault = true; + + if (format.majorVersion() == 3) { + attributes.majorVersion = 2; + } + + // WebGL offers enable/disable control but not size control for these + attributes.alpha = format.alphaBufferSize() > 0; + attributes.depth = format.depthBufferSize() > 0; + attributes.stencil = format.stencilBufferSize() > 0; + + EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context = emscripten_webgl_create_context(canvasId, &attributes); + + return context; +} + +QSurfaceFormat QWasmOpenGLContext::format() const +{ + return m_requestedFormat; +} + +GLuint QWasmOpenGLContext::defaultFramebufferObject(QPlatformSurface *surface) const +{ + return QPlatformOpenGLContext::defaultFramebufferObject(surface); +} + +bool QWasmOpenGLContext::makeCurrent(QPlatformSurface *surface) +{ + maybeRecreateEmscriptenContext(surface); + + return emscripten_webgl_make_context_current(m_context) == EMSCRIPTEN_RESULT_SUCCESS; +} + +void QWasmOpenGLContext::swapBuffers(QPlatformSurface *surface) +{ + Q_UNUSED(surface); + // No swapbuffers on WebGl +} + +void QWasmOpenGLContext::doneCurrent() +{ + // No doneCurrent on WebGl +} + +bool QWasmOpenGLContext::isSharing() const +{ + return false; +} + +bool QWasmOpenGLContext::isValid() const +{ + return (m_contextLost == false); +} + +QFunctionPointer QWasmOpenGLContext::getProcAddress(const char *procName) +{ + return reinterpret_cast(eglGetProcAddress(procName)); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/wasm/qwasmopenglcontext.h b/src/plugins/platforms/wasm/qwasmopenglcontext.h new file mode 100644 index 00000000000..91231004798 --- /dev/null +++ b/src/plugins/platforms/wasm/qwasmopenglcontext.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) 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.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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +class QWasmOpenGLContext : public QPlatformOpenGLContext +{ +public: + QWasmOpenGLContext(const QSurfaceFormat &format); + ~QWasmOpenGLContext(); + + QSurfaceFormat format() const override; + void swapBuffers(QPlatformSurface *surface) override; + GLuint defaultFramebufferObject(QPlatformSurface *surface) const override; + bool makeCurrent(QPlatformSurface *surface) override; + void doneCurrent() override; + bool isSharing() const override; + bool isValid() const override; + QFunctionPointer getProcAddress(const char *procName) override; + +private: + void maybeRecreateEmscriptenContext(QPlatformSurface *surface); + static EMSCRIPTEN_WEBGL_CONTEXT_HANDLE createEmscriptenContext(const char *canvasId, QSurfaceFormat format); + + bool m_contextLost = false; + QSurfaceFormat m_requestedFormat; + QPlatformSurface *m_surface = nullptr; + EMSCRIPTEN_WEBGL_CONTEXT_HANDLE m_context = 0; +}; + +QT_END_NAMESPACE + diff --git a/src/plugins/platforms/wasm/qwasmscreen.cpp b/src/plugins/platforms/wasm/qwasmscreen.cpp new file mode 100644 index 00000000000..93e9906ffc4 --- /dev/null +++ b/src/plugins/platforms/wasm/qwasmscreen.cpp @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) 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.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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwasmscreen.h" +#include "qwasmwindow.h" +#include "qwasmcompositor.h" + +#include +#ifndef QT_NO_OPENGL +# include +#endif +#include +#include +#include +#include + + +QT_BEGIN_NAMESPACE + +QWasmScreen::QWasmScreen(QWasmCompositor *compositor) + : m_compositor(compositor) + , m_depth(32) + , m_format(QImage::Format_RGB32) +{ + m_compositor->setScreen(this); +} + +QWasmScreen::~QWasmScreen() +{ + +} + +QRect QWasmScreen::geometry() const +{ + return m_geometry; +} + +int QWasmScreen::depth() const +{ + return m_depth; +} + +QImage::Format QWasmScreen::format() const +{ + return m_format; +} + +qreal QWasmScreen::devicePixelRatio() const +{ + // FIXME: The effective device pixel ratio may be different from the + // HTML window dpr if the OpenGL driver/GPU allocates a less than + // full resolution surface. Use emscripten_webgl_get_drawing_buffer_size() + // and compute the dpr instead. + double htmlWindowDpr = EM_ASM_DOUBLE({ + return window.devicePixelRatio; + }); + return qreal(htmlWindowDpr); +} + +QPlatformCursor *QWasmScreen::cursor() const +{ + return const_cast(&m_cursor); +} + +void QWasmScreen::resizeMaximizedWindows() +{ + QPlatformScreen::resizeMaximizedWindows(); +} + +QWindow *QWasmScreen::topWindow() const +{ + return m_compositor->keyWindow(); +} + +QWindow *QWasmScreen::topLevelAt(const QPoint &p) const +{ + return m_compositor->windowAt(p); +} + +void QWasmScreen::invalidateSize() +{ + m_geometry = QRect(); +} + +void QWasmScreen::setGeometry(const QRect &rect) +{ + m_geometry = rect; + QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry()); + resizeMaximizedWindows(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/wasm/qwasmscreen.h b/src/plugins/platforms/wasm/qwasmscreen.h new file mode 100644 index 00000000000..3891db77bb9 --- /dev/null +++ b/src/plugins/platforms/wasm/qwasmscreen.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) 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.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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWASMSCREEN_H +#define QWASMSCREEN_H + +#include "qwasmcursor.h" + +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlatformOpenGLContext; +class QWasmWindow; +class QWasmBackingStore; +class QWasmCompositor; +class QOpenGLContext; + +class QWasmScreen : public QObject, public QPlatformScreen +{ + Q_OBJECT +public: + + QWasmScreen(QWasmCompositor *compositor); + ~QWasmScreen(); + + QRect geometry() const override; + int depth() const override; + QImage::Format format() const override; + qreal devicePixelRatio() const override; + QPlatformCursor *cursor() const override; + + void resizeMaximizedWindows(); + QWindow *topWindow() const; + QWindow *topLevelAt(const QPoint &p) const override; + + void invalidateSize(); + +public slots: + void setGeometry(const QRect &rect); +protected: + +private: + QWasmCompositor *m_compositor; + + QRect m_geometry = QRect(0, 0, 100, 100); + int m_depth; + QImage::Format m_format; + QWasmCursor m_cursor; +}; + +QT_END_NAMESPACE +#endif // QWASMSCREEN_H diff --git a/src/plugins/platforms/wasm/qwasmstylepixmaps_p.h b/src/plugins/platforms/wasm/qwasmstylepixmaps_p.h new file mode 100644 index 00000000000..2b5860f42ff --- /dev/null +++ b/src/plugins/platforms/wasm/qwasmstylepixmaps_p.h @@ -0,0 +1,183 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) 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.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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWASMSTYLEPIXMAPS_P_H +#define QWASMSTYLEPIXMAPS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +/* XPM */ +static const char * const qt_menu_xpm[] = { +"16 16 72 1", +" c None", +". c #65AF36", +"+ c #66B036", +"@ c #77B94C", +"# c #A7D28C", +"$ c #BADBA4", +"% c #A4D088", +"& c #72B646", +"* c #9ACB7A", +"= c #7FBD56", +"- c #85C05F", +"; c #F4F9F0", +"> c #FFFFFF", +", c #E5F1DC", +"' c #ECF5E7", +") c #7ABA50", +"! c #83BF5C", +"~ c #AED595", +"{ c #D7EACA", +"] c #A9D28D", +"^ c #BCDDA8", +"/ c #C4E0B1", +"( c #81BE59", +"_ c #D0E7C2", +": c #D4E9C6", +"< c #6FB542", +"[ c #6EB440", +"} c #88C162", +"| c #98CA78", +"1 c #F4F9F1", +"2 c #8FC56C", +"3 c #F1F8EC", +"4 c #E8F3E1", +"5 c #D4E9C7", +"6 c #74B748", +"7 c #80BE59", +"8 c #73B747", +"9 c #6DB43F", +"0 c #CBE4BA", +"a c #80BD58", +"b c #6DB33F", +"c c #FEFFFE", +"d c #68B138", +"e c #F9FCF7", +"f c #91C66F", +"g c #E8F3E0", +"h c #DCEDD0", +"i c #91C66E", +"j c #A3CF86", +"k c #C9E3B8", +"l c #B0D697", +"m c #E3F0DA", +"n c #95C873", +"o c #E6F2DE", +"p c #9ECD80", +"q c #BEDEAA", +"r c #C7E2B6", +"s c #79BA4F", +"t c #6EB441", +"u c #BCDCA7", +"v c #FAFCF8", +"w c #F6FAF3", +"x c #84BF5D", +"y c #EDF6E7", +"z c #FAFDF9", +"A c #88C263", +"B c #98CA77", +"C c #CDE5BE", +"D c #67B037", +"E c #D9EBCD", +"F c #6AB23C", +"G c #77B94D", +" .++++++++++++++", +".+++++++++++++++", +"+++@#$%&+++*=+++", +"++-;>,>')+!>~+++", +"++{>]+^>/(_>:~<+", +"+[>>}+|>123>456+", +"+7>>8+->>90>~+++", +"+a>>b+a>c[0>~+++", +"+de>=+f>g+0>~+++", +"++h>i+j>k+0>~+++", +"++l>mno>p+q>rst+", +"++duv>wl++xy>zA+", +"++++B>Cb++++&D++", +"+++++0zE++++++++", +"++++++FG+++++++.", +"++++++++++++++. "}; + +static const char * const qt_close_xpm[] = { +"10 10 2 1", +"# c #000000", +". c None", +"..........", +".##....##.", +"..##..##..", +"...####...", +"....##....", +"...####...", +"..##..##..", +".##....##.", +"..........", +".........."}; + +static const char * const qt_maximize_xpm[]={ +"10 10 2 1", +"# c #000000", +". c None", +"#########.", +"#########.", +"#.......#.", +"#.......#.", +"#.......#.", +"#.......#.", +"#.......#.", +"#.......#.", +"#########.", +".........."}; + + +static const char * const qt_normalizeup_xpm[] = { +"10 10 2 1", +"# c #000000", +". c None", +"...######.", +"...######.", +"...#....#.", +".######.#.", +".######.#.", +".#....###.", +".#....#...", +".#....#...", +".######...", +".........."}; + + +#endif // QWASMSTYLEPIXMAPS_P_H diff --git a/src/plugins/platforms/wasm/qwasmtheme.cpp b/src/plugins/platforms/wasm/qwasmtheme.cpp new file mode 100644 index 00000000000..a7f2db3bd3c --- /dev/null +++ b/src/plugins/platforms/wasm/qwasmtheme.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) 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.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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwasmtheme.h" +#include + +QT_BEGIN_NAMESPACE + +QWasmTheme::QWasmTheme() +{ +} + +QWasmTheme::~QWasmTheme() +{ +} + +QVariant QWasmTheme::themeHint(ThemeHint hint) const +{ + if (hint == QPlatformTheme::StyleNames) + return QVariant(QStringList() << QLatin1String("fusion")); + return QPlatformTheme::themeHint(hint); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/wasm/qwasmtheme.h b/src/plugins/platforms/wasm/qwasmtheme.h new file mode 100644 index 00000000000..e4cc06e0498 --- /dev/null +++ b/src/plugins/platforms/wasm/qwasmtheme.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) 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.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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWASMTHEME_H +#define QWASMTHEME_H + +#include + +QT_BEGIN_NAMESPACE + +class QWasmEventTranslator; +class QWasmFontDatabase; +class QWasmWindow; +class QWasmEventDispatcher; +class QWasmScreen; +class QWasmCompositor; +class QWasmBackingStore; + +class QWasmTheme : public QPlatformTheme +{ +public: + QWasmTheme(); + ~QWasmTheme(); + + QVariant themeHint(ThemeHint hint) const override; +}; + +QT_END_NAMESPACE + +#endif // QWASMTHEME_H diff --git a/src/plugins/platforms/wasm/qwasmwindow.cpp b/src/plugins/platforms/wasm/qwasmwindow.cpp new file mode 100644 index 00000000000..0489813929c --- /dev/null +++ b/src/plugins/platforms/wasm/qwasmwindow.cpp @@ -0,0 +1,398 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) 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.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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "qwasmwindow.h" +#include "qwasmscreen.h" +#include "qwasmcompositor.h" +#include "qwasmeventdispatcher.h" + +#include + +Q_GUI_EXPORT int qt_defaultDpiX(); + +QT_BEGIN_NAMESPACE + +QWasmWindow::QWasmWindow(QWindow *w, QWasmCompositor *compositor, QWasmBackingStore *backingStore) + : QPlatformWindow(w), + m_window(w), + m_compositor(compositor), + m_backingStore(backingStore) +{ + m_needsCompositor = w->surfaceType() != QSurface::OpenGLSurface; + static int serialNo = 0; + m_winid = ++serialNo; + qWarning("QWasmWindow %p: %p 0x%x\n", this, w, uint(m_winid)); + + m_compositor->addWindow(this); + + // Pure OpenGL windows draw directly using egl, disable the compositor. + m_compositor->setEnabled(w->surfaceType() != QSurface::OpenGLSurface); +} + +QWasmWindow::~QWasmWindow() +{ + m_compositor->removeWindow(this); +} + +void QWasmWindow::initialize() +{ + QRect rect = windowGeometry(); + + QPlatformWindow::setGeometry(rect); + + const QSize minimumSize = windowMinimumSize(); + if (rect.width() > 0 || rect.height() > 0) { + rect.setWidth(qBound(1, rect.width(), 2000)); + rect.setHeight(qBound(1, rect.height(), 2000)); + } else if (minimumSize.width() > 0 || minimumSize.height() > 0) { + rect.setSize(minimumSize); + } + + setWindowState(window()->windowStates()); + setWindowFlags(window()->flags()); + setWindowTitle(window()->title()); + m_hasTitle = window()->flags().testFlag(Qt::WindowTitleHint) && m_needsCompositor; + + if (window()->isTopLevel()) + setWindowIcon(window()->icon()); + m_normalGeometry = rect; +} + +QWasmScreen *QWasmWindow::platformScreen() const +{ + return static_cast(window()->screen()->handle()); +} + +void QWasmWindow::setGeometry(const QRect &rect) +{ + QRect r = rect; + if (m_needsCompositor) { + int yMin = window()->geometry().top() - window()->frameGeometry().top(); + + if (r.y() < yMin) + r.moveTop(yMin); + } + QWindowSystemInterface::handleGeometryChange(window(), r); + QPlatformWindow::setGeometry(r); + + QWindowSystemInterface::flushWindowSystemEvents(); + invalidate(); +} + +void QWasmWindow::setVisible(bool visible) +{ + QRect newGeom; + + if (visible) { + const bool forceFullScreen = !m_needsCompositor;//make gl apps fullscreen for now + + if (forceFullScreen || (m_windowState & Qt::WindowFullScreen)) + newGeom = platformScreen()->geometry(); + else if (m_windowState & Qt::WindowMaximized) + newGeom = platformScreen()->availableGeometry(); + } + QPlatformWindow::setVisible(visible); + + m_compositor->setVisible(this, visible); + + if (!newGeom.isEmpty()) + setGeometry(newGeom); // may or may not generate an expose + + invalidate(); +} + +QMargins QWasmWindow::frameMargins() const +{ + int border = m_hasTitle ? 4. * (qreal(qt_defaultDpiX()) / 96.0) : 0; + int titleBarHeight = m_hasTitle ? titleHeight() : 0; + + QMargins margins; + margins.setLeft(border); + margins.setRight(border); + margins.setTop(2*border + titleBarHeight); + margins.setBottom(border); + + return margins; +} + +void QWasmWindow::raise() +{ + m_compositor->raise(this); + QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), geometry().size())); + invalidate(); +} + +void QWasmWindow::lower() +{ + m_compositor->lower(this); + QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), geometry().size())); + invalidate(); +} + +WId QWasmWindow::winId() const +{ + return m_winid; +} + +void QWasmWindow::propagateSizeHints() +{ +// get rid of base class warning +} + +void QWasmWindow::injectMousePressed(const QPoint &local, const QPoint &global, + Qt::MouseButton button, Qt::KeyboardModifiers mods) +{ + Q_UNUSED(local); + Q_UNUSED(mods); + + if (!m_hasTitle || button != Qt::LeftButton) + return; + + if (maxButtonRect().contains(global)) + m_activeControl = QWasmCompositor::SC_TitleBarMaxButton; + else if (minButtonRect().contains(global)) + m_activeControl = QWasmCompositor::SC_TitleBarMinButton; + else if (closeButtonRect().contains(global)) + m_activeControl = QWasmCompositor::SC_TitleBarCloseButton; + else if (normButtonRect().contains(global)) + m_activeControl = QWasmCompositor::SC_TitleBarNormalButton; + + invalidate(); +} + +void QWasmWindow::injectMouseReleased(const QPoint &local, const QPoint &global, + Qt::MouseButton button, Qt::KeyboardModifiers mods) +{ + Q_UNUSED(local); + Q_UNUSED(mods); + + if (!m_hasTitle || button != Qt::LeftButton) + return; + + if (closeButtonRect().contains(global) && m_activeControl == QWasmCompositor::SC_TitleBarCloseButton) + window()->close(); + + if (maxButtonRect().contains(global) && m_activeControl == QWasmCompositor::SC_TitleBarMaxButton) { + window()->setWindowState(Qt::WindowMaximized); + platformScreen()->resizeMaximizedWindows(); + } + + if (normButtonRect().contains(global) && m_activeControl == QWasmCompositor::SC_TitleBarNormalButton) { + window()->setWindowState(Qt::WindowNoState); + setGeometry(normalGeometry()); + } + + m_activeControl = QWasmCompositor::SC_None; + + invalidate(); +} + +int QWasmWindow::titleHeight() const +{ + return 18. * (qreal(qt_defaultDpiX()) / 96.0);//dpiScaled(18.); +} + +int QWasmWindow::borderWidth() const +{ + return 4. * (qreal(qt_defaultDpiX()) / 96.0);// dpiScaled(4.); +} + +QRegion QWasmWindow::titleGeometry() const +{ + int border = borderWidth(); + + QRegion result(window()->frameGeometry().x() + border, + window()->frameGeometry().y() + border, + window()->frameGeometry().width() - 2*border, + titleHeight()); + + result -= titleControlRegion(); + + return result; +} + +QRegion QWasmWindow::resizeRegion() const +{ + int border = borderWidth(); + QRegion result(window()->frameGeometry().adjusted(-border, -border, border, border)); + result -= window()->frameGeometry().adjusted(border, border, -border, -border); + + return result; +} + +bool QWasmWindow::isPointOnTitle(QPoint point) const +{ + bool ok = titleGeometry().contains(point); + return ok; +} + +bool QWasmWindow::isPointOnResizeRegion(QPoint point) const +{ + return resizeRegion().contains(point); +} + +QWasmWindow::ResizeMode QWasmWindow::resizeModeAtPoint(QPoint point) const +{ + QPoint p1 = window()->frameGeometry().topLeft() - QPoint(5, 5); + QPoint p2 = window()->frameGeometry().bottomRight() + QPoint(5, 5); + int corner = 20; + + QRect top(p1, QPoint(p2.x(), p1.y() + corner)); + QRect middle(QPoint(p1.x(), p1.y() + corner), QPoint(p2.x(), p2.y() - corner)); + QRect bottom(QPoint(p1.x(), p2.y() - corner), p2); + + QRect left(p1, QPoint(p1.x() + corner, p2.y())); + QRect center(QPoint(p1.x() + corner, p1.y()), QPoint(p2.x() - corner, p2.y())); + QRect right(QPoint(p2.x() - corner, p1.y()), p2); + + if (top.contains(point)) { + // Top + if (left.contains(point)) + return ResizeTopLeft; + if (center.contains(point)) + return ResizeTop; + if (right.contains(point)) + return ResizeTopRight; + } else if (middle.contains(point)) { + // Middle + if (left.contains(point)) + return ResizeLeft; + if (right.contains(point)) + return ResizeRight; + } else if (bottom.contains(point)) { + // Bottom + if (left.contains(point)) + return ResizeBottomLeft; + if (center.contains(point)) + return ResizeBottom; + if (right.contains(point)) + return ResizeBottomRight; + } + + return ResizeNone; +} + +QRect getSubControlRect(const QWasmWindow *window, QWasmCompositor::SubControls subControl) +{ + QWasmCompositor::QWasmTitleBarOptions options = QWasmCompositor::makeTitleBarOptions(window); + + QRect r = QWasmCompositor::titlebarRect(options, subControl); + r.translate(window->window()->frameGeometry().x(), window->window()->frameGeometry().y()); + + return r; +} + +QRect QWasmWindow::maxButtonRect() const +{ + return getSubControlRect(this, QWasmCompositor::SC_TitleBarMaxButton); +} + +QRect QWasmWindow::minButtonRect() const +{ + return getSubControlRect(this, QWasmCompositor::SC_TitleBarMinButton); +} + +QRect QWasmWindow::closeButtonRect() const +{ + return getSubControlRect(this, QWasmCompositor::SC_TitleBarCloseButton); +} + +QRect QWasmWindow::normButtonRect() const +{ + return getSubControlRect(this, QWasmCompositor::SC_TitleBarNormalButton); +} + +QRect QWasmWindow::sysMenuRect() const +{ + return getSubControlRect(this, QWasmCompositor::SC_TitleBarSysMenu); +} + +QRegion QWasmWindow::titleControlRegion() const +{ + QRegion result; + result += closeButtonRect(); + result += minButtonRect(); + result += maxButtonRect(); + result += sysMenuRect(); + + return result; +} + +void QWasmWindow::invalidate() +{ + m_compositor->requestRedraw(); +} + +QWasmCompositor::SubControls QWasmWindow::activeSubControl() const +{ + return m_activeControl; +} + +void QWasmWindow::setWindowState(Qt::WindowStates states) +{ + m_windowState = Qt::WindowNoState; + if (states & Qt::WindowMinimized) + m_windowState = Qt::WindowMinimized; + else if (states & Qt::WindowFullScreen) + m_windowState = Qt::WindowFullScreen; + else if (states & Qt::WindowMaximized) + m_windowState = Qt::WindowMaximized; +} + +QRect QWasmWindow::normalGeometry() const +{ + return m_normalGeometry; +} + +qreal QWasmWindow::devicePixelRatio() const +{ + return screen()->devicePixelRatio(); +} + +void QWasmWindow::requestUpdate() +{ + QPointer windowPointer(window()); + bool registered = QWasmEventDispatcher::registerRequestUpdateCallback([=](){ + if (windowPointer.isNull()) + return; + + deliverUpdateRequest(); + }); + + if (!registered) + QPlatformWindow::requestUpdate(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/wasm/qwasmwindow.h b/src/plugins/platforms/wasm/qwasmwindow.h new file mode 100644 index 00000000000..a0c463e796c --- /dev/null +++ b/src/plugins/platforms/wasm/qwasmwindow.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) 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.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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWASMWINDOW_H +#define QWASMWINDOW_H + +#include "qwasmintegration.h" +#include +#include +#include "qwasmbackingstore.h" +#include "qwasmscreen.h" +#include "qwasmcompositor.h" + +QT_BEGIN_NAMESPACE + +class QWasmCompositor; + +class QWasmWindow : public QPlatformWindow +{ +public: + enum ResizeMode { + ResizeNone, + ResizeTopLeft, + ResizeTop, + ResizeTopRight, + ResizeRight, + ResizeBottomRight, + ResizeBottom, + ResizeBottomLeft, + ResizeLeft + }; + + QWasmWindow(QWindow *w, QWasmCompositor *compositor, QWasmBackingStore *backingStore); + ~QWasmWindow(); + + void initialize() override; + + void setGeometry(const QRect &) override; + void setVisible(bool visible) override; + QMargins frameMargins() const override; + + WId winId() const override; + + void propagateSizeHints() override; + void raise() override; + void lower() override; + QRect normalGeometry() const override; + qreal devicePixelRatio() const override; + void requestUpdate() override; + + QWasmScreen *platformScreen() const; + void setBackingStore(QWasmBackingStore *store) { m_backingStore = store; } + QWasmBackingStore *backingStore() const { return m_backingStore; } + QWindow *window() const { return m_window; } + + void injectMousePressed(const QPoint &local, const QPoint &global, + Qt::MouseButton button, Qt::KeyboardModifiers mods); + void injectMouseReleased(const QPoint &local, const QPoint &global, + Qt::MouseButton button, Qt::KeyboardModifiers mods); + + int titleHeight() const; + int borderWidth() const; + QRegion titleGeometry() const; + QRegion resizeRegion() const; + bool isPointOnTitle(QPoint point) const; + bool isPointOnResizeRegion(QPoint point) const; + ResizeMode resizeModeAtPoint(QPoint point) const; + QRect maxButtonRect() const; + QRect minButtonRect() const; + QRect closeButtonRect() const; + QRect sysMenuRect() const; + QRect normButtonRect() const; + QRegion titleControlRegion() const; + QWasmCompositor::SubControls activeSubControl() const; + + void setWindowState(Qt::WindowStates state) override; + bool setKeyboardGrabEnabled(bool) override { return false; } + bool setMouseGrabEnabled(bool) override { return false; } + +protected: + void invalidate(); + +protected: + friend class QWasmScreen; + + QWindow* m_window = nullptr; + QWasmCompositor *m_compositor = nullptr; + QWasmBackingStore *m_backingStore = nullptr; + QRect m_normalGeometry {0, 0, 0 ,0}; + + Qt::WindowState m_windowState = Qt::WindowNoState; + QWasmCompositor::SubControls m_activeControl = QWasmCompositor::SC_None; + WId m_winid = 0; + bool m_hasTitle = false; + bool m_needsCompositor = false; +}; +QT_END_NAMESPACE +#endif // QWASMWINDOW_H diff --git a/src/plugins/platforms/wasm/wasm.json b/src/plugins/platforms/wasm/wasm.json new file mode 100644 index 00000000000..6e700e06b9d --- /dev/null +++ b/src/plugins/platforms/wasm/wasm.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "wasm" ] +} diff --git a/src/plugins/platforms/wasm/wasm.pro b/src/plugins/platforms/wasm/wasm.pro new file mode 100644 index 00000000000..f1205702ef8 --- /dev/null +++ b/src/plugins/platforms/wasm/wasm.pro @@ -0,0 +1,65 @@ +TARGET = wasm +CONFIG += static plugin +QT += \ + core-private gui-private \ + eventdispatcher_support-private fontdatabase_support-private egl_support-private + +# Avoid X11 header collision, use generic EGL native types +DEFINES += QT_EGL_NO_X11 + +SOURCES = \ + main.cpp \ + qwasmintegration.cpp \ + qwasmwindow.cpp \ + qwasmscreen.cpp \ + qwasmfontdatabase.cpp \ + qwasmeventtranslator.cpp \ + qwasmeventdispatcher.cpp \ + qwasmcompositor.cpp \ + qwasmcursor.cpp \ + qwasmopenglcontext.cpp \ + qwasmtheme.cpp + +HEADERS = \ + qwasmintegration.h \ + qwasmwindow.h \ + qwasmscreen.h \ + qwasmfontdatabase.h \ + qwasmeventtranslator.h \ + qwasmeventdispatcher.h \ + qwasmcompositor.h \ + qwasmstylepixmaps_p.h \ + qwasmcursor.h \ + qwasmopenglcontext.h \ + qwasmtheme.h + +wasmfonts.files = \ + ../../../3rdparty/wasm/Vera.ttf \ + ../../../3rdparty/wasm/DejaVuSans.ttf +wasmfonts.prefix = /fonts +wasmfonts.base = ../../../3rdparty/wasm +RESOURCES += wasmfonts + +qtConfig(opengl) { + SOURCES += qwasmbackingstore.cpp + HEADERS += qwasmbackingstore.h +} +CONFIG += egl + +OTHER_FILES += \ + wasm.json \ + wasm_shell.html \ + qtloader.js + +shell_files.path = $$[QT_INSTALL_PLUGINS]/platforms +shell_files.files = \ + wasm_shell.html \ + qtloader.js \ + qtlogo.svg + +INSTALLS += shell_files + +PLUGIN_TYPE = platforms +PLUGIN_CLASS_NAME = QWasmIntegrationPlugin +!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = - +load(qt_plugin) diff --git a/src/plugins/platforms/wasm/wasm_shell.html b/src/plugins/platforms/wasm/wasm_shell.html new file mode 100644 index 00000000000..67bfcdfbdc2 --- /dev/null +++ b/src/plugins/platforms/wasm/wasm_shell.html @@ -0,0 +1,61 @@ + + + + + + APPNAME + + + +

+
+ + Qt for WebAssembly: APPNAME +
+ +
+
+ + + + + + diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index 9116bf61fe5..6b037726a0a 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -1113,7 +1113,7 @@ Q_AUTOTEST_EXPORT QString qt_tildeExpansion(const QString &path) const QString homePath = QDir::homePath(); #else const QByteArray userName = path.midRef(1, separatorPosition - 1).toLocal8Bit(); -# if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) +# if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_WASM) passwd pw; passwd *tmpPw; char buf[200]; diff --git a/src/widgets/graphicsview/qgraphicsitem_p.h b/src/widgets/graphicsview/qgraphicsitem_p.h index 9fc6c0794a8..d586a225446 100644 --- a/src/widgets/graphicsview/qgraphicsitem_p.h +++ b/src/widgets/graphicsview/qgraphicsitem_p.h @@ -500,7 +500,9 @@ public: quint32 filtersDescendantEvents : 1; quint32 sceneTransformTranslateOnly : 1; quint32 notifyBoundingRectChanged : 1; - +#ifdef Q_OS_WASM + unsigned char :0; //this aligns 64bit field for wasm see QTBUG-65259 +#endif // New 32 bits quint32 notifyInvalidated : 1; quint32 mouseSetsFocus : 1; diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp index 51e78ec7655..ed0fe0ed914 100644 --- a/src/widgets/kernel/qopenglwidget.cpp +++ b/src/widgets/kernel/qopenglwidget.cpp @@ -906,9 +906,19 @@ void QOpenGLWidgetPrivate::invalidateFbo() const int gl_color_attachment0 = 0x8CE0; // GL_COLOR_ATTACHMENT0 const int gl_depth_attachment = 0x8D00; // GL_DEPTH_ATTACHMENT const int gl_stencil_attachment = 0x8D20; // GL_STENCIL_ATTACHMENT +#ifdef Q_OS_WASM + // webgl does not allow separate depth and stencil attachments + // QTBUG-69913 + const int gl_depth_stencil_attachment = 0x821A; // GL_DEPTH_STENCIL_ATTACHMENT + + const GLenum attachments[] = { + gl_color_attachment0, gl_depth_attachment, gl_stencil_attachment, gl_depth_stencil_attachment + }; +#else const GLenum attachments[] = { gl_color_attachment0, gl_depth_attachment, gl_stencil_attachment }; +#endif f->glDiscardFramebufferEXT(GL_FRAMEBUFFER, sizeof attachments / sizeof *attachments, attachments); } else { f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); diff --git a/util/unicode/main.cpp b/util/unicode/main.cpp index 0f3c28137da..0c3c0b2ee14 100644 --- a/util/unicode/main.cpp +++ b/util/unicode/main.cpp @@ -2473,6 +2473,10 @@ static QByteArray createPropertyInfo() out += ", "; out += QByteArray::number( p.lowerCaseDiff ); out += ", "; + out += "#ifdef Q_OS_WASM \n" +// " unsigned char : 0; //wasm 64 packing trick QTBUG-65259\n" + out += "#endif \n" + out += ", "; // " ushort upperCaseSpecial : 1;\n" // " signed short upperCaseDiff : 15;\n" out += QByteArray::number( p.upperCaseSpecial ); @@ -2497,6 +2501,10 @@ static QByteArray createPropertyInfo() // " ushort nfQuickCheck : 8;\n" out += QByteArray::number( p.nfQuickCheck ); out += ", "; + out += "#ifdef Q_OS_WASM \n" +// " unsigned char : 0; //wasm 64 packing trick QTBUG-65259\n" + out += "#endif \n" + out += ", "; // " ushort graphemeBreakClass : 5; /* 5 used */\n" // " ushort wordBreakClass : 5; /* 5 used */\n" // " ushort sentenceBreakClass : 8; /* 4 used */\n"