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>
38#include <QKeySequence>
48 m_compositor(compositor),
49 m_backingStore(backingStore),
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_canvas[
"style"].set(
"pointerEvents",
"none");
129 m_window.call<
void>(
"appendChild", m_canvas);
131 m_a11yContainer[
"classList"].call<
void>(
"add", emscripten::val(
"qt-window-a11y-container"));
132 m_window.call<
void>(
"appendChild", m_a11yContainer);
134 if (QWasmAccessibility::isEnabled())
137 const bool rendersTo2dContext = w->surfaceType() != QSurface::OpenGLSurface;
138 if (rendersTo2dContext)
139 m_context2d = m_canvas.call<emscripten::val>(
"getContext", emscripten::val(
"2d"));
141 m_winId = WId(&m_window);
142 m_decoratedWindow.set(
"id",
"qt-window-" + std::to_string(m_winId));
143 emscripten::val::module_property(
"specialHTMLTargets").set(canvasSelector(), m_canvas);
145 m_flags = window()->flags();
149 m_transientWindowChangedConnection =
151 window(), &QWindow::transientParentChanged,
152 window(), [
this](QWindow *tp) { onTransientParentChanged(tp); });
154 m_modalityChangedConnection =
156 window(), &QWindow::modalityChanged,
157 window(), [
this](Qt::WindowModality) { onModalityChanged(); });
164 m_pointerDownCallback = QWasmEventHandler(m_window,
"pointerdown",
165 [
this](emscripten::val event){ processPointer(PointerEvent(EventType::PointerDown, event)); }
167 m_pointerMoveCallback = QWasmEventHandler(m_window,
"pointermove",
168 [
this](emscripten::val event){ processPointer(PointerEvent(EventType::PointerMove, event)); }
170 m_pointerUpCallback = QWasmEventHandler(m_window,
"pointerup",
171 [
this](emscripten::val event){ processPointer(PointerEvent(EventType::PointerUp, event)); }
173 m_pointerCancelCallback = QWasmEventHandler(m_window,
"pointercancel",
174 [
this](emscripten::val event){ processPointer(PointerEvent(EventType::PointerCancel, event)); }
176 m_pointerEnterCallback = QWasmEventHandler(m_window,
"pointerenter",
177 [
this](emscripten::val event) {
this->handlePointerEnterLeaveEvent(PointerEvent(EventType::PointerEnter, event)); }
179 m_pointerLeaveCallback = QWasmEventHandler(m_window,
"pointerleave",
180 [
this](emscripten::val event) {
this->handlePointerEnterLeaveEvent(PointerEvent(EventType::PointerLeave, event)); }
183#if QT_CONFIG(draganddrop)
184 m_window.call<
void>(
"setAttribute", emscripten::val(
"draggable"), emscripten::val(
"true"));
185 m_dragStartCallback = QWasmEventHandler(m_window,
"dragstart",
186 [
this](emscripten::val event) {
187 DragEvent dragEvent(EventType::DragStart, event, window());
188 QWasmDrag::instance()->onNativeDragStarted(&dragEvent);
191 m_dragOverCallback = QWasmEventHandler(m_window,
"dragover",
192 [
this](emscripten::val event) {
193 DragEvent dragEvent(EventType::DragOver, event, window());
194 QWasmDrag::instance()->onNativeDragOver(&dragEvent);
197 m_dropCallback = QWasmEventHandler(m_window,
"drop",
198 [
this](emscripten::val event) {
199 DragEvent dragEvent(EventType::Drop, event, window());
200 QWasmDrag::instance()->onNativeDrop(&dragEvent);
203 m_dragEndCallback = QWasmEventHandler(m_window,
"dragend",
204 [
this](emscripten::val event) {
205 DragEvent dragEvent(EventType::DragEnd, event, window());
206 QWasmDrag::instance()->onNativeDragFinished(&dragEvent, platformScreen());
207 releasePointerGrab(dragEvent);
210 m_dragEnterCallback = QWasmEventHandler(m_window,
"dragenter",
211 [
this](emscripten::val event) {
212 DragEvent dragEvent(EventType::DragEnter, event, window());
213 QWasmDrag::instance()->onNativeDragEnter(&dragEvent);
216 m_dragLeaveCallback = QWasmEventHandler(m_window,
"dragleave",
217 [
this](emscripten::val event) {
218 DragEvent dragEvent(EventType::DragLeave, event, window());
219 QWasmDrag::instance()->onNativeDragLeave(&dragEvent);
224 m_wheelEventCallback = QWasmEventHandler(m_window,
"wheel",
225 [
this](emscripten::val event) {
this->handleWheelEvent(event); });
227 m_keyDownCallback = QWasmEventHandler(m_window,
"keydown",
228 [
this](emscripten::val event) {
this->handleKeyEvent(KeyEvent(EventType::KeyDown, event)); });
229 m_keyUpCallback =QWasmEventHandler(m_window,
"keyup",
230 [
this](emscripten::val event) {
this->handleKeyEvent(KeyEvent(EventType::KeyUp, event)); });
232 m_inputCallback = QWasmEventHandler(m_window,
"input",
233 [
this](emscripten::val event){ handleInputEvent(event); });
234 m_compositionUpdateCallback = QWasmEventHandler(m_window,
"compositionupdate",
235 [
this](emscripten::val event){ handleCompositionUpdateEvent(event); });
236 m_compositionStartCallback = QWasmEventHandler(m_window,
"compositionstart",
237 [
this](emscripten::val event){ handleCompositionStartEvent(event); });
238 m_compositionEndCallback = QWasmEventHandler(m_window,
"compositionend",
239 [
this](emscripten::val event){ handleCompositionEndEvent(event); });
240 m_beforeInputCallback = QWasmEventHandler(m_window,
"beforeinput",
241 [
this](emscripten::val event){ handleBeforeInputEvent(event); });
248#if QT_CONFIG(accessibility)
249 QWasmAccessibility::onRemoveWindow(window());
251 QObject::disconnect(m_transientWindowChangedConnection);
252 QObject::disconnect(m_modalityChangedConnection);
256 emscripten::val::module_property(
"specialHTMLTargets").delete_(canvasSelector());
257 m_window.call<
void>(
"removeChild", m_canvas);
258 m_window.call<
void>(
"removeChild", m_a11yContainer);
259 m_context2d = emscripten::val::undefined();
260 commitParent(
nullptr);
261 if (m_requestAnimationFrameId > -1)
262 emscripten_cancel_animation_frame(m_requestAnimationFrameId);
268 (QGuiApplication::focusWindow() &&
269 QGuiApplication::focusWindow() != window()))
275 std::map<uint64_t, QWasmWindow *> allWindows;
276 for (
const auto &w : platformScreen()->allWindows()) {
277 if (w->getActiveIndex() > 0)
278 allWindows.insert({w->getActiveIndex(), w});
282 if (getActiveIndex() > 0)
283 allWindows.insert({getActiveIndex(),
this});
285 if (allWindows.size() >= 2) {
286 const auto lastIt =
std::prev(allWindows.end());
287 const auto prevIt =
std::prev(lastIt);
288 const auto lastW = lastIt->second;
289 const auto prevW = prevIt->second;
292 prevW->requestActivateWindow();
298 return window()->requestedFormat();
303 if (!window ||!window->handle())
305 return static_cast<
QWasmWindow *>(window->handle());
318 return window()->flags();
323 return window()->isModal();
328 window()->setWindowState(Qt::WindowNoState);
333 window()->setWindowState(Qt::WindowMaximized);
338 window()->setWindowState(m_state.testFlag(Qt::WindowMaximized) ? Qt::WindowNoState
339 : Qt::WindowMaximized);
350 QGuiApplicationPrivate::instance()->closeAllPopups();
357 return QWindowSystemInterface::handleMouseEvent(
358 window(), QWasmIntegration::getTimestamp(), window()->mapFromGlobal(pointInScreen),
359 pointInScreen, event.mouseButtons, event.mouseButton,
360 MouseEvent::mouseEventTypeFromEventType(event.type, WindowArea::NonClient),
366 auto initialGeometry = QPlatformWindow::initialGeometry(window(),
367 windowGeometry(), defaultWindowSize, defaultWindowSize);
368 m_normalGeometry = initialGeometry;
370 setWindowState(window()->windowStates());
371 setWindowFlags(window()->flags());
372 setWindowTitle(window()->title());
373 setMask(QHighDpi::toNativeLocalRegion(window()->mask(), window()));
375 if (window()->isTopLevel())
376 setWindowIcon(window()->icon());
377 QPlatformWindow::setGeometry(m_normalGeometry);
379#if QT_CONFIG(accessibility)
382 if (window()->isTopLevel())
383 QWasmAccessibility::addAccessibilityEnableButton(window());
389 return static_cast<
QWasmScreen *>(window()->screen()->handle());
394 if (!m_backingStore || !isVisible() || m_context2d.isUndefined())
397 auto image = m_backingStore->getUpdatedWebImage(
this);
398 if (image.isUndefined())
400 m_context2d.call<
void>(
"putImageData", image, emscripten::val(0), emscripten::val(0));
405 m_decoratedWindow[
"style"].set(
"zIndex", std::to_string(z));
410 m_window[
"style"].set(
"cursor", emscripten::val(cssCursorName.constData()));
415 const auto margins = frameMargins();
417 const QRect clientAreaRect = ([
this, &rect, &margins]() {
418 if (m_state.testFlag(Qt::WindowFullScreen))
419 return platformScreen()->geometry();
420 if (m_state.testFlag(Qt::WindowMaximized))
421 return platformScreen()->availableGeometry().marginsRemoved(frameMargins());
423 auto offset = rect.topLeft() - (!parent() ? screen()->geometry().topLeft() : QPoint());
426 auto containerGeometryInViewport =
427 QRectF::fromDOMRect(parentNode()->containerElement().call<emscripten::val>(
428 "getBoundingClientRect"))
431 auto rectInViewport = QRect(containerGeometryInViewport.topLeft() + offset, rect.size());
433 QRect cappedGeometry(rectInViewport);
436 cappedGeometry.moveTop(
437 std::max(std::min(rectInViewport.y(), containerGeometryInViewport.bottom()),
438 containerGeometryInViewport.y() + margins.top()));
440 cappedGeometry.setSize(
441 cappedGeometry.size().expandedTo(windowMinimumSize()).boundedTo(windowMaximumSize()));
442 return QRect(QPoint(rect.x(), rect.y() + cappedGeometry.y() - rectInViewport.y()),
445 m_nonClientArea->onClientAreaWidthChange(clientAreaRect.width());
447 const auto frameRect =
449 .adjusted(-margins.left(), -margins.top(), margins.right(), margins.bottom())
450 .translated(!parent() ? -screen()->geometry().topLeft() : QPoint());
452 m_decoratedWindow[
"style"].set(
"left", std::to_string(frameRect.left()) +
"px");
453 m_decoratedWindow[
"style"].set(
"top", std::to_string(frameRect.top()) +
"px");
454 m_canvas[
"style"].set(
"width", std::to_string(clientAreaRect.width()) +
"px");
455 m_canvas[
"style"].set(
"height", std::to_string(clientAreaRect.height()) +
"px");
456 m_a11yContainer[
"style"].set(
"width", std::to_string(clientAreaRect.width()) +
"px");
457 m_a11yContainer[
"style"].set(
"height", std::to_string(clientAreaRect.height()) +
"px");
460 m_window[
"style"].set(
"width", std::to_string(clientAreaRect.width()) +
"px");
461 m_window[
"style"].set(
"height", std::to_string(clientAreaRect.height()) +
"px");
463 QSizeF canvasSize = clientAreaRect.size() * devicePixelRatio();
465 m_canvas.set(
"width", canvasSize.width());
466 m_canvas.set(
"height", canvasSize.height());
468 bool shouldInvalidate =
true;
469 if (!m_state.testFlag(Qt::WindowFullScreen) && !m_state.testFlag(Qt::WindowMaximized)) {
470 shouldInvalidate = m_normalGeometry.size() != clientAreaRect.size();
471 m_normalGeometry = clientAreaRect;
475 if (wasmInput && (QGuiApplication::focusWindow() == window()))
476 wasmInput->updateGeometry();
478 QWindowSystemInterface::handleGeometryChange(window(), clientAreaRect);
479 if (shouldInvalidate)
482 m_compositor->requestUpdateWindow(
this, QRect(QPoint(0, 0), geometry().size()));
488 const bool nowVisible = m_decoratedWindow[
"style"][
"display"].as<std::string>() ==
"block";
489 if (visible == nowVisible)
493 m_decoratedWindow[
"style"].set(
"display", visible ?
"block" :
"none");
494 if (window() == QGuiApplication::focusWindow())
499#if QT_CONFIG(accessibility)
500 QWasmAccessibility::onShowWindow(window());
507 return window()->isVisible();
512 const auto frameRect =
513 QRectF::fromDOMRect(m_decoratedWindow.call<emscripten::val>(
"getBoundingClientRect"));
514 const auto canvasRect =
515 QRectF::fromDOMRect(m_window.call<emscripten::val>(
"getBoundingClientRect"));
516 return QMarginsF(canvasRect.left() - frameRect.left(), canvasRect.top() - frameRect.top(),
517 frameRect.right() - canvasRect.right(),
518 frameRect.bottom() - canvasRect.bottom())
543 m_nonClientArea->propagateSizeHints();
548 m_decoratedWindow[
"style"].set(
"opacity", qBound(0.0, level, 1.0));
553 m_compositor->requestUpdateWindow(
this, QRect(QPoint(0, 0), geometry().size()));
563 flags = fixTopLevelWindowFlags(flags);
565 if ((flags.testFlag(Qt::WindowStaysOnTopHint) != m_flags.testFlag(Qt::WindowStaysOnTopHint))
566 || (flags.testFlag(Qt::WindowStaysOnBottomHint)
567 != m_flags.testFlag(Qt::WindowStaysOnBottomHint))
568 || shouldBeAboveTransientParentFlags(flags) != shouldBeAboveTransientParentFlags(m_flags)) {
569 onPositionPreferenceChanged(positionPreferenceFromWindowFlags(flags));
577 flags.testFlag(Qt::WindowTransparentForInput));
579 m_nonClientArea->titleBar()->setMaximizeVisible(hasMaximizeButton());
580 m_nonClientArea->titleBar()->setCloseVisible(m_flags.testFlag(Qt::WindowCloseButtonHint));
587 newState &= Qt::WindowActive;
589 const Qt::WindowStates oldState = m_state;
591 if (newState.testFlag(Qt::WindowMinimized)) {
592 newState.setFlag(Qt::WindowMinimized,
false);
593 qWarning(
"Qt::WindowMinimized is not implemented in wasm");
594 window()->setWindowStates(newState);
598 if (newState == oldState)
602 m_previousWindowState = oldState;
609 m_nonClientArea->titleBar()->setTitle(title);
614 const auto dpi = screen()->devicePixelRatio();
615 auto pixmap = icon.pixmap(10 * dpi, 10 * dpi);
616 if (pixmap.isNull()) {
617 m_nonClientArea->titleBar()->setIcon(
618 Base64IconStore::get()->getIcon(Base64IconStore::IconType::QtLogo),
"svg+xml");
623 QBuffer buffer(&bytes);
624 pixmap.save(&buffer,
"png");
625 m_nonClientArea->titleBar()->setIcon(bytes.toBase64().toStdString(),
"png");
632 const bool isFullscreen = m_state.testFlag(Qt::WindowFullScreen);
633 const bool isMaximized = m_state.testFlag(Qt::WindowMaximized);
644 else if (isMaximized)
645 newGeom =
platformScreen()->availableGeometry().marginsRemoved(frameMargins());
652 m_nonClientArea->titleBar()->setRestoreVisible(isMaximized);
653 m_nonClientArea->titleBar()->setMaximizeVisible(hasMaximizeButton());
656 QWindowSystemInterface::handleWindowStateChanged(window(), m_state, m_previousWindowState);
660void QWasmWindow::commitParent(QWasmWindowTreeNode *parent)
662 onParentChanged(m_commitedParent, parent, positionPreferenceFromWindowFlags(window()->flags()));
663 m_commitedParent = parent;
668 qCDebug(qLcQpaWasmInputContext) <<
"handleKeyEvent";
670 if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive()) {
671 handleKeyForInputContextEvent(event);
673 if (processKey(event)) {
674 event.webEvent.call<
void>(
"preventDefault");
675 event.webEvent.call<
void>(
"stopPropagation");
682 constexpr bool ProceedToNativeEvent =
false;
685#if QT_CONFIG(clipboard)
686 const auto clipboardResult =
687 QWasmIntegration::get()->getWasmClipboard()->processKeyboard(event);
689 using ProcessKeyboardResult = QWasmClipboard::ProcessKeyboardResult;
690 if (clipboardResult == ProcessKeyboardResult::NativeClipboardEventNeeded)
691 return ProceedToNativeEvent;
694 const auto result = QWindowSystemInterface::handleKeyEvent(
695 0, event.type == EventType::KeyDown ? QEvent::KeyPress : QEvent::KeyRelease, event.key,
696 event.modifiers, event.text, event.autoRepeat);
698#if QT_CONFIG(clipboard)
699 return clipboardResult == ProcessKeyboardResult::NativeClipboardEventAndCopiedDataNeeded
700 ? ProceedToNativeEvent
716 qCDebug(qLcQpaWasmInputContext) <<
"processKey as KeyEvent";
718 if (processKeyForInputContext(keyEvent))
719 event.call<
void>(
"preventDefault");
720 event.call<
void>(
"stopImmediatePropagation");
725 qCDebug(qLcQpaWasmInputContext) << Q_FUNC_INFO;
728 QKeySequence keySeq(event.modifiers | event.key);
730 if (keySeq == QKeySequence::Paste) {
735 const auto result = QWindowSystemInterface::handleKeyEvent(
736 0, event.type == EventType::KeyDown ? QEvent::KeyPress : QEvent::KeyRelease, event.key,
737 event.modifiers, event.text);
739#if QT_CONFIG(clipboard)
741 if (keySeq == QKeySequence::Copy || keySeq == QKeySequence::Cut)
750 if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive())
751 inputContext->inputCallback(event);
753 m_focusHelper.set(
"innerHTML", std::string());
758 if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive())
759 inputContext->compositionStartCallback(event);
761 m_focusHelper.set(
"innerHTML", std::string());
766 if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive())
767 inputContext->compositionUpdateCallback(event);
769 m_focusHelper.set(
"innerHTML", std::string());
774 if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive())
775 inputContext->compositionEndCallback(event);
777 m_focusHelper.set(
"innerHTML", std::string());
782 if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive())
783 inputContext->beforeInputCallback(event);
785 m_focusHelper.set(
"innerHTML", std::string());
790 if (processPointerEnterLeave(event))
791 event.webEvent.call<
void>(
"preventDefault");
799 switch (event.type) {
803 QWindowSystemInterface::handleEnterEvent(
804 window(), mapFromGlobal(pointInScreen.toPoint()), pointInScreen);
821 if (m_capturedPointerId && event.isTargetedForElement(m_window) &&
822 m_window.call<
bool>(
"hasPointerCapture", *m_capturedPointerId)) {
823 m_window.call<
void>(
"releasePointerCapture", *m_capturedPointerId);
824 m_capturedPointerId = std::nullopt;
832 if (!event.isTargetedForElement(m_window))
835 switch (event.type) {
836 case EventType::PointerDown:
837 m_capturedPointerId = event.pointerId;
838 m_window.call<
void>(
"setPointerCapture", event.pointerId);
840 if ((window()->flags() & Qt::WindowDoesNotAcceptFocus)
841 != Qt::WindowDoesNotAcceptFocus
842 && window()->isTopLevel())
843 window()->requestActivate();
846 releasePointerGrab(event);
852 const bool eventAccepted = deliverPointerEvent(event);
853 if (!eventAccepted && event.type == EventType::PointerDown)
854 QGuiApplicationPrivate::instance()->closeAllPopups();
857 event.webEvent.call<
void>(
"preventDefault");
858 event.webEvent.call<
void>(
"stopPropagation");
868 const QPointF targetPointClippedToScreen(
869 qBound(geometryF.left(), pointInScreen.x(), geometryF.right()),
870 qBound(geometryF.top(), pointInScreen.y(), geometryF.bottom()));
873 const QEvent::Type eventType =
876 return eventType != QEvent::None
877 && QWindowSystemInterface::handleMouseEvent(
878 window(), QWasmIntegration::getTimestamp(),
879 window()->mapFromGlobal(targetPointClippedToScreen),
880 targetPointClippedToScreen, event.mouseButtons, event.mouseButton,
881 eventType, event.modifiers);
886 switch (event.type) {
889 pressure = event.pressure;
898 qreal xTilt = qBound(-60.0, event.tiltX, 60.0);
899 qreal yTilt = qBound(-60.0, event.tiltY, 60.0);
901 qreal rotation = event.twist > 180.0 ? 360.0 - event.twist : event.twist;
902 return QWindowSystemInterface::handleTabletEvent(
903 window(), QWasmIntegration::getTimestamp(), platformScreen()->tabletDevice(),
904 window()->mapFromGlobal(targetPointClippedToScreen),
905 targetPointClippedToScreen, event.mouseButtons, pressure, xTilt, yTilt,
906 event.tangentialPressure, rotation, event.modifiers);
909 QWindowSystemInterface::TouchPoint *touchPoint;
911 QPointF pointInTargetWindowCoords =
912 QPointF(window()->mapFromGlobal(targetPointClippedToScreen));
913 QPointF normalPosition(pointInTargetWindowCoords.x() / window()->width(),
914 pointInTargetWindowCoords.y() / window()->height());
916 const auto tp = m_pointerIdToTouchPoints.find(event.pointerId);
917 if (event.pointerType != PointerType::Pen && tp != m_pointerIdToTouchPoints.end()) {
918 touchPoint = &tp.value();
920 touchPoint = &m_pointerIdToTouchPoints
921 .insert(event.pointerId, QWindowSystemInterface::TouchPoint())
929 touchPoint->state = QEventPoint::State::Pressed;
932 const bool stationaryTouchPoint = (normalPosition == touchPoint->normalPosition);
933 touchPoint->normalPosition = normalPosition;
934 touchPoint->area = QRectF(targetPointClippedToScreen, QSizeF(event.width, event.height))
935 .translated(-event.width / 2, -event.height / 2);
936 touchPoint->pressure = event.pressure;
938 switch (event.type) {
939 case EventType::PointerUp:
940 touchPoint->state = QEventPoint::State::Released;
942 case EventType::PointerMove:
943 touchPoint->state = (stationaryTouchPoint ? QEventPoint::State::Stationary
944 : QEventPoint::State::Updated);
950 QList<QWindowSystemInterface::TouchPoint> touchPointList;
951 touchPointList.reserve(m_pointerIdToTouchPoints.size());
952 std::transform(m_pointerIdToTouchPoints.begin(), m_pointerIdToTouchPoints.end(),
953 std::back_inserter(touchPointList),
954 [](
const QWindowSystemInterface::TouchPoint &val) {
return val; });
956 if (event.type == EventType::PointerUp || event.type == EventType::PointerCancel)
957 m_pointerIdToTouchPoints.remove(event.pointerId);
959 return event.type == EventType::PointerCancel
960 ? QWindowSystemInterface::handleTouchCancelEvent(
961 window(), QWasmIntegration::getTimestamp(), platformScreen()->touchDevice(),
963 : QWindowSystemInterface::handleTouchEvent(
964 window(), QWasmIntegration::getTimestamp(), platformScreen()->touchDevice(),
965 touchPointList, event.modifiers);
971 event.call<
void>(
"preventDefault");
977 const int scrollFactor = -([&event]() {
991 return QWindowSystemInterface::handleWheelEvent(
992 window(), QWasmIntegration::getTimestamp(), window()->mapFromGlobal(pointInScreen),
993 pointInScreen, (event.delta * scrollFactor).toPoint(),
994 (event.delta * scrollFactor).toPoint(), event.modifiers, Qt::NoScrollPhase,
995 Qt::MouseEventNotSynthesized, event.webkitDirectionInvertedFromDevice);
999Qt::WindowFlags
QWasmWindow::fixTopLevelWindowFlags(Qt::WindowFlags flags)
const
1001 if (!(flags.testFlag(Qt::CustomizeWindowHint))) {
1002 if (flags.testFlag(Qt::Window)) {
1003 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint
1004 |Qt::WindowMaximizeButtonHint|Qt::WindowCloseButtonHint;
1006 if (flags.testFlag(Qt::Dialog) || flags.testFlag(Qt::Tool))
1007 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
1009 if ((flags & Qt::WindowType_Mask) == Qt::SplashScreen)
1010 flags |= Qt::FramelessWindowHint;
1015bool QWasmWindow::shouldBeAboveTransientParentFlags(Qt::WindowFlags flags)
const
1023 if (flags.testFlag(Qt::Tool) ||
1024 flags.testFlag(Qt::SplashScreen) ||
1025 flags.testFlag(Qt::ToolTip) ||
1026 flags.testFlag(Qt::Popup))
1034QWasmWindowStack<>::PositionPreference
QWasmWindow::positionPreferenceFromWindowFlags(Qt::WindowFlags flags)
const
1036 flags = fixTopLevelWindowFlags(flags);
1038 if (flags.testFlag(Qt::WindowStaysOnTopHint))
1039 return QWasmWindowStack<>::PositionPreference::StayOnTop;
1040 if (flags.testFlag(Qt::WindowStaysOnBottomHint))
1041 return QWasmWindowStack<>::PositionPreference::StayOnBottom;
1042 if (shouldBeAboveTransientParentFlags(flags))
1043 return QWasmWindowStack<>::PositionPreference::StayAboveTransientParent;
1044 return QWasmWindowStack<>::PositionPreference::Regular;
1049 return m_normalGeometry;
1054 return screen()->devicePixelRatio();
1064 return !m_flags.testFlag(Qt::FramelessWindowHint);
1069 return hasFrame() && !m_state.testFlag(Qt::WindowFullScreen) && !m_flags.testFlag(Qt::SubWindow)
1070 && !windowIsPopupType(m_flags) && !parent();
1075 return hasBorder() && m_flags.testFlag(Qt::WindowTitleHint);
1080 return hasBorder() && !m_flags.testFlag(Qt::NoDropShadowWindowHint);
1085 return !m_state.testFlag(Qt::WindowMaximized) && m_flags.testFlag(Qt::WindowMaximizeButtonHint);
1088bool QWasmWindow::windowIsPopupType(Qt::WindowFlags flags)
const
1090 if (flags.testFlag(Qt::Tool))
1093 return (flags.testFlag(Qt::Popup));
1098 QWindow *modalWindow;
1099 if (QGuiApplicationPrivate::instance()->isWindowBlocked(window(), &modalWindow)) {
1109 QPlatformWindow::requestActivateWindow();
1114 if (QWasmAccessibility::isEnabled())
1117 m_focusHelper.call<
void>(
"focus");
1122 m_focusHelper.call<
void>(
"setAttribute", std::string(
"aria-hidden"), std::string(
"true"));
1123 m_inputElement.call<
void>(
"setAttribute", std::string(
"aria-hidden"), std::string(
"true"));
1134 switch (event->type()) {
1135 case QEvent::WindowBlocked:
1136 m_decoratedWindow[
"classList"].call<
void>(
"add", emscripten::val(
"blocked"));
1138 case QEvent::WindowUnblocked:;
1139 m_decoratedWindow[
"classList"].call<
void>(
"remove", emscripten::val(
"blocked"));
1142 return QPlatformWindow::windowEvent(event);
1148 if (region.isEmpty()) {
1149 m_decoratedWindow[
"style"].set(
"clipPath", emscripten::val(
""));
1153 std::ostringstream cssClipPath;
1154 cssClipPath <<
"path('";
1155 for (
const auto &rect : region) {
1156 const auto cssRect = rect.adjusted(0, 0, 1, 1);
1157 cssClipPath <<
"M " << cssRect.left() <<
" " << cssRect.top() <<
" ";
1158 cssClipPath <<
"L " << cssRect.right() <<
" " << cssRect.top() <<
" ";
1159 cssClipPath <<
"L " << cssRect.right() <<
" " << cssRect.bottom() <<
" ";
1160 cssClipPath <<
"L " << cssRect.left() <<
" " << cssRect.bottom() <<
" z ";
1162 cssClipPath <<
"')";
1163 m_decoratedWindow[
"style"].set(
"clipPath", emscripten::val(cssClipPath.str()));
1166void QWasmWindow::onTransientParentChanged(QWindow *newTransientParent)
1168 Q_UNUSED(newTransientParent);
1170 const auto positionPreference = positionPreferenceFromWindowFlags(window()->flags());
1171 QWasmWindowTreeNode::onParentChanged(parentNode(),
nullptr, positionPreference);
1172 QWasmWindowTreeNode::onParentChanged(
nullptr, parentNode(), positionPreference);
1177 const auto positionPreference = positionPreferenceFromWindowFlags(window()->flags());
1178 QWasmWindowTreeNode::onParentChanged(parentNode(),
nullptr, positionPreference);
1179 QWasmWindowTreeNode::onParentChanged(
nullptr, parentNode(), positionPreference);
1186 setWindowFlags(window()->flags());
1188 commitParent(parentNode());
1193 return "!qtwindow" +
std::to_string(m_winId);
1214 QWasmWindowStack<>::PositionPreference positionPreference)
1217 previous->containerElement().call<
void>(
"removeChild", m_decoratedWindow);
1219 current->containerElement().call<
void>(
"appendChild", m_decoratedWindow);
1220 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 ...
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)
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.
void syncCSSClassWith(emscripten::val element, std::string cssClassName, bool flag)
Q_GUI_EXPORT int qt_defaultDpiX()
QDebug Q_GUI_EXPORT & operator<<(QDebug &s, const QVectorPath &path)