10#if QT_CONFIG(clipboard)
11#include "qwasmclipboard.h"
20#if QT_CONFIG(draganddrop)
24#include <qpa/qplatformwindow.h>
25#include <QtGui/qscreen.h>
26#include <qpa/qwindowsysteminterface.h>
27#include <QtCore/qcoreapplication.h>
28#include <qpa/qplatforminputcontextfactory_p.h>
29#include <qpa/qwindowsysteminterface_p.h>
30#include "private/qwasmsuspendresumecontrol_p.h"
32#include <emscripten/bind.h>
33#include <emscripten/val.h>
37#if QT_CONFIG(draganddrop)
38#include <private/qsimpledrag_p.h>
47using namespace Qt::StringLiterals;
87 function(
"qtSetContainerElements", &setContainerElements);
99 : m_suspendResume(std::make_shared<QWasmSuspendResumeControl>())
101 , m_desktopServices(
nullptr)
102#if QT_CONFIG(clipboard)
103 , m_clipboard(
new QWasmClipboard)
105#if QT_CONFIG(accessibility)
106 , m_accessibility(
new QWasmAccessibility)
114 touchPoints = emscripten::val::global(
"navigator")[
"maxTouchPoints"].as<
int>();
115 QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(
false);
121 emscripten::val filtered = emscripten::val::array();
122 emscripten::val qtContainerElements = val::module_property(
"qtContainerElements");
123 if (qtContainerElements.isArray()) {
124 for (
int i = 0; i < qtContainerElements[
"length"].as<
int>(); ++i) {
125 emscripten::val element = qtContainerElements[i].as<emscripten::val>();
126 if (element.isNull() || element.isUndefined())
127 qWarning() <<
"Skipping null or undefined element in qtContainerElements";
129 filtered.call<
void>(
"push", element);
133 qWarning() <<
"The qtContainerElements module property was not set or is invalid. "
134 "Proceeding with no screens.";
139 emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW,
nullptr, EM_TRUE,
140 [](
int,
const EmscriptenUiEvent *,
void *) -> EM_BOOL {
145 if (QWasmIntegration *integration = QWasmIntegration::get())
146 integration->resizeAllScreens();
151 emscripten::val visualViewport = emscripten::val::global(
"window")[
"visualViewport"];
152 if (!visualViewport.isUndefined()) {
153 visualViewport.call<
void>(
"addEventListener", val(
"resize"),
154 val::module_property(
"qtResizeAllScreens"));
156#if QT_CONFIG(draganddrop)
157 m_drag = std::make_unique<QWasmDrag>();
164 emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW,
nullptr, EM_TRUE,
nullptr);
165 emscripten::val visualViewport = emscripten::val::global(
"window")[
"visualViewport"];
166 if (!visualViewport.isUndefined()) {
167 visualViewport.call<
void>(
"removeEventListener", val(
"resize"),
168 val::module_property(
"qtResizeAllScreens"));
172 delete m_desktopServices;
173#if QT_CONFIG(accessibility)
174 delete m_accessibility;
177 for (
const auto &elementAndScreen : m_screens)
178 elementAndScreen.wasmScreen->deleteScreen();
182 s_instance =
nullptr;
188 case ThreadedPixmaps:
return true;
189 case OpenGL:
return true;
190 case ThreadedOpenGL:
return false;
191 case MultipleWindows:
return true;
192 case WindowManagement:
return true;
193 case ForeignWindows:
return true;
194 case OpenGLOnRasterSurface:
return true;
195 case OffscreenSurface:
return true;
196 default:
return QPlatformIntegration::hasCapability(cap);
202 auto *wasmScreen = QWasmScreen::get(window->screen());
204 return new QWasmWindow(window, compositor,
205 m_backingStores.value(window), nativeHandle);
210 return createWindow(window, 0);
215 return createWindow(window, nativeHandle);
220 QWasmCompositor *compositor = QWasmScreen::get(window->screen())->compositor();
222 m_backingStores.insert(window, backingStore);
228 m_backingStores.remove(window);
235 for (
const auto &elementAndScreen : m_screens) {
236 elementAndScreen.wasmScreen->compositor()->requestUpdate();
250 auto icStrs = QPlatformInputContextFactory::requested();
251 if (!icStrs.isEmpty()) {
252 m_inputContext.reset(QPlatformInputContextFactory::create(icStrs));
253 m_wasmInputContext =
nullptr;
255 m_inputContext.reset(
new QWasmInputContext());
256 m_wasmInputContext =
static_cast<QWasmInputContext *>(m_inputContext.data());
262 return m_inputContext.data();
265QPlatformOffscreenSurface *
QWasmIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface)
const
267 return new QWasmOffscreenSurface
(surface
);
272 if (m_fontDb ==
nullptr)
273 m_fontDb =
new QWasmFontDatabase;
280 return new QWasmEventDispatcher(m_suspendResume);
286 case ShowIsFullScreen:
288 case UnderlineShortcut:
291 return QPlatformIntegration::styleHint(hint);
298 if (flags.testFlag(Qt::Dialog) || flags.testFlag(Qt::Popup))
299 return Qt::WindowNoState;
301 return QPlatformIntegration::defaultWindowState(flags);
306 return QStringList() <<
"webassembly"_L1;
311 if (name ==
"webassembly"_L1)
313 return QPlatformIntegration::createPlatformTheme(name);
318 if (m_desktopServices ==
nullptr)
319 m_desktopServices =
new QWasmServices();
320 return m_desktopServices;
323#if QT_CONFIG(clipboard)
324QPlatformClipboard* QWasmIntegration::clipboard()
const
330#ifndef QT_NO_ACCESSIBILITY
333 return m_accessibility;
339 const auto *primaryScreenBefore = m_screens.isEmpty() ?
nullptr : m_screens[0].wasmScreen;
340 QList<ScreenMapping> newScreens;
342 QList<QWasmScreen *> screensToDelete;
343 std::transform(m_screens.begin(), m_screens.end(), std::back_inserter(screensToDelete),
344 [](
const ScreenMapping &mapping) {
return mapping.wasmScreen; });
346 for (
int i = 0; i < elementArray[
"length"].as<
int>(); ++i) {
347 const auto element = elementArray[i];
348 const auto it = std::find_if(
349 m_screens.begin(), m_screens.end(),
350 [&element](
const ScreenMapping &screen) {
return screen.emscriptenVal == element; });
352 if (it != m_screens.end()) {
353 screen = it->wasmScreen;
354 screensToDelete.erase(std::remove_if(screensToDelete.begin(), screensToDelete.end(),
355 [screen](
const QWasmScreen *removedScreen) {
356 return removedScreen == screen;
358 screensToDelete.end());
361 QWindowSystemInterface::handleScreenAdded(screen);
363 newScreens.push_back({element, screen});
366 std::for_each(screensToDelete.begin(), screensToDelete.end(),
367 [](QWasmScreen *removed) { removed->deleteScreen(); });
369 m_screens = newScreens;
370 auto *primaryScreenAfter = m_screens.isEmpty() ?
nullptr : m_screens[0].wasmScreen;
371 if (primaryScreenAfter && primaryScreenAfter != primaryScreenBefore)
372 QWindowSystemInterface::handlePrimaryScreenChanged(primaryScreenAfter);
377 Q_ASSERT_X(m_screens.end()
378 == std::find_if(m_screens.begin(), m_screens.end(),
379 [&element](
const ScreenMapping &screen) {
380 return screen.emscriptenVal == element;
382 Q_FUNC_INFO,
"Double-add of an element");
385 QWindowSystemInterface::handleScreenAdded(screen);
386 m_screens.push_back({element, screen});
391 const auto *primaryScreenBefore = m_screens.isEmpty() ?
nullptr : m_screens[0].wasmScreen;
394 std::find_if(m_screens.begin(), m_screens.end(),
395 [&element](
const ScreenMapping &screen) {
return screen.emscriptenVal == element; });
396 if (it == m_screens.end()) {
397 qWarning() <<
"Attempt to remove a nonexistent screen.";
404 m_screens.erase(std::remove_if(m_screens.begin(), m_screens.end(),
405 [removedScreen](
const ScreenMapping &mapping) {
406 return removedScreen == mapping.wasmScreen;
409 auto *primaryScreenAfter = m_screens.isEmpty() ?
nullptr : m_screens[0].wasmScreen;
410 if (primaryScreenAfter && primaryScreenAfter != primaryScreenBefore)
411 QWindowSystemInterface::handlePrimaryScreenChanged(primaryScreenAfter);
416 auto it = std::find_if(m_screens.begin(), m_screens.end(),
417 [&] (
const ScreenMapping &candidate) {
return candidate.emscriptenVal.equals(element); });
418 if (it == m_screens.end()) {
419 qWarning() <<
"Attempting to resize non-existing screen for element"
420 << QString::fromEcmaString(element[
"id"]);
423 it->wasmScreen->updateQScreenSize();
428 emscripten::val dpi = emscripten::val::module_property(
"qtFontDpi");
429 if (dpi.isUndefined())
431 qreal dpiValue = dpi.as<qreal>();
432 for (
const auto &elementAndScreen : m_screens)
433 QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(elementAndScreen.wasmScreen->screen(), dpiValue, dpiValue);
438 for (
const auto &elementAndScreen : m_screens)
439 elementAndScreen.wasmScreen->updateQScreenSize();
444 m_fontDb->populateLocalFontFamilies(families);
449 return emscripten_performance_now();
452#if QT_CONFIG(draganddrop)
453QPlatformDrag *QWasmIntegration::drag()
const
static bool releaseRequestUpdateHold()
QWasmCompositor(QWasmScreen *screen)
QPlatformInputContext * inputContext() const override
Returns the platforms input context.
void setContainerElements(emscripten::val elementArray)
static QWasmIntegration * get()
Qt::WindowState defaultWindowState(Qt::WindowFlags flags) const override
QPlatformFontDatabase * fontDatabase() const override
Accessor for the platform integration's fontdatabase.
void addContainerElement(emscripten::val elementArray)
void initialize() override
Performs initialization steps that depend on having an event dispatcher available.
void removeContainerElement(emscripten::val elementArray)
QAbstractEventDispatcher * createEventDispatcher() const override
Factory function for the GUI event dispatcher.
QStringList themeNames() const override
void releaseRequesetUpdateHold()
void loadLocalFontFamilies(emscripten::val families)
QPlatformOpenGLContext * createPlatformOpenGLContext(QOpenGLContext *context) const override
Factory function for QPlatformOpenGLContext.
void removeBackingStore(QWindow *window)
QPlatformBackingStore * createPlatformBackingStore(QWindow *window) const override
Factory function for QPlatformBackingStore.
QPlatformServices * services() const override
QPlatformWindow * createForeignWindow(QWindow *window, WId nativeHandle) const override
QPlatformTheme * createPlatformTheme(const QString &name) const override
void resizeScreen(const emscripten::val &canvas)
QVariant styleHint(QPlatformIntegration::StyleHint hint) const override
bool hasCapability(QPlatformIntegration::Capability cap) const override
QPlatformWindow * createPlatformWindow(QWindow *window) const override
Factory function for QPlatformWindow.
QPlatformAccessibility * accessibility() const override
QWasmOffscreenSurface(QOffscreenSurface *offscreenSurface)
QWasmOpenGLContext(QOpenGLContext *context)
friend class QWasmCompositor
Combined button and popup list for selecting options.
EMSCRIPTEN_BINDINGS(qtQWasmIntegraton)
static void addContainerElement(emscripten::val element)
static void removeContainerElement(emscripten::val element)
QT_BEGIN_NAMESPACE void qt_set_sequence_auto_mnemonic(bool)
static void loadLocalFontFamilies(emscripten::val event)
static void resizeAllScreens(emscripten::val event)
static void resizeContainerElement(emscripten::val element)
static void setContainerElements(emscripten::val elementArray)
static void qtUpdateDpi()