qt6-bb10/src/plugins/platforms/wasm/qwasmintegration.cpp

220 lines
6.6 KiB
C++

/****************************************************************************
**
** 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 <QtEventDispatcherSupport/private/qgenericunixeventdispatcher_p.h>
#endif
#include <qpa/qplatformwindow.h>
#include <QtGui/qscreen.h>
#include <qpa/qwindowsysteminterface.h>
#include <QtCore/qcoreapplication.h>
#include <emscripten/bind.h>
// 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();
QWindowSystemInterface::handleScreenAdded(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;
QWindowSystemInterface::handleScreenRemoved(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 false; // to enable this you need to fix qopenglwidget and quickwidget for wasm
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