5#include <qpa/qwindowsysteminterface.h>
6#include <private/qguiapplication_p.h>
7#include <QtCore/qfile.h>
8#include <QtGui/private/qwindow_p.h>
9#include <QtGui/private/qhighdpiscaling_p.h>
10#include <private/qpixmapcache_p.h>
11#include <QtGui/qopenglfunctions.h>
16#if QT_CONFIG(clipboard)
17#include "qwasmclipboard.h"
27#if QT_CONFIG(draganddrop)
35#include <emscripten/val.h>
37#include <QtCore/private/qstdweb_p.h>
47 m_compositor(compositor),
48 m_backingStore(backingStore),
58 m_decoratedWindow.set(
"className",
"qt-decorated-window");
59 m_decoratedWindow[
"style"].set(
"display", std::string(
"none"));
61 m_nonClientArea = std::make_unique<NonClientArea>(
this, m_decoratedWindow);
62 m_nonClientArea->titleBar()->setTitle(window()->title());
73 m_window = *(emscripten::val *)(nativeHandle);
74 m_winId = nativeHandle;
75 m_decoratedWindow.set(
"id",
"qt-window-" + std::to_string(m_winId));
76 m_decoratedWindow.call<
void>(
"appendChild", m_window);
80 m_window.set(
"className",
"qt-window");
81 m_decoratedWindow.call<
void>(
"appendChild", m_window);
83 m_canvas[
"classList"].call<
void>(
"add", emscripten::val(
"qt-window-canvas"));
85#if QT_CONFIG(clipboard)
86 if (QWasmClipboard::shouldInstallWindowEventHandlers()) {
87 m_cutCallback = QWasmEventHandler(m_canvas,
"cut", QWasmClipboard::cut);
88 m_copyCallback = QWasmEventHandler(m_canvas,
"copy", QWasmClipboard::copy);
89 m_pasteCallback = QWasmEventHandler(m_canvas,
"paste", QWasmClipboard::paste);
97 m_focusHelper[
"classList"].call<
void>(
"add", emscripten::val(
"qt-window-focus-helper"));
98 m_focusHelper.set(
"inputMode", std::string(
"none"));
99 m_focusHelper.call<
void>(
"setAttribute", std::string(
"contenteditable"), std::string(
"true"));
100 m_focusHelper[
"style"].set(
"position",
"absolute");
101 m_focusHelper[
"style"].set(
"left", 0);
102 m_focusHelper[
"style"].set(
"top", 0);
103 m_focusHelper[
"style"].set(
"width",
"1px");
104 m_focusHelper[
"style"].set(
"height",
"1px");
105 m_focusHelper[
"style"].set(
"z-index", -2);
106 m_focusHelper[
"style"].set(
"opacity", 0);
107 m_window.call<
void>(
"appendChild", m_focusHelper);
111 m_inputElement[
"classList"].call<
void>(
"add", emscripten::val(
"qt-window-input-element"));
112 m_inputElement.call<
void>(
"setAttribute", std::string(
"contenteditable"), std::string(
"true"));
113 m_inputElement.set(
"type",
"text");
114 m_inputElement[
"style"].set(
"position",
"absolute");
115 m_inputElement[
"style"].set(
"left", 0);
116 m_inputElement[
"style"].set(
"top", 0);
117 m_inputElement[
"style"].set(
"width",
"1px");
118 m_inputElement[
"style"].set(
"height",
"1px");
119 m_inputElement[
"style"].set(
"z-index", -2);
120 m_inputElement[
"style"].set(
"opacity", 0);
121 m_inputElement[
"style"].set(
"display",
"");
122 m_window.call<
void>(
"appendChild", m_inputElement);
125 m_canvas.call<
void>(
"setAttribute", std::string(
"aria-hidden"), std::string(
"true"));
126 m_canvas[
"style"].set(
"pointerEvents",
"none");
128 m_window.call<
void>(
"appendChild", m_canvas);
130 m_a11yContainer[
"classList"].call<
void>(
"add", emscripten::val(
"qt-window-a11y-container"));
131 m_window.call<
void>(
"appendChild", m_a11yContainer);
133 if (QWasmAccessibility::isEnabled())
136 const bool rendersTo2dContext = w->surfaceType() != QSurface::OpenGLSurface;
137 if (rendersTo2dContext)
138 m_context2d = m_canvas.call<emscripten::val>(
"getContext", emscripten::val(
"2d"));
140 m_winId = WId(&m_window);
141 m_decoratedWindow.set(
"id",
"qt-window-" + std::to_string(m_winId));
142 emscripten::val::module_property(
"specialHTMLTargets").set(canvasSelector(), m_canvas);
144 m_flags = window()->flags();
148 m_transientWindowChangedConnection =
150 window(), &QWindow::transientParentChanged,
151 window(), [
this](QWindow *tp) { onTransientParentChanged(tp); });
153 m_modalityChangedConnection =
155 window(), &QWindow::modalityChanged,
156 window(), [
this](Qt::WindowModality) { onModalityChanged(); });
163 m_pointerDownCallback = QWasmEventHandler(m_window,
"pointerdown",
164 [
this](emscripten::val event){ processPointer(PointerEvent(EventType::PointerDown, event)); }
166 m_pointerMoveCallback = QWasmEventHandler(m_window,
"pointermove",
167 [
this](emscripten::val event){ processPointer(PointerEvent(EventType::PointerMove, event)); }
169 m_pointerUpCallback = QWasmEventHandler(m_window,
"pointerup",
170 [
this](emscripten::val event){ processPointer(PointerEvent(EventType::PointerUp, event)); }
172 m_pointerCancelCallback = QWasmEventHandler(m_window,
"pointercancel",
173 [
this](emscripten::val event){ processPointer(PointerEvent(EventType::PointerCancel, event)); }
175 m_pointerEnterCallback = QWasmEventHandler(m_window,
"pointerenter",
176 [
this](emscripten::val event) {
this->handlePointerEnterLeaveEvent(PointerEvent(EventType::PointerEnter, event)); }
178 m_pointerLeaveCallback = QWasmEventHandler(m_window,
"pointerleave",
179 [
this](emscripten::val event) {
this->handlePointerEnterLeaveEvent(PointerEvent(EventType::PointerLeave, event)); }
182#if QT_CONFIG(draganddrop)
183 m_window.call<
void>(
"setAttribute", emscripten::val(
"draggable"), emscripten::val(
"true"));
184 m_dragStartCallback = QWasmEventHandler(m_window,
"dragstart",
185 [
this](emscripten::val event) {
186 DragEvent dragEvent(EventType::DragStart, event, window());
187 QWasmDrag::instance()->onNativeDragStarted(&dragEvent);
190 m_dragOverCallback = QWasmEventHandler(m_window,
"dragover",
191 [
this](emscripten::val event) {
192 DragEvent dragEvent(EventType::DragOver, event, window());
193 QWasmDrag::instance()->onNativeDragOver(&dragEvent);
196 m_dropCallback = QWasmEventHandler(m_window,
"drop",
197 [
this](emscripten::val event) {
198 DragEvent dragEvent(EventType::Drop, event, window());
199 QWasmDrag::instance()->onNativeDrop(&dragEvent);
202 m_dragEndCallback = QWasmEventHandler(m_window,
"dragend",
203 [
this](emscripten::val event) {
204 DragEvent dragEvent(EventType::DragEnd, event, window());
205 QWasmDrag::instance()->onNativeDragFinished(&dragEvent, platformScreen());
206 releasePointerGrab(dragEvent);
209 m_dragEnterCallback = QWasmEventHandler(m_window,
"dragenter",
210 [
this](emscripten::val event) {
211 DragEvent dragEvent(EventType::DragEnter, event, window());
212 QWasmDrag::instance()->onNativeDragEnter(&dragEvent);
215 m_dragLeaveCallback = QWasmEventHandler(m_window,
"dragleave",
216 [
this](emscripten::val event) {
217 DragEvent dragEvent(EventType::DragLeave, event, window());
218 QWasmDrag::instance()->onNativeDragLeave(&dragEvent);
223 m_wheelEventCallback = QWasmEventHandler(m_window,
"wheel",
224 [
this](emscripten::val event) {
this->handleWheelEvent(event); });
226 m_keyDownCallback = QWasmEventHandler(m_window,
"keydown",
227 [
this](emscripten::val event) {
this->handleKeyEvent(KeyEvent(EventType::KeyDown, event)); });
228 m_keyUpCallback =QWasmEventHandler(m_window,
"keyup",
229 [
this](emscripten::val event) {
this->handleKeyEvent(KeyEvent(EventType::KeyUp, event)); });
231 m_inputCallback = QWasmEventHandler(m_window,
"input",
232 [
this](emscripten::val event){ handleInputEvent(event); });
233 m_compositionUpdateCallback = QWasmEventHandler(m_window,
"compositionupdate",
234 [
this](emscripten::val event){ handleCompositionUpdateEvent(event); });
235 m_compositionStartCallback = QWasmEventHandler(m_window,
"compositionstart",
236 [
this](emscripten::val event){ handleCompositionStartEvent(event); });
237 m_compositionEndCallback = QWasmEventHandler(m_window,
"compositionend",
238 [
this](emscripten::val event){ handleCompositionEndEvent(event); });
239 m_beforeInputCallback = QWasmEventHandler(m_window,
"beforeinput",
240 [
this](emscripten::val event){ handleBeforeInputEvent(event); });
247#if QT_CONFIG(accessibility)
248 QWasmAccessibility::onRemoveWindow(window());
250 QObject::disconnect(m_transientWindowChangedConnection);
251 QObject::disconnect(m_modalityChangedConnection);
255 emscripten::val::module_property(
"specialHTMLTargets").delete_(canvasSelector());
256 m_window.call<
void>(
"removeChild", m_canvas);
257 m_window.call<
void>(
"removeChild", m_a11yContainer);
258 m_context2d = emscripten::val::undefined();
259 commitParent(
nullptr);
260 if (m_requestAnimationFrameId > -1)
261 emscripten_cancel_animation_frame(m_requestAnimationFrameId);
267 (QGuiApplication::focusWindow() &&
268 QGuiApplication::focusWindow() != window()))
274 std::map<uint64_t, QWasmWindow *> allWindows;
275 for (
const auto &w : platformScreen()->allWindows()) {
276 if (w->getActiveIndex() > 0)
277 allWindows.insert({w->getActiveIndex(), w});
281 if (getActiveIndex() > 0)
282 allWindows.insert({getActiveIndex(),
this});
284 if (allWindows.size() >= 2) {
285 const auto lastIt =
std::prev(allWindows.end());
286 const auto prevIt =
std::prev(lastIt);
287 const auto lastW = lastIt->second;
288 const auto prevW = prevIt->second;
291 prevW->requestActivateWindow();
297 return window()->requestedFormat();
302 if (!window ||!window->handle())
304 return static_cast<
QWasmWindow *>(window->handle());
317 return window()->flags();
322 return window()->isModal();
327 window()->setWindowState(Qt::WindowNoState);
332 window()->setWindowState(Qt::WindowMaximized);
337 window()->setWindowState(m_state.testFlag(Qt::WindowMaximized) ? Qt::WindowNoState
338 : Qt::WindowMaximized);
349 QGuiApplicationPrivate::instance()->closeAllPopups();
356 return QWindowSystemInterface::handleMouseEvent(
357 window(), QWasmIntegration::getTimestamp(), window()->mapFromGlobal(pointInScreen),
358 pointInScreen, event.mouseButtons, event.mouseButton,
359 MouseEvent::mouseEventTypeFromEventType(event.type, WindowArea::NonClient),
365 auto initialGeometry = QPlatformWindow::initialGeometry(window(),
366 windowGeometry(), defaultWindowSize, defaultWindowSize);
367 m_normalGeometry = initialGeometry;
369 setWindowState(window()->windowStates());
370 setWindowFlags(window()->flags());
371 setWindowTitle(window()->title());
372 setMask(QHighDpi::toNativeLocalRegion(window()->mask(), window()));
374 if (window()->isTopLevel())
375 setWindowIcon(window()->icon());
376 QPlatformWindow::setGeometry(m_normalGeometry);
378#if QT_CONFIG(accessibility)
381 if (window()->isTopLevel())
382 QWasmAccessibility::addAccessibilityEnableButton(window());
388 return static_cast<
QWasmScreen *>(window()->screen()->handle());
393 if (!m_backingStore || !isVisible() || m_context2d.isUndefined())
396 auto image = m_backingStore->getUpdatedWebImage(
this);
397 if (image.isUndefined())
399 m_context2d.call<
void>(
"putImageData", image, emscripten::val(0), emscripten::val(0));
404 m_decoratedWindow[
"style"].set(
"zIndex", std::to_string(z));
409 m_window[
"style"].set(
"cursor", emscripten::val(cssCursorName.constData()));
414 const auto margins = frameMargins();
416 const QRect clientAreaRect = ([
this, &rect, &margins]() {
417 if (m_state.testFlag(Qt::WindowFullScreen))
418 return platformScreen()->geometry();
419 if (m_state.testFlag(Qt::WindowMaximized))
420 return platformScreen()->availableGeometry().marginsRemoved(frameMargins());
422 auto offset = rect.topLeft() - (!parent() ? screen()->geometry().topLeft() : QPoint());
425 auto containerGeometryInViewport =
426 QRectF::fromDOMRect(parentNode()->containerElement().call<emscripten::val>(
427 "getBoundingClientRect"))
430 auto rectInViewport = QRect(containerGeometryInViewport.topLeft() + offset, rect.size());
432 QRect cappedGeometry(rectInViewport);
435 cappedGeometry.moveTop(
436 std::max(std::min(rectInViewport.y(), containerGeometryInViewport.bottom()),
437 containerGeometryInViewport.y() + margins.top()));
439 cappedGeometry.setSize(
440 cappedGeometry.size().expandedTo(windowMinimumSize()).boundedTo(windowMaximumSize()));
441 return QRect(QPoint(rect.x(), rect.y() + cappedGeometry.y() - rectInViewport.y()),
444 m_nonClientArea->onClientAreaWidthChange(clientAreaRect.width());
446 const auto frameRect =
448 .adjusted(-margins.left(), -margins.top(), margins.right(), margins.bottom())
449 .translated(!parent() ? -screen()->geometry().topLeft() : QPoint());
451 m_decoratedWindow[
"style"].set(
"left", std::to_string(frameRect.left()) +
"px");
452 m_decoratedWindow[
"style"].set(
"top", std::to_string(frameRect.top()) +
"px");
453 m_canvas[
"style"].set(
"width", std::to_string(clientAreaRect.width()) +
"px");
454 m_canvas[
"style"].set(
"height", std::to_string(clientAreaRect.height()) +
"px");
455 m_a11yContainer[
"style"].set(
"width", std::to_string(clientAreaRect.width()) +
"px");
456 m_a11yContainer[
"style"].set(
"height", std::to_string(clientAreaRect.height()) +
"px");
459 m_window[
"style"].set(
"width", std::to_string(clientAreaRect.width()) +
"px");
460 m_window[
"style"].set(
"height", std::to_string(clientAreaRect.height()) +
"px");
462 QSizeF canvasSize = clientAreaRect.size() * devicePixelRatio();
464 m_canvas.set(
"width", canvasSize.width());
465 m_canvas.set(
"height", canvasSize.height());
467 bool shouldInvalidate =
true;
468 if (!m_state.testFlag(Qt::WindowFullScreen) && !m_state.testFlag(Qt::WindowMaximized)) {
469 shouldInvalidate = m_normalGeometry.size() != clientAreaRect.size();
470 m_normalGeometry = clientAreaRect;
474 if (wasmInput && (QGuiApplication::focusWindow() == window()))
475 wasmInput->updateGeometry();
477 QWindowSystemInterface::handleGeometryChange(window(), clientAreaRect);
478 if (shouldInvalidate)
481 m_compositor->requestUpdateWindow(
this, QRect(QPoint(0, 0), geometry().size()));
487 const bool nowVisible = m_decoratedWindow[
"style"][
"display"].as<std::string>() ==
"block";
488 if (visible == nowVisible)
492 m_decoratedWindow[
"style"].set(
"display", visible ?
"block" :
"none");
493 if (window() == QGuiApplication::focusWindow())
498#if QT_CONFIG(accessibility)
499 QWasmAccessibility::onShowWindow(window());
506 return window()->isVisible();
511 const auto frameRect =
512 QRectF::fromDOMRect(m_decoratedWindow.call<emscripten::val>(
"getBoundingClientRect"));
513 const auto canvasRect =
514 QRectF::fromDOMRect(m_window.call<emscripten::val>(
"getBoundingClientRect"));
515 return QMarginsF(canvasRect.left() - frameRect.left(), canvasRect.top() - frameRect.top(),
516 frameRect.right() - canvasRect.right(),
517 frameRect.bottom() - canvasRect.bottom())
542 m_nonClientArea->propagateSizeHints();
547 m_decoratedWindow[
"style"].set(
"opacity", qBound(0.0, level, 1.0));
552 m_compositor->requestUpdateWindow(
this, QRect(QPoint(0, 0), geometry().size()));
557 dom::syncCSSClassWith(m_decoratedWindow,
"inactive", !active);
562 flags = fixTopLevelWindowFlags(flags);
567 if (
std::find(childStack().begin(), childStack().end(),
this) != childStack().end()) {
568 if ((flags.testFlag(Qt::WindowStaysOnTopHint) != m_flags.testFlag(Qt::WindowStaysOnTopHint))
569 || (flags.testFlag(Qt::WindowStaysOnBottomHint)
570 != m_flags.testFlag(Qt::WindowStaysOnBottomHint))
571 || shouldBeAboveTransientParentFlags(flags) != shouldBeAboveTransientParentFlags(m_flags)) {
572 onPositionPreferenceChanged(positionPreferenceFromWindowFlags(flags));
576 dom::syncCSSClassWith(m_decoratedWindow,
"frameless", !hasFrame() || !window()->isTopLevel());
577 dom::syncCSSClassWith(m_decoratedWindow,
"has-border", hasBorder());
578 dom::syncCSSClassWith(m_decoratedWindow,
"has-shadow", hasShadow());
579 dom::syncCSSClassWith(m_decoratedWindow,
"has-title", hasTitleBar());
580 dom::syncCSSClassWith(m_decoratedWindow,
"transparent-for-input",
581 flags.testFlag(Qt::WindowTransparentForInput));
583 m_nonClientArea->titleBar()->setMaximizeVisible(hasMaximizeButton());
584 m_nonClientArea->titleBar()->setCloseVisible(m_flags.testFlag(Qt::WindowCloseButtonHint));
591 newState &= Qt::WindowActive;
593 const Qt::WindowStates oldState = m_state;
595 if (newState.testFlag(Qt::WindowMinimized)) {
596 newState.setFlag(Qt::WindowMinimized,
false);
597 qWarning(
"Qt::WindowMinimized is not implemented in wasm");
598 window()->setWindowStates(newState);
602 if (newState == oldState)
606 m_previousWindowState = oldState;
613 m_nonClientArea->titleBar()->setTitle(title);
618 const auto dpi = screen()->devicePixelRatio();
619 auto pixmap = icon.pixmap(10 * dpi, 10 * dpi);
620 if (pixmap.isNull()) {
621 m_nonClientArea->titleBar()->setIcon(
622 Base64IconStore::get()->getIcon(Base64IconStore::IconType::QtLogo),
"svg+xml");
627 QBuffer buffer(&bytes);
628 pixmap.save(&buffer,
"png");
629 m_nonClientArea->titleBar()->setIcon(bytes.toBase64().toStdString(),
"png");
636 const bool isFullscreen = m_state.testFlag(Qt::WindowFullScreen);
637 const bool isMaximized = m_state.testFlag(Qt::WindowMaximized);
648 else if (isMaximized)
649 newGeom =
platformScreen()->availableGeometry().marginsRemoved(frameMargins());
653 dom::syncCSSClassWith(m_decoratedWindow,
"has-border", hasBorder());
654 dom::syncCSSClassWith(m_decoratedWindow,
"maximized", isMaximized);
656 m_nonClientArea->titleBar()->setRestoreVisible(isMaximized);
657 m_nonClientArea->titleBar()->setMaximizeVisible(hasMaximizeButton());
660 QWindowSystemInterface::handleWindowStateChanged(window(), m_state, m_previousWindowState);
664void QWasmWindow::commitParent(QWasmWindowTreeNode *parent)
666 onParentChanged(m_commitedParent, parent, positionPreferenceFromWindowFlags(window()->flags()));
667 m_commitedParent = parent;
672 qCDebug(qLcQpaWasmInputContext) <<
"handleKeyEvent";
674 if (QWasmInputContext *inputContext = activeWasmInputContext()) {
679 if (processKey(event)) {
683 inputContext->m_ignoreNextInput =
true;
685 event.webEvent.call<
void>(
"stopImmediatePropagation");
687 if (processKey(event)) {
688 event.webEvent.call<
void>(
"preventDefault");
689 event.webEvent.call<
void>(
"stopPropagation");
696 constexpr bool ProceedToNativeEvent =
false;
702#if QT_CONFIG(clipboard)
703 const auto clipboardResult =
704 QWasmIntegration::get()->getWasmClipboard()->processKeyboard(event);
706 using ProcessKeyboardResult = QWasmClipboard::ProcessKeyboardResult;
707 if (clipboardResult == ProcessKeyboardResult::NativeClipboardEventNeeded)
708 return ProceedToNativeEvent;
711 const auto result = QWindowSystemInterface::handleKeyEvent(
712 0, event.type == EventType::KeyDown ? QEvent::KeyPress : QEvent::KeyRelease, event.key,
713 event.modifiers, event.text, event.autoRepeat);
715#if QT_CONFIG(clipboard)
716 if (clipboardResult == ProcessKeyboardResult::NativeClipboardEventAndCopiedDataNeeded)
717 return ProceedToNativeEvent;
725 if (QWasmInputContext *inputContext = activeWasmInputContext())
726 inputContext->inputCallback(event);
728 m_focusHelper.set(
"innerHTML", std::string());
733 if (QWasmInputContext *inputContext = activeWasmInputContext())
734 inputContext->compositionStartCallback(event);
736 m_focusHelper.set(
"innerHTML", std::string());
741 if (QWasmInputContext *inputContext = activeWasmInputContext())
742 inputContext->compositionUpdateCallback(event);
744 m_focusHelper.set(
"innerHTML", std::string());
749 if (QWasmInputContext *inputContext = activeWasmInputContext())
750 inputContext->compositionEndCallback(event);
752 m_focusHelper.set(
"innerHTML", std::string());
757 if (QWasmInputContext *inputContext = activeWasmInputContext())
758 inputContext->beforeInputCallback(event);
760 m_focusHelper.set(
"innerHTML", std::string());
765 if (processPointerEnterLeave(event))
766 event.webEvent.call<
void>(
"preventDefault");
774 switch (event.type) {
778 QWindowSystemInterface::handleEnterEvent(
779 window(), mapFromGlobal(pointInScreen.toPoint()), pointInScreen);
796 if (m_capturedPointerId && event.isTargetedForElement(m_window) &&
797 m_window.call<
bool>(
"hasPointerCapture", *m_capturedPointerId)) {
798 m_window.call<
void>(
"releasePointerCapture", *m_capturedPointerId);
799 m_capturedPointerId = std::nullopt;
807 if (!event.isTargetedForElement(m_window))
810 switch (event.type) {
811 case EventType::PointerDown:
812 m_capturedPointerId = event.pointerId;
813 m_window.call<
void>(
"setPointerCapture", event.pointerId);
815 if ((window()->flags() & Qt::WindowDoesNotAcceptFocus)
816 != Qt::WindowDoesNotAcceptFocus
817 && window()->isTopLevel())
818 window()->requestActivate();
821 releasePointerGrab(event);
827 const bool eventAccepted = deliverPointerEvent(event);
828 if (!eventAccepted && event.type == EventType::PointerDown)
829 QGuiApplicationPrivate::instance()->closeAllPopups();
832 event.webEvent.call<
void>(
"preventDefault");
833 event.webEvent.call<
void>(
"stopPropagation");
843 const QPointF targetPointClippedToScreen(
844 qBound(geometryF.left(), pointInScreen.x(), geometryF.right()),
845 qBound(geometryF.top(), pointInScreen.y(), geometryF.bottom()));
848 const QEvent::Type eventType =
851 return eventType != QEvent::None
852 && QWindowSystemInterface::handleMouseEvent(
853 window(), QWasmIntegration::getTimestamp(),
854 window()->mapFromGlobal(targetPointClippedToScreen),
855 targetPointClippedToScreen, event.mouseButtons, event.mouseButton,
856 eventType, event.modifiers);
861 switch (event.type) {
864 pressure = event.pressure;
873 qreal xTilt = qBound(-60.0, event.tiltX, 60.0);
874 qreal yTilt = qBound(-60.0, event.tiltY, 60.0);
876 qreal rotation = event.twist > 180.0 ? 360.0 - event.twist : event.twist;
877 return QWindowSystemInterface::handleTabletEvent(
878 window(), QWasmIntegration::getTimestamp(), platformScreen()->tabletDevice(),
879 window()->mapFromGlobal(targetPointClippedToScreen),
880 targetPointClippedToScreen, event.mouseButtons, pressure, xTilt, yTilt,
881 event.tangentialPressure, rotation, event.modifiers);
884 QWindowSystemInterface::TouchPoint *touchPoint;
886 QPointF pointInTargetWindowCoords =
887 QPointF(window()->mapFromGlobal(targetPointClippedToScreen));
888 QPointF normalPosition(pointInTargetWindowCoords.x() / window()->width(),
889 pointInTargetWindowCoords.y() / window()->height());
891 const auto tp = m_pointerIdToTouchPoints.find(event.pointerId);
892 if (event.pointerType != PointerType::Pen && tp != m_pointerIdToTouchPoints.end()) {
893 touchPoint = &tp.value();
895 touchPoint = &m_pointerIdToTouchPoints
896 .insert(event.pointerId, QWindowSystemInterface::TouchPoint())
904 touchPoint->state = QEventPoint::State::Pressed;
907 const bool stationaryTouchPoint = (normalPosition == touchPoint->normalPosition);
908 touchPoint->normalPosition = normalPosition;
909 touchPoint->area = QRectF(targetPointClippedToScreen, QSizeF(event.width, event.height))
910 .translated(-event.width / 2, -event.height / 2);
911 touchPoint->pressure = event.pressure;
913 switch (event.type) {
914 case EventType::PointerUp:
915 touchPoint->state = QEventPoint::State::Released;
917 case EventType::PointerMove:
918 touchPoint->state = (stationaryTouchPoint ? QEventPoint::State::Stationary
919 : QEventPoint::State::Updated);
925 QList<QWindowSystemInterface::TouchPoint> touchPointList;
926 touchPointList.reserve(m_pointerIdToTouchPoints.size());
927 std::transform(m_pointerIdToTouchPoints.begin(), m_pointerIdToTouchPoints.end(),
928 std::back_inserter(touchPointList),
929 [](
const QWindowSystemInterface::TouchPoint &val) {
return val; });
931 if (event.type == EventType::PointerUp || event.type == EventType::PointerCancel)
932 m_pointerIdToTouchPoints.remove(event.pointerId);
934 return event.type == EventType::PointerCancel
935 ? QWindowSystemInterface::handleTouchCancelEvent(
936 window(), QWasmIntegration::getTimestamp(), platformScreen()->touchDevice(),
938 : QWindowSystemInterface::handleTouchEvent(
939 window(), QWasmIntegration::getTimestamp(), platformScreen()->touchDevice(),
940 touchPointList, event.modifiers);
946 event.call<
void>(
"preventDefault");
952 const int scrollFactor = -([&event]() {
966 return QWindowSystemInterface::handleWheelEvent(
967 window(), QWasmIntegration::getTimestamp(), window()->mapFromGlobal(pointInScreen),
968 pointInScreen, (event.delta * scrollFactor).toPoint(),
969 (event.delta * scrollFactor).toPoint(), event.modifiers, Qt::NoScrollPhase,
970 Qt::MouseEventNotSynthesized, event.webkitDirectionInvertedFromDevice);
974Qt::WindowFlags
QWasmWindow::fixTopLevelWindowFlags(Qt::WindowFlags flags)
const
976 if (!(flags.testFlag(Qt::CustomizeWindowHint))) {
977 if (flags.testFlag(Qt::Window)) {
978 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint
979 |Qt::WindowMaximizeButtonHint|Qt::WindowCloseButtonHint;
981 if (flags.testFlag(Qt::Dialog) || flags.testFlag(Qt::Tool))
982 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
984 if ((flags & Qt::WindowType_Mask) == Qt::SplashScreen)
985 flags |= Qt::FramelessWindowHint;
990bool QWasmWindow::shouldBeAboveTransientParentFlags(Qt::WindowFlags flags)
const
998 if (flags.testFlag(Qt::Tool) ||
999 flags.testFlag(Qt::SplashScreen) ||
1000 flags.testFlag(Qt::ToolTip) ||
1001 flags.testFlag(Qt::Popup))
1009QWasmWindowStack<>::PositionPreference
QWasmWindow::positionPreferenceFromWindowFlags(Qt::WindowFlags flags)
const
1011 flags = fixTopLevelWindowFlags(flags);
1013 if (flags.testFlag(Qt::WindowStaysOnTopHint))
1014 return QWasmWindowStack<>::PositionPreference::StayOnTop;
1015 if (flags.testFlag(Qt::WindowStaysOnBottomHint))
1016 return QWasmWindowStack<>::PositionPreference::StayOnBottom;
1017 if (shouldBeAboveTransientParentFlags(flags))
1018 return QWasmWindowStack<>::PositionPreference::StayAboveTransientParent;
1019 return QWasmWindowStack<>::PositionPreference::Regular;
1023QWasmInputContext *
QWasmWindow::activeWasmInputContext()
const
1026 return inputContext && inputContext->isActive() ? inputContext :
nullptr;
1031 return m_normalGeometry;
1036 return screen()->devicePixelRatio();
1046 return !m_flags.testFlag(Qt::FramelessWindowHint);
1051 return hasFrame() && !m_state.testFlag(Qt::WindowFullScreen) && !m_flags.testFlag(Qt::SubWindow)
1052 && !windowIsPopupType(m_flags) && !parent();
1057 return hasBorder() && m_flags.testFlag(Qt::WindowTitleHint);
1062 return hasBorder() && !m_flags.testFlag(Qt::NoDropShadowWindowHint);
1067 return !m_state.testFlag(Qt::WindowMaximized) && m_flags.testFlag(Qt::WindowMaximizeButtonHint);
1070bool QWasmWindow::windowIsPopupType(Qt::WindowFlags flags)
const
1072 if (flags.testFlag(Qt::Tool))
1075 return (flags.testFlag(Qt::Popup));
1080 QWindow *modalWindow;
1081 if (QGuiApplicationPrivate::instance()->isWindowBlocked(window(), &modalWindow)) {
1091 QPlatformWindow::requestActivateWindow();
1096 if (QWasmAccessibility::isEnabled())
1099 m_focusHelper.call<
void>(
"focus");
1104 m_focusHelper.call<
void>(
"setAttribute", std::string(
"aria-hidden"), std::string(
"true"));
1105 m_inputElement.call<
void>(
"setAttribute", std::string(
"aria-hidden"), std::string(
"true"));
1116 switch (event->type()) {
1117 case QEvent::WindowBlocked:
1118 m_decoratedWindow[
"classList"].call<
void>(
"add", emscripten::val(
"blocked"));
1120 case QEvent::WindowUnblocked:;
1121 m_decoratedWindow[
"classList"].call<
void>(
"remove", emscripten::val(
"blocked"));
1124 return QPlatformWindow::windowEvent(event);
1130 if (region.isEmpty()) {
1131 m_decoratedWindow[
"style"].set(
"clipPath", emscripten::val(
""));
1135 std::ostringstream cssClipPath;
1136 cssClipPath <<
"path('";
1137 for (
const auto &rect : region) {
1138 const auto cssRect = rect.adjusted(0, 0, 1, 1);
1139 cssClipPath <<
"M " << cssRect.left() <<
" " << cssRect.top() <<
" ";
1140 cssClipPath <<
"L " << cssRect.right() <<
" " << cssRect.top() <<
" ";
1141 cssClipPath <<
"L " << cssRect.right() <<
" " << cssRect.bottom() <<
" ";
1142 cssClipPath <<
"L " << cssRect.left() <<
" " << cssRect.bottom() <<
" z ";
1144 cssClipPath <<
"')";
1145 m_decoratedWindow[
"style"].set(
"clipPath", emscripten::val(cssClipPath.str()));
1148void QWasmWindow::onTransientParentChanged(QWindow *newTransientParent)
1150 Q_UNUSED(newTransientParent);
1152 const auto positionPreference = positionPreferenceFromWindowFlags(window()->flags());
1153 QWasmWindowTreeNode::onParentChanged(parentNode(),
nullptr, positionPreference);
1154 QWasmWindowTreeNode::onParentChanged(
nullptr, parentNode(), positionPreference);
1159 const auto positionPreference = positionPreferenceFromWindowFlags(window()->flags());
1160 QWasmWindowTreeNode::onParentChanged(parentNode(),
nullptr, positionPreference);
1161 QWasmWindowTreeNode::onParentChanged(
nullptr, parentNode(), positionPreference);
1168 setWindowFlags(window()->flags());
1170 commitParent(parentNode());
1175 return "!qtwindow" +
std::to_string(m_winId);
1196 QWasmWindowStack<>::PositionPreference positionPreference)
1199 previous->containerElement().call<
void>(
"removeChild", m_decoratedWindow);
1201 current->containerElement().call<
void>(
"appendChild", m_decoratedWindow);
1202 QWasmWindowTreeNode::onParentChanged(previous, current, positionPreference);
QRect window() const
Returns the window rectangle.
QWasmCompositor(QWasmScreen *screen)
static QWasmIntegration * get()
QWasmInputContext * wasmInputContext() const
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 ...
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
QWasmWindow(QWindow *w, QWasmCompositor *compositor, QWasmBackingStore *backingStore, WId nativeHandle)
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)