wasm: Improve screen cleanup

Fix the use case where the application recreates the
QApplication object while reusing the html container
element. This would cause an error:

  Uncaught DOMException: Failed to execute 'attachShadow' on
  'Element': Shadow root cannot be created on a host which
  already hosts a shadow tree

It looks like there is no way to remove a previously
attached shadow root, which means we can't return the
container element to its initial state if we attach
to the user-provided container element.

Fix this by introducing an intermediate element which
we can remove() in the QWasmScreen destructor.

Pick-to: 6.5
Change-Id: I929393a498b0440390a3e2c1774a3cac3a5a7e79
Reviewed-by: Piotr Wierciński <piotr.wiercinski@qt.io>
Reviewed-by: Lorn Potter <lorn.potter@gmail.com>
(cherry picked from commit 0e23865c9ed0cf6560df8c7c5fcea6e0eef1160e)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Morten Sørvig 2023-09-12 17:59:09 +02:00 committed by Qt Cherry-pick Bot
parent 1d261f3a54
commit 45cab397e8
2 changed files with 16 additions and 1 deletions

View File

@ -28,6 +28,7 @@ const char *QWasmScreen::m_canvasResizeObserverCallbackContextPropertyName =
QWasmScreen::QWasmScreen(const emscripten::val &containerOrCanvas)
: m_container(containerOrCanvas),
m_intermediateContainer(emscripten::val::undefined()),
m_shadowContainer(emscripten::val::undefined()),
m_compositor(new QWasmCompositor(this)),
m_deadKeySupport(std::make_unique<QWasmDeadKeySupport>())
@ -43,9 +44,20 @@ QWasmScreen::QWasmScreen(const emscripten::val &containerOrCanvas)
m_container["parentNode"].call<void>("replaceChild", container, m_container);
m_container = container;
}
// Create an intermediate container which we can remove during cleanup in ~QWasmScreen().
// This is required due to the attachShadow() call below; there is no corresponding
// "detachShadow()" API to return the container to its previous state.
m_intermediateContainer = document.call<emscripten::val>("createElement", emscripten::val("div"));
m_intermediateContainer.set("id", std::string("qt-shadow-container"));
emscripten::val intermediateContainerStyle = m_intermediateContainer["style"];
intermediateContainerStyle.set("width", std::string("100%"));
intermediateContainerStyle.set("height", std::string("100%"));
m_container.call<void>("appendChild", m_intermediateContainer);
auto shadowOptions = emscripten::val::object();
shadowOptions.set("mode", "open");
auto shadow = m_container.call<emscripten::val>("attachShadow", shadowOptions);
auto shadow = m_intermediateContainer.call<emscripten::val>("attachShadow", shadowOptions);
m_shadowContainer = document.call<emscripten::val>("createElement", emscripten::val("div"));
@ -86,6 +98,8 @@ QWasmScreen::QWasmScreen(const emscripten::val &containerOrCanvas)
QWasmScreen::~QWasmScreen()
{
m_intermediateContainer.call<void>("remove");
emscripten::val::module_property("specialHTMLTargets")
.set(eventTargetId().toStdString(), emscripten::val::undefined());

View File

@ -66,6 +66,7 @@ public slots:
private:
emscripten::val m_container;
emscripten::val m_intermediateContainer;
emscripten::val m_shadowContainer;
std::unique_ptr<QWasmCompositor> m_compositor;
std::unique_ptr<QPointingDevice> m_touchDevice;