4#include <qpa/qwindowsysteminterface.h>
5#include <private/qguiapplication_p.h>
6#include <QtCore/qfile.h>
7#include <QtGui/private/qwindow_p.h>
8#include <QtGui/private/qhighdpiscaling_p.h>
9#include <private/qpixmapcache_p.h>
10#include <QtGui/qopenglfunctions.h>
15#if QT_CONFIG(clipboard)
16#include "qwasmclipboard.h"
26#if QT_CONFIG(draganddrop)
34#include <emscripten/val.h>
36#include <QtCore/private/qstdweb_p.h>
37#include <QKeySequence>
47 m_compositor(compositor),
48 m_backingStore(backingStore),
49 m_deadKeySupport(deadKeySupport),
59 m_decoratedWindow.set(
"className",
"qt-decorated-window");
60 m_decoratedWindow[
"style"].set(
"display", std::string(
"none"));
62 m_nonClientArea = std::make_unique<NonClientArea>(
this, m_decoratedWindow);
63 m_nonClientArea->titleBar()->setTitle(window()->title());
74 m_window = *(emscripten::val *)(nativeHandle);
75 m_winId = nativeHandle;
76 m_decoratedWindow.set(
"id",
"qt-window-" + std::to_string(m_winId));
77 m_decoratedWindow.call<
void>(
"appendChild", m_window);
81 m_window.set(
"className",
"qt-window");
82 m_decoratedWindow.call<
void>(
"appendChild", m_window);
84 m_canvas[
"classList"].call<
void>(
"add", emscripten::val(
"qt-window-canvas"));
86#if QT_CONFIG(clipboard)
87 if (QWasmClipboard::shouldInstallWindowEventHandlers()) {
88 m_cutCallback = QWasmEventHandler(m_canvas,
"cut", QWasmClipboard::cut);
89 m_copyCallback = QWasmEventHandler(m_canvas,
"copy", QWasmClipboard::copy);
90 m_pasteCallback = QWasmEventHandler(m_canvas,
"paste", QWasmClipboard::paste);
98 m_focusHelper[
"classList"].call<
void>(
"add", emscripten::val(
"qt-window-focus-helper"));
99 m_focusHelper.set(
"inputMode", std::string(
"none"));
100 m_focusHelper.call<
void>(
"setAttribute", std::string(
"contenteditable"), std::string(
"true"));
101 m_focusHelper[
"style"].set(
"position",
"absolute");
102 m_focusHelper[
"style"].set(
"left", 0);
103 m_focusHelper[
"style"].set(
"top", 0);
104 m_focusHelper[
"style"].set(
"width",
"1px");
105 m_focusHelper[
"style"].set(
"height",
"1px");
106 m_focusHelper[
"style"].set(
"z-index", -2);
107 m_focusHelper[
"style"].set(
"opacity", 0);
108 m_window.call<
void>(
"appendChild", m_focusHelper);
112 m_inputElement[
"classList"].call<
void>(
"add", emscripten::val(
"qt-window-input-element"));
113 m_inputElement.call<
void>(
"setAttribute", std::string(
"contenteditable"), std::string(
"true"));
114 m_inputElement.set(
"type",
"text");
115 m_inputElement[
"style"].set(
"position",
"absolute");
116 m_inputElement[
"style"].set(
"left", 0);
117 m_inputElement[
"style"].set(
"top", 0);
118 m_inputElement[
"style"].set(
"width",
"1px");
119 m_inputElement[
"style"].set(
"height",
"1px");
120 m_inputElement[
"style"].set(
"z-index", -2);
121 m_inputElement[
"style"].set(
"opacity", 0);
122 m_inputElement[
"style"].set(
"display",
"");
123 m_window.call<
void>(
"appendChild", m_inputElement);
126 m_canvas.call<
void>(
"setAttribute", std::string(
"aria-hidden"), std::string(
"true"));
127 m_window.call<
void>(
"appendChild", m_canvas);
129 m_a11yContainer[
"classList"].call<
void>(
"add", emscripten::val(
"qt-window-a11y-container"));
130 m_window.call<
void>(
"appendChild", m_a11yContainer);
132 if (QWasmAccessibility::isEnabled())
135 const bool rendersTo2dContext = w->surfaceType() != QSurface::OpenGLSurface;
136 if (rendersTo2dContext)
137 m_context2d = m_canvas.call<emscripten::val>(
"getContext", emscripten::val(
"2d"));
139 m_winId = WId(&m_window);
140 m_decoratedWindow.set(
"id",
"qt-window-" + std::to_string(m_winId));
141 emscripten::val::module_property(
"specialHTMLTargets").set(canvasSelector(), m_canvas);
143 m_flags = window()->flags();
147 m_transientWindowChangedConnection =
149 window(), &QWindow::transientParentChanged,
150 window(), [
this](QWindow *tp) { onTransientParentChanged(tp); });
152 m_modalityChangedConnection =
154 window(), &QWindow::modalityChanged,
155 window(), [
this](Qt::WindowModality) { onModalityChanged(); });
162 m_pointerDownCallback = QWasmEventHandler(m_window,
"pointerdown",
163 [
this](emscripten::val event){ processPointer(PointerEvent(EventType::PointerDown, event)); }
165 m_pointerMoveCallback = QWasmEventHandler(m_window,
"pointermove",
166 [
this](emscripten::val event){ processPointer(PointerEvent(EventType::PointerMove, event)); }
168 m_pointerUpCallback = QWasmEventHandler(m_window,
"pointerup",
169 [
this](emscripten::val event){ processPointer(PointerEvent(EventType::PointerUp, event)); }
171 m_pointerCancelCallback = QWasmEventHandler(m_window,
"pointercancel",
172 [
this](emscripten::val event){ processPointer(PointerEvent(EventType::PointerCancel, event)); }
174 m_pointerEnterCallback = QWasmEventHandler(m_window,
"pointerenter",
175 [
this](emscripten::val event) {
this->handlePointerEnterLeaveEvent(PointerEvent(EventType::PointerEnter, event)); }
177 m_pointerLeaveCallback = QWasmEventHandler(m_window,
"pointerleave",
178 [
this](emscripten::val event) {
this->handlePointerEnterLeaveEvent(PointerEvent(EventType::PointerLeave, event)); }
181#if QT_CONFIG(draganddrop)
182 m_window.call<
void>(
"setAttribute", emscripten::val(
"draggable"), emscripten::val(
"true"));
183 m_dragStartCallback = QWasmEventHandler(m_window,
"dragstart",
184 [
this](emscripten::val event) {
185 DragEvent dragEvent(EventType::DragStart, event, window());
186 QWasmDrag::instance()->onNativeDragStarted(&dragEvent);
189 m_dragOverCallback = QWasmEventHandler(m_window,
"dragover",
190 [
this](emscripten::val event) {
191 DragEvent dragEvent(EventType::DragOver, event, window());
192 QWasmDrag::instance()->onNativeDragOver(&dragEvent);
195 m_dropCallback = QWasmEventHandler(m_window,
"drop",
196 [
this](emscripten::val event) {
197 DragEvent dragEvent(EventType::Drop, event, window());
198 QWasmDrag::instance()->onNativeDrop(&dragEvent);
201 m_dragEndCallback = QWasmEventHandler(m_window,
"dragend",
202 [
this](emscripten::val event) {
203 DragEvent dragEvent(EventType::DragEnd, event, window());
204 QWasmDrag::instance()->onNativeDragFinished(&dragEvent);
207 m_dragLeaveCallback = QWasmEventHandler(m_window,
"dragleave",
208 [
this](emscripten::val event) {
209 DragEvent dragEvent(EventType::DragLeave, event, window());
210 QWasmDrag::instance()->onNativeDragLeave(&dragEvent);
215 m_wheelEventCallback = QWasmEventHandler(m_window,
"wheel",
216 [
this](emscripten::val event) {
this->handleWheelEvent(event); });
218 m_keyDownCallback = QWasmEventHandler(m_window,
"keydown",
219 [
this](emscripten::val event) {
this->handleKeyEvent(KeyEvent(EventType::KeyDown, event, m_deadKeySupport)); });
220 m_keyUpCallback =QWasmEventHandler(m_window,
"keyup",
221 [
this](emscripten::val event) {
this->handleKeyEvent(KeyEvent(EventType::KeyUp, event, m_deadKeySupport)); });
223 m_inputCallback = QWasmEventHandler(m_window,
"input",
224 [
this](emscripten::val event){ handleInputEvent(event); });
225 m_compositionUpdateCallback = QWasmEventHandler(m_window,
"compositionupdate",
226 [
this](emscripten::val event){ handleCompositionUpdateEvent(event); });
227 m_compositionStartCallback = QWasmEventHandler(m_window,
"compositionstart",
228 [
this](emscripten::val event){ handleCompositionStartEvent(event); });
229 m_compositionEndCallback = QWasmEventHandler(m_window,
"compositionend",
230 [
this](emscripten::val event){ handleCompositionEndEvent(event); });
231 m_beforeInputCallback = QWasmEventHandler(m_window,
"beforeinput",
232 [
this](emscripten::val event){ handleBeforeInputEvent(event); });
239#if QT_CONFIG(accessibility)
240 QWasmAccessibility::onRemoveWindow(window());
242 QObject::disconnect(m_transientWindowChangedConnection);
243 QObject::disconnect(m_modalityChangedConnection);
247 emscripten::val::module_property(
"specialHTMLTargets").delete_(canvasSelector());
248 m_window.call<
void>(
"removeChild", m_canvas);
249 m_window.call<
void>(
"removeChild", m_a11yContainer);
250 m_context2d = emscripten::val::undefined();
251 commitParent(
nullptr);
252 if (m_requestAnimationFrameId > -1)
253 emscripten_cancel_animation_frame(m_requestAnimationFrameId);
259 (QGuiApplication::focusWindow() &&
260 QGuiApplication::focusWindow() != window()))
266 std::map<uint64_t, QWasmWindow *> allWindows;
267 for (
const auto &w : platformScreen()->allWindows()) {
268 if (w->getActiveIndex() > 0)
269 allWindows.insert({w->getActiveIndex(), w});
273 if (getActiveIndex() > 0)
274 allWindows.insert({getActiveIndex(),
this});
276 if (allWindows.size() >= 2) {
277 const auto lastIt =
std::prev(allWindows.end());
278 const auto prevIt =
std::prev(lastIt);
279 const auto lastW = lastIt->second;
280 const auto prevW = prevIt->second;
283 prevW->requestActivateWindow();
289 return window()->requestedFormat();
294 if (!window ||!window->handle())
296 return static_cast<
QWasmWindow *>(window->handle());
309 return window()->flags();
314 return window()->isModal();
319 window()->setWindowState(Qt::WindowNoState);
324 window()->setWindowState(Qt::WindowMaximized);
329 window()->setWindowState(m_state.testFlag(Qt::WindowMaximized) ? Qt::WindowNoState
330 : Qt::WindowMaximized);
341 QGuiApplicationPrivate::instance()->closeAllPopups();
348 return QWindowSystemInterface::handleMouseEvent(
349 window(), QWasmIntegration::getTimestamp(), window()->mapFromGlobal(pointInScreen),
350 pointInScreen, event.mouseButtons, event.mouseButton,
351 MouseEvent::mouseEventTypeFromEventType(event.type, WindowArea::NonClient),
357 auto initialGeometry = QPlatformWindow::initialGeometry(window(),
358 windowGeometry(), defaultWindowSize, defaultWindowSize);
359 m_normalGeometry = initialGeometry;
361 setWindowState(window()->windowStates());
362 setWindowFlags(window()->flags());
363 setWindowTitle(window()->title());
364 setMask(QHighDpi::toNativeLocalRegion(window()->mask(), window()));
366 if (window()->isTopLevel())
367 setWindowIcon(window()->icon());
368 QPlatformWindow::setGeometry(m_normalGeometry);
370#if QT_CONFIG(accessibility)
373 if (window()->isTopLevel())
374 QWasmAccessibility::addAccessibilityEnableButton(window());
380 return static_cast<
QWasmScreen *>(window()->screen()->handle());
385 if (!m_backingStore || !isVisible() || m_context2d.isUndefined())
388 auto image = m_backingStore->getUpdatedWebImage(
this);
389 if (image.isUndefined())
391 m_context2d.call<
void>(
"putImageData", image, emscripten::val(0), emscripten::val(0));
396 m_decoratedWindow[
"style"].set(
"zIndex", std::to_string(z));
401 m_window[
"style"].set(
"cursor", emscripten::val(cssCursorName.constData()));
406 const auto margins = frameMargins();
408 const QRect clientAreaRect = ([
this, &rect, &margins]() {
409 if (m_state.testFlag(Qt::WindowFullScreen))
410 return platformScreen()->geometry();
411 if (m_state.testFlag(Qt::WindowMaximized))
412 return platformScreen()->availableGeometry().marginsRemoved(frameMargins());
414 auto offset = rect.topLeft() - (!parent() ? screen()->geometry().topLeft() : QPoint());
417 auto containerGeometryInViewport =
418 QRectF::fromDOMRect(parentNode()->containerElement().call<emscripten::val>(
419 "getBoundingClientRect"))
422 auto rectInViewport = QRect(containerGeometryInViewport.topLeft() + offset, rect.size());
424 QRect cappedGeometry(rectInViewport);
427 cappedGeometry.moveTop(
428 std::max(std::min(rectInViewport.y(), containerGeometryInViewport.bottom()),
429 containerGeometryInViewport.y() + margins.top()));
431 cappedGeometry.setSize(
432 cappedGeometry.size().expandedTo(windowMinimumSize()).boundedTo(windowMaximumSize()));
433 return QRect(QPoint(rect.x(), rect.y() + cappedGeometry.y() - rectInViewport.y()),
436 m_nonClientArea->onClientAreaWidthChange(clientAreaRect.width());
438 const auto frameRect =
440 .adjusted(-margins.left(), -margins.top(), margins.right(), margins.bottom())
441 .translated(!parent() ? -screen()->geometry().topLeft() : QPoint());
443 m_decoratedWindow[
"style"].set(
"left", std::to_string(frameRect.left()) +
"px");
444 m_decoratedWindow[
"style"].set(
"top", std::to_string(frameRect.top()) +
"px");
445 m_canvas[
"style"].set(
"width", std::to_string(clientAreaRect.width()) +
"px");
446 m_canvas[
"style"].set(
"height", std::to_string(clientAreaRect.height()) +
"px");
447 m_a11yContainer[
"style"].set(
"width", std::to_string(clientAreaRect.width()) +
"px");
448 m_a11yContainer[
"style"].set(
"height", std::to_string(clientAreaRect.height()) +
"px");
451 m_window[
"style"].set(
"width", std::to_string(clientAreaRect.width()) +
"px");
453 QSizeF canvasSize = clientAreaRect.size() * devicePixelRatio();
455 m_canvas.set(
"width", canvasSize.width());
456 m_canvas.set(
"height", canvasSize.height());
458 bool shouldInvalidate =
true;
459 if (!m_state.testFlag(Qt::WindowFullScreen) && !m_state.testFlag(Qt::WindowMaximized)) {
460 shouldInvalidate = m_normalGeometry.size() != clientAreaRect.size();
461 m_normalGeometry = clientAreaRect;
465 if (wasmInput && (QGuiApplication::focusWindow() == window()))
466 wasmInput->updateGeometry();
468 QWindowSystemInterface::handleGeometryChange(window(), clientAreaRect);
469 if (shouldInvalidate)
472 m_compositor->requestUpdateWindow(
this, QRect(QPoint(0, 0), geometry().size()));
478 const bool nowVisible = m_decoratedWindow[
"style"][
"display"].as<std::string>() ==
"block";
479 if (visible == nowVisible)
483 m_decoratedWindow[
"style"].set(
"display", visible ?
"block" :
"none");
484 if (window() == QGuiApplication::focusWindow())
489#if QT_CONFIG(accessibility)
490 QWasmAccessibility::onShowWindow(window());
497 return window()->isVisible();
502 const auto frameRect =
503 QRectF::fromDOMRect(m_decoratedWindow.call<emscripten::val>(
"getBoundingClientRect"));
504 const auto canvasRect =
505 QRectF::fromDOMRect(m_window.call<emscripten::val>(
"getBoundingClientRect"));
506 return QMarginsF(canvasRect.left() - frameRect.left(), canvasRect.top() - frameRect.top(),
507 frameRect.right() - canvasRect.right(),
508 frameRect.bottom() - canvasRect.bottom())
533 m_nonClientArea->propagateSizeHints();
538 m_decoratedWindow[
"style"].set(
"opacity", qBound(0.0, level, 1.0));
543 m_compositor->requestUpdateWindow(
this, QRect(QPoint(0, 0), geometry().size()));
548 dom::syncCSSClassWith(m_decoratedWindow,
"inactive", !active);
553 flags = fixTopLevelWindowFlags(flags);
555 if ((flags.testFlag(Qt::WindowStaysOnTopHint) != m_flags.testFlag(Qt::WindowStaysOnTopHint))
556 || (flags.testFlag(Qt::WindowStaysOnBottomHint)
557 != m_flags.testFlag(Qt::WindowStaysOnBottomHint))
558 || shouldBeAboveTransientParentFlags(flags) != shouldBeAboveTransientParentFlags(m_flags)) {
559 onPositionPreferenceChanged(positionPreferenceFromWindowFlags(flags));
562 dom::syncCSSClassWith(m_decoratedWindow,
"frameless", !hasFrame() || !window()->isTopLevel());
563 dom::syncCSSClassWith(m_decoratedWindow,
"has-border", hasBorder());
564 dom::syncCSSClassWith(m_decoratedWindow,
"has-shadow", hasShadow());
565 dom::syncCSSClassWith(m_decoratedWindow,
"has-title", hasTitleBar());
566 dom::syncCSSClassWith(m_decoratedWindow,
"transparent-for-input",
567 flags.testFlag(Qt::WindowTransparentForInput));
569 m_nonClientArea->titleBar()->setMaximizeVisible(hasMaximizeButton());
570 m_nonClientArea->titleBar()->setCloseVisible(m_flags.testFlag(Qt::WindowCloseButtonHint));
577 newState &= Qt::WindowActive;
579 const Qt::WindowStates oldState = m_state;
581 if (newState.testFlag(Qt::WindowMinimized)) {
582 newState.setFlag(Qt::WindowMinimized,
false);
583 qWarning(
"Qt::WindowMinimized is not implemented in wasm");
584 window()->setWindowStates(newState);
588 if (newState == oldState)
592 m_previousWindowState = oldState;
599 m_nonClientArea->titleBar()->setTitle(title);
604 const auto dpi = screen()->devicePixelRatio();
605 auto pixmap = icon.pixmap(10 * dpi, 10 * dpi);
606 if (pixmap.isNull()) {
607 m_nonClientArea->titleBar()->setIcon(
608 Base64IconStore::get()->getIcon(Base64IconStore::IconType::QtLogo),
"svg+xml");
613 QBuffer buffer(&bytes);
614 pixmap.save(&buffer,
"png");
615 m_nonClientArea->titleBar()->setIcon(bytes.toBase64().toStdString(),
"png");
622 const bool isFullscreen = m_state.testFlag(Qt::WindowFullScreen);
623 const bool isMaximized = m_state.testFlag(Qt::WindowMaximized);
626 else if (isMaximized)
627 newGeom = platformScreen()->availableGeometry().marginsRemoved(frameMargins());
631 dom::syncCSSClassWith(m_decoratedWindow,
"has-border", hasBorder());
632 dom::syncCSSClassWith(m_decoratedWindow,
"maximized", isMaximized);
634 m_nonClientArea->titleBar()->setRestoreVisible(isMaximized);
635 m_nonClientArea->titleBar()->setMaximizeVisible(hasMaximizeButton());
638 QWindowSystemInterface::handleWindowStateChanged(window(), m_state, m_previousWindowState);
642void QWasmWindow::commitParent(QWasmWindowTreeNode *parent)
644 onParentChanged(m_commitedParent, parent, positionPreferenceFromWindowFlags(window()->flags()));
645 m_commitedParent = parent;
650 qCDebug(qLcQpaWasmInputContext) <<
"handleKeyEvent";
652 if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive()) {
653 handleKeyForInputContextEvent(event);
655 if (processKey(event)) {
656 event.webEvent.call<
void>(
"preventDefault");
657 event.webEvent.call<
void>(
"stopPropagation");
664 constexpr bool ProceedToNativeEvent =
false;
667#if QT_CONFIG(clipboard)
668 const auto clipboardResult =
669 QWasmIntegration::get()->getWasmClipboard()->processKeyboard(event);
671 using ProcessKeyboardResult = QWasmClipboard::ProcessKeyboardResult;
672 if (clipboardResult == ProcessKeyboardResult::NativeClipboardEventNeeded)
673 return ProceedToNativeEvent;
676 const auto result = QWindowSystemInterface::handleKeyEvent(
677 0, event.type == EventType::KeyDown ? QEvent::KeyPress : QEvent::KeyRelease, event.key,
678 event.modifiers, event.text, event.autoRepeat);
680#if QT_CONFIG(clipboard)
681 return clipboardResult == ProcessKeyboardResult::NativeClipboardEventAndCopiedDataNeeded
682 ? ProceedToNativeEvent
700 bool useInputContext = [event]() ->
bool {
705 const auto keyString = QString::fromStdString(event[
"key"].as<std::string>());
706 qCDebug(qLcQpaWasmInputContext) <<
"Key callback" << keyString << keyString.size();
709 bool composing = event[
"isComposing"].as<
bool>();
713 bool androidUnidentified = (keyString ==
"Unidentified");
718 bool hasModifiers = event[
"ctrlKey"].as<
bool>()
719 || event[
"altKey"].as<
bool>()
720 || event[
"metaKey"].as<
bool>();
724 bool hasNoncharacterKeyString = keyString.size() != 1;
726 bool overrideCompose = !hasModifiers && !hasNoncharacterKeyString && wasmInput->inputMethodAccepted();
727 return composing || androidUnidentified || overrideCompose;
730 if (!useInputContext) {
731 qCDebug(qLcQpaWasmInputContext) <<
"processKey as KeyEvent";
732 if (processKeyForInputContext(keyEvent))
733 event.call<
void>(
"preventDefault");
734 event.call<
void>(
"stopImmediatePropagation");
740 qCDebug(qLcQpaWasmInputContext) << Q_FUNC_INFO;
743 QKeySequence keySeq(event.modifiers | event.key);
745 if (keySeq == QKeySequence::Paste) {
750 const auto result = QWindowSystemInterface::handleKeyEvent(
751 0, event.type == EventType::KeyDown ? QEvent::KeyPress : QEvent::KeyRelease, event.key,
752 event.modifiers, event.text);
754#if QT_CONFIG(clipboard)
756 if (keySeq == QKeySequence::Copy || keySeq == QKeySequence::Cut)
765 if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive())
766 inputContext->inputCallback(event);
768 m_focusHelper.set(
"innerHTML", std::string());
773 if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive())
774 inputContext->compositionStartCallback(event);
776 m_focusHelper.set(
"innerHTML", std::string());
781 if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive())
782 inputContext->compositionUpdateCallback(event);
784 m_focusHelper.set(
"innerHTML", std::string());
789 if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive())
790 inputContext->compositionEndCallback(event);
792 m_focusHelper.set(
"innerHTML", std::string());
797 qWarning() << Q_FUNC_INFO;
799 if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive())
800 inputContext->beforeInputCallback(event);
807 if (processPointerEnterLeave(event))
808 event.webEvent.call<
void>(
"preventDefault");
816 switch (event
.type) {
820 QWindowSystemInterface::handleEnterEvent(
821 window(), mapFromGlobal(pointInScreen.toPoint()), pointInScreen);
836 switch (event
.type) {
837 case EventType::PointerDown:
838 if (event.isTargetedForQtElement())
839 m_window.call<
void>(
"setPointerCapture", event.pointerId);
841 if ((window()->flags() & Qt::WindowDoesNotAcceptFocus)
842 != Qt::WindowDoesNotAcceptFocus
843 && window()->isTopLevel())
844 window()->requestActivate();
846 case EventType::PointerUp:
847 if (event.isTargetedForQtElement())
848 m_window.call<
void>(
"releasePointerCapture", event.pointerId);
854 const bool eventAccepted = deliverPointerEvent(event);
855 if (!eventAccepted && event.type == EventType::PointerDown)
856 QGuiApplicationPrivate::instance()->closeAllPopups();
859 event.webEvent.call<
void>(
"preventDefault");
860 event.webEvent.call<
void>(
"stopPropagation");
870 const QPointF targetPointClippedToScreen(
871 qBound(geometryF.left(), pointInScreen.x(), geometryF.right()),
872 qBound(geometryF.top(), pointInScreen.y(), geometryF.bottom()));
875 const QEvent::Type eventType =
878 return eventType != QEvent::None
879 && QWindowSystemInterface::handleMouseEvent(
880 window(), QWasmIntegration::getTimestamp(),
881 window()->mapFromGlobal(targetPointClippedToScreen),
882 targetPointClippedToScreen, event.mouseButtons, event.mouseButton,
883 eventType, event.modifiers);
888 switch (event
.type) {
891 pressure = event.pressure;
900 qreal xTilt = qBound(-60.0, event.tiltX, 60.0);
901 qreal yTilt = qBound(-60.0, event.tiltY, 60.0);
903 qreal rotation = event.twist > 180.0 ? 360.0 - event.twist : event.twist;
904 return QWindowSystemInterface::handleTabletEvent(
905 window(), QWasmIntegration::getTimestamp(), platformScreen()->tabletDevice(),
906 window()->mapFromGlobal(targetPointClippedToScreen),
907 targetPointClippedToScreen, event.mouseButtons, pressure, xTilt, yTilt,
908 event.tangentialPressure, rotation, event.modifiers);
911 QWindowSystemInterface::TouchPoint *touchPoint;
913 QPointF pointInTargetWindowCoords =
914 QPointF(window()->mapFromGlobal(targetPointClippedToScreen));
915 QPointF normalPosition(pointInTargetWindowCoords.x() / window()->width(),
916 pointInTargetWindowCoords.y() / window()->height());
918 const auto tp = m_pointerIdToTouchPoints.find(event.pointerId);
919 if (event.pointerType != PointerType::Pen && tp != m_pointerIdToTouchPoints.end()) {
920 touchPoint = &tp.value();
922 touchPoint = &m_pointerIdToTouchPoints
923 .insert(event.pointerId, QWindowSystemInterface::TouchPoint())
931 touchPoint->state = QEventPoint::State::Pressed;
934 const bool stationaryTouchPoint = (normalPosition == touchPoint->normalPosition);
935 touchPoint->normalPosition = normalPosition;
936 touchPoint->area = QRectF(targetPointClippedToScreen, QSizeF(event.width, event.height))
937 .translated(-event.width / 2, -event.height / 2);
938 touchPoint->pressure = event.pressure;
940 switch (event
.type) {
941 case EventType::PointerUp:
942 touchPoint->state = QEventPoint::State::Released;
944 case EventType::PointerMove:
945 touchPoint->state = (stationaryTouchPoint ? QEventPoint::State::Stationary
946 : QEventPoint::State::Updated);
952 QList<QWindowSystemInterface::TouchPoint> touchPointList;
953 touchPointList.reserve(m_pointerIdToTouchPoints.size());
954 std::transform(m_pointerIdToTouchPoints.begin(), m_pointerIdToTouchPoints.end(),
955 std::back_inserter(touchPointList),
956 [](
const QWindowSystemInterface::TouchPoint &val) {
return val; });
958 if (event.type == EventType::PointerUp)
959 m_pointerIdToTouchPoints.remove(event.pointerId);
961 return event.type == EventType::PointerCancel
962 ? QWindowSystemInterface::handleTouchCancelEvent(
963 window(), QWasmIntegration::getTimestamp(), platformScreen()->touchDevice(),
965 : QWindowSystemInterface::handleTouchEvent(
966 window(), QWasmIntegration::getTimestamp(), platformScreen()->touchDevice(),
967 touchPointList, event.modifiers);
973 event.call<
void>(
"preventDefault");
979 const int scrollFactor = -([&event]() {
993 return QWindowSystemInterface::handleWheelEvent(
994 window(), QWasmIntegration::getTimestamp(), window()->mapFromGlobal(pointInScreen),
995 pointInScreen, (event.delta * scrollFactor).toPoint(),
996 (event.delta * scrollFactor).toPoint(), event.modifiers, Qt::NoScrollPhase,
997 Qt::MouseEventNotSynthesized, event.webkitDirectionInvertedFromDevice);
1001Qt::WindowFlags
QWasmWindow::fixTopLevelWindowFlags(Qt::WindowFlags flags)
const
1003 if (!(flags.testFlag(Qt::CustomizeWindowHint))) {
1004 if (flags.testFlag(Qt::Window)) {
1005 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint
1006 |Qt::WindowMaximizeButtonHint|Qt::WindowCloseButtonHint;
1008 if (flags.testFlag(Qt::Dialog) || flags.testFlag(Qt::Tool))
1009 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
1011 if ((flags & Qt::WindowType_Mask) == Qt::SplashScreen)
1012 flags |= Qt::FramelessWindowHint;
1017bool QWasmWindow::shouldBeAboveTransientParentFlags(Qt::WindowFlags flags)
const
1025 if (flags.testFlag(Qt::Tool) ||
1026 flags.testFlag(Qt::SplashScreen) ||
1027 flags.testFlag(Qt::ToolTip) ||
1028 flags.testFlag(Qt::Popup))
1036QWasmWindowStack<>::PositionPreference
QWasmWindow::positionPreferenceFromWindowFlags(Qt::WindowFlags flags)
const
1038 flags = fixTopLevelWindowFlags(flags);
1040 if (flags.testFlag(Qt::WindowStaysOnTopHint))
1041 return QWasmWindowStack<>::PositionPreference::StayOnTop;
1042 if (flags.testFlag(Qt::WindowStaysOnBottomHint))
1043 return QWasmWindowStack<>::PositionPreference::StayOnBottom;
1044 if (shouldBeAboveTransientParentFlags(flags))
1045 return QWasmWindowStack<>::PositionPreference::StayAboveTransientParent;
1046 return QWasmWindowStack<>::PositionPreference::Regular;
1051 return m_normalGeometry;
1056 return screen()->devicePixelRatio();
1066 return !m_flags.testFlag(Qt::FramelessWindowHint);
1071 return hasFrame() && !m_state.testFlag(Qt::WindowFullScreen) && !m_flags.testFlag(Qt::SubWindow)
1072 && !windowIsPopupType(m_flags) && !parent();
1077 return hasBorder() && m_flags.testFlag(Qt::WindowTitleHint);
1082 return hasBorder() && !m_flags.testFlag(Qt::NoDropShadowWindowHint);
1087 return !m_state.testFlag(Qt::WindowMaximized) && m_flags.testFlag(Qt::WindowMaximizeButtonHint);
1090bool QWasmWindow::windowIsPopupType(Qt::WindowFlags flags)
const
1092 if (flags.testFlag(Qt::Tool))
1095 return (flags.testFlag(Qt::Popup));
1100 QWindow *modalWindow;
1101 if (QGuiApplicationPrivate::instance()->isWindowBlocked(window(), &modalWindow)) {
1111 QPlatformWindow::requestActivateWindow();
1116 if (QWasmAccessibility::isEnabled())
1119 m_focusHelper.call<
void>(
"focus");
1124 m_focusHelper.call<
void>(
"setAttribute", std::string(
"aria-hidden"), std::string(
"true"));
1125 m_inputElement.call<
void>(
"setAttribute", std::string(
"aria-hidden"), std::string(
"true"));
1136 switch (event->type()) {
1137 case QEvent::WindowBlocked:
1138 m_decoratedWindow[
"classList"].call<
void>(
"add", emscripten::val(
"blocked"));
1140 case QEvent::WindowUnblocked:;
1141 m_decoratedWindow[
"classList"].call<
void>(
"remove", emscripten::val(
"blocked"));
1144 return QPlatformWindow::windowEvent(event);
1150 if (region.isEmpty()) {
1151 m_decoratedWindow[
"style"].set(
"clipPath", emscripten::val(
""));
1155 std::ostringstream cssClipPath;
1156 cssClipPath <<
"path('";
1157 for (
const auto &rect : region) {
1158 const auto cssRect = rect.adjusted(0, 0, 1, 1);
1159 cssClipPath <<
"M " << cssRect.left() <<
" " << cssRect.top() <<
" ";
1160 cssClipPath <<
"L " << cssRect.right() <<
" " << cssRect.top() <<
" ";
1161 cssClipPath <<
"L " << cssRect.right() <<
" " << cssRect.bottom() <<
" ";
1162 cssClipPath <<
"L " << cssRect.left() <<
" " << cssRect.bottom() <<
" z ";
1164 cssClipPath <<
"')";
1165 m_decoratedWindow[
"style"].set(
"clipPath", emscripten::val(cssClipPath.str()));
1168void QWasmWindow::onTransientParentChanged(QWindow *newTransientParent)
1170 Q_UNUSED(newTransientParent);
1172 const auto positionPreference = positionPreferenceFromWindowFlags(window()->flags());
1173 QWasmWindowTreeNode::onParentChanged(parentNode(),
nullptr, positionPreference);
1174 QWasmWindowTreeNode::onParentChanged(
nullptr, parentNode(), positionPreference);
1179 const auto positionPreference = positionPreferenceFromWindowFlags(window()->flags());
1180 QWasmWindowTreeNode::onParentChanged(parentNode(),
nullptr, positionPreference);
1181 QWasmWindowTreeNode::onParentChanged(
nullptr, parentNode(), positionPreference);
1188 setWindowFlags(window()->flags());
1190 commitParent(parentNode());
1195 return "!qtwindow" + std::to_string(m_winId);
1216 QWasmWindowStack<>::PositionPreference positionPreference)
1219 previous->containerElement().call<
void>(
"removeChild", m_decoratedWindow);
1221 current->containerElement().call<
void>(
"appendChild", m_decoratedWindow);
1222 QWasmWindowTreeNode::onParentChanged(previous, current, positionPreference);
QRect window() const
Returns the window rectangle.
QWasmCompositor(QWasmScreen *screen)
static QWasmIntegration * get()
static void destroyWebGLContext(QPlatformSurface *surface)
emscripten::val element() const
QRect geometry() const override
Reimplement in subclass to return the pixel geometry of the screen.
void setVisible(bool visible) override
Reimplemented in subclasses to show the surface if visible is true, and hide it if visible is false.
qreal devicePixelRatio() const override
Reimplement this function in subclass to return the device pixel ratio for the window.
QRect normalGeometry() const override
Returns the geometry of a window in 'normal' state (neither maximized, fullscreen nor minimized) for ...
QWasmWindow(QWindow *w, QWasmDeadKeySupport *deadKeySupport, QWasmCompositor *compositor, QWasmBackingStore *backingStore, WId nativeHandle)
QSurfaceFormat format() const override
Returns the actual surface format of the window.
void setParent(const QPlatformWindow *window) final
This function is called to enable native child window in QPA.
static QWasmWindow * fromWindow(const QWindow *window)
void raise() override
Reimplement to be able to let Qt raise windows to the top of the desktop.
void setWindowTitle(const QString &title) override
Reimplement to set the window title to title.
void requestActivateWindow() override
Reimplement to let Qt be able to request activation/focus for a window.
WId winId() const override
Reimplement in subclasses to return a handle to the native window.
std::string canvasSelector() const
friend class QWasmCompositor
void onNonClientAreaInteraction()
void setGeometry(const QRect &) override
This function is called by Qt whenever a window is moved or resized using the QWindow API.
bool setMouseGrabEnabled(bool grab) final
bool onNonClientEvent(const PointerEvent &event)
void setWindowCursor(QByteArray cssCursorName)
void setZOrder(int order)
void setMask(const QRegion ®ion) final
Reimplement to be able to let Qt set the mask of a window.
QWasmWindow * transientParent() const
QWasmWindowTreeNode * parentNode() final
void initialize() override
Called as part of QWindow::create(), after constructing the window.
Qt::WindowFlags windowFlags() const
void registerEventHandlers()
void requestUpdate() override
Requests an QEvent::UpdateRequest event.
void lower() override
Reimplement to be able to let Qt lower windows to the bottom of the desktop.
void onParentChanged(QWasmWindowTreeNode *previous, QWasmWindowTreeNode *current, QWasmWindowStack<>::PositionPreference positionPreference) final
void setOpacity(qreal level) override
Reimplement to be able to let Qt set the opacity level of a window.
void onActivationChanged(bool active)
void onAccessibilityEnable()
void setWindowState(Qt::WindowStates state) override
Requests setting the window state of this surface to type.
void setWindowIcon(const QIcon &icon) override
Reimplement to set the window icon to icon.
void propagateSizeHints() override
Reimplement to propagate the size hints of the QWindow.
QMargins frameMargins() const override
QWasmWindow * asWasmWindow() final
bool windowEvent(QEvent *event) final
Reimplement this method to be able to do any platform specific event handling.
QWasmScreen * platformScreen() const
emscripten::val containerElement() final
void setWindowFlags(Qt::WindowFlags flags) override
Requests setting the window flags of this surface to flags.
Q_GUI_EXPORT int qt_defaultDpiX()
QDebug Q_GUI_EXPORT & operator<<(QDebug &s, const QVectorPath &path)