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.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_window.call<
void>(
"appendChild", m_canvas);
128 m_a11yContainer[
"classList"].call<
void>(
"add", emscripten::val(
"qt-window-a11y-container"));
129 m_window.call<
void>(
"appendChild", m_a11yContainer);
131 if (QWasmAccessibility::isEnabled())
134 const bool rendersTo2dContext = w->surfaceType() != QSurface::OpenGLSurface;
135 if (rendersTo2dContext)
136 m_context2d = m_canvas.call<emscripten::val>(
"getContext", emscripten::val(
"2d"));
138 m_winId = WId(&m_window);
139 m_decoratedWindow.set(
"id",
"qt-window-" + std::to_string(m_winId));
140 emscripten::val::module_property(
"specialHTMLTargets").set(canvasSelector(), m_canvas);
142 m_flags = window()->flags();
146 m_transientWindowChangedConnection =
148 window(), &QWindow::transientParentChanged,
149 window(), [
this](QWindow *tp) { onTransientParentChanged(tp); });
151 m_modalityChangedConnection =
153 window(), &QWindow::modalityChanged,
154 window(), [
this](Qt::WindowModality) { onModalityChanged(); });
161 m_pointerDownCallback = QWasmEventHandler(m_window,
"pointerdown",
162 [
this](emscripten::val event){ processPointer(PointerEvent(EventType::PointerDown, event)); }
164 m_pointerMoveCallback = QWasmEventHandler(m_window,
"pointermove",
165 [
this](emscripten::val event){ processPointer(PointerEvent(EventType::PointerMove, event)); }
167 m_pointerUpCallback = QWasmEventHandler(m_window,
"pointerup",
168 [
this](emscripten::val event){ processPointer(PointerEvent(EventType::PointerUp, event)); }
170 m_pointerCancelCallback = QWasmEventHandler(m_window,
"pointercancel",
171 [
this](emscripten::val event){ processPointer(PointerEvent(EventType::PointerCancel, event)); }
173 m_pointerEnterCallback = QWasmEventHandler(m_window,
"pointerenter",
174 [
this](emscripten::val event) {
this->handlePointerEnterLeaveEvent(PointerEvent(EventType::PointerEnter, event)); }
176 m_pointerLeaveCallback = QWasmEventHandler(m_window,
"pointerleave",
177 [
this](emscripten::val event) {
this->handlePointerEnterLeaveEvent(PointerEvent(EventType::PointerLeave, event)); }
180#if QT_CONFIG(draganddrop)
181 m_window.call<
void>(
"setAttribute", emscripten::val(
"draggable"), emscripten::val(
"true"));
182 m_dragStartCallback = QWasmEventHandler(m_window,
"dragstart",
183 [
this](emscripten::val event) {
184 DragEvent dragEvent(EventType::DragStart, event, window());
185 QWasmDrag::instance()->onNativeDragStarted(&dragEvent);
188 m_dragOverCallback = QWasmEventHandler(m_window,
"dragover",
189 [
this](emscripten::val event) {
190 DragEvent dragEvent(EventType::DragOver, event, window());
191 QWasmDrag::instance()->onNativeDragOver(&dragEvent);
194 m_dropCallback = QWasmEventHandler(m_window,
"drop",
195 [
this](emscripten::val event) {
196 DragEvent dragEvent(EventType::Drop, event, window());
197 QWasmDrag::instance()->onNativeDrop(&dragEvent);
200 m_dragEndCallback = QWasmEventHandler(m_window,
"dragend",
201 [
this](emscripten::val event) {
202 DragEvent dragEvent(EventType::DragEnd, event, window());
203 QWasmDrag::instance()->onNativeDragFinished(&dragEvent);
206 m_dragLeaveCallback = QWasmEventHandler(m_window,
"dragleave",
207 [
this](emscripten::val event) {
208 DragEvent dragEvent(EventType::DragLeave, event, window());
209 QWasmDrag::instance()->onNativeDragLeave(&dragEvent);
214 m_wheelEventCallback = QWasmEventHandler(m_window,
"wheel",
215 [
this](emscripten::val event) {
this->handleWheelEvent(event); });
217 m_keyDownCallback = QWasmEventHandler(m_window,
"keydown",
218 [
this](emscripten::val event) {
this->handleKeyEvent(KeyEvent(EventType::KeyDown, event, m_deadKeySupport)); });
219 m_keyUpCallback =QWasmEventHandler(m_window,
"keyup",
220 [
this](emscripten::val event) {
this->handleKeyEvent(KeyEvent(EventType::KeyUp, event, m_deadKeySupport)); });
222 m_inputCallback = QWasmEventHandler(m_window,
"input",
223 [
this](emscripten::val event){ handleInputEvent(event); });
224 m_compositionUpdateCallback = QWasmEventHandler(m_window,
"compositionupdate",
225 [
this](emscripten::val event){ handleCompositionUpdateEvent(event); });
226 m_compositionStartCallback = QWasmEventHandler(m_window,
"compositionstart",
227 [
this](emscripten::val event){ handleCompositionStartEvent(event); });
228 m_compositionEndCallback = QWasmEventHandler(m_window,
"compositionend",
229 [
this](emscripten::val event){ handleCompositionEndEvent(event); });
236#if QT_CONFIG(accessibility)
237 QWasmAccessibility::onRemoveWindow(window());
239 QObject::disconnect(m_transientWindowChangedConnection);
240 QObject::disconnect(m_modalityChangedConnection);
244 emscripten::val::module_property(
"specialHTMLTargets").delete_(canvasSelector());
245 m_window.call<
void>(
"removeChild", m_canvas);
246 m_window.call<
void>(
"removeChild", m_a11yContainer);
247 m_context2d = emscripten::val::undefined();
248 commitParent(
nullptr);
249 if (m_requestAnimationFrameId > -1)
250 emscripten_cancel_animation_frame(m_requestAnimationFrameId);
256 (QGuiApplication::focusWindow() &&
257 QGuiApplication::focusWindow() != window()))
263 std::map<uint64_t, QWasmWindow *> allWindows;
264 for (
const auto &w : platformScreen()->allWindows()) {
265 if (w->getActiveIndex() > 0)
266 allWindows.insert({w->getActiveIndex(), w});
270 if (getActiveIndex() > 0)
271 allWindows.insert({getActiveIndex(),
this});
273 if (allWindows.size() >= 2) {
274 const auto lastIt =
std::prev(allWindows.end());
275 const auto prevIt =
std::prev(lastIt);
276 const auto lastW = lastIt->second;
277 const auto prevW = prevIt->second;
280 prevW->requestActivateWindow();
286 return window()->requestedFormat();
291 if (!window ||!window->handle())
293 return static_cast<
QWasmWindow *>(window->handle());
306 return window()->flags();
311 return window()->isModal();
316 window()->setWindowState(Qt::WindowNoState);
321 window()->setWindowState(Qt::WindowMaximized);
326 window()->setWindowState(m_state.testFlag(Qt::WindowMaximized) ? Qt::WindowNoState
327 : Qt::WindowMaximized);
338 QGuiApplicationPrivate::instance()->closeAllPopups();
345 return QWindowSystemInterface::handleMouseEvent(
346 window(), QWasmIntegration::getTimestamp(), window()->mapFromGlobal(pointInScreen),
347 pointInScreen, event.mouseButtons, event.mouseButton,
348 MouseEvent::mouseEventTypeFromEventType(event.type, WindowArea::NonClient),
354 auto initialGeometry = QPlatformWindow::initialGeometry(window(),
355 windowGeometry(), defaultWindowSize, defaultWindowSize);
356 m_normalGeometry = initialGeometry;
358 setWindowState(window()->windowStates());
359 setWindowFlags(window()->flags());
360 setWindowTitle(window()->title());
361 setMask(QHighDpi::toNativeLocalRegion(window()->mask(), window()));
363 if (window()->isTopLevel())
364 setWindowIcon(window()->icon());
365 QPlatformWindow::setGeometry(m_normalGeometry);
367#if QT_CONFIG(accessibility)
370 if (window()->isTopLevel())
371 QWasmAccessibility::addAccessibilityEnableButton(window());
377 return static_cast<
QWasmScreen *>(window()->screen()->handle());
382 if (!m_backingStore || !isVisible() || m_context2d.isUndefined())
385 auto image = m_backingStore->getUpdatedWebImage(
this);
386 if (image.isUndefined())
388 m_context2d.call<
void>(
"putImageData", image, emscripten::val(0), emscripten::val(0));
393 m_decoratedWindow[
"style"].set(
"zIndex", std::to_string(z));
398 m_window[
"style"].set(
"cursor", emscripten::val(cssCursorName.constData()));
403 const auto margins = frameMargins();
405 const QRect clientAreaRect = ([
this, &rect, &margins]() {
406 if (m_state.testFlag(Qt::WindowFullScreen))
407 return platformScreen()->geometry();
408 if (m_state.testFlag(Qt::WindowMaximized))
409 return platformScreen()->availableGeometry().marginsRemoved(frameMargins());
411 auto offset = rect.topLeft() - (!parent() ? screen()->geometry().topLeft() : QPoint());
414 auto containerGeometryInViewport =
415 QRectF::fromDOMRect(parentNode()->containerElement().call<emscripten::val>(
416 "getBoundingClientRect"))
419 auto rectInViewport = QRect(containerGeometryInViewport.topLeft() + offset, rect.size());
421 QRect cappedGeometry(rectInViewport);
424 cappedGeometry.moveTop(
425 std::max(std::min(rectInViewport.y(), containerGeometryInViewport.bottom()),
426 containerGeometryInViewport.y() + margins.top()));
428 cappedGeometry.setSize(
429 cappedGeometry.size().expandedTo(windowMinimumSize()).boundedTo(windowMaximumSize()));
430 return QRect(QPoint(rect.x(), rect.y() + cappedGeometry.y() - rectInViewport.y()),
433 m_nonClientArea->onClientAreaWidthChange(clientAreaRect.width());
435 const auto frameRect =
437 .adjusted(-margins.left(), -margins.top(), margins.right(), margins.bottom())
438 .translated(!parent() ? -screen()->geometry().topLeft() : QPoint());
440 m_decoratedWindow[
"style"].set(
"left", std::to_string(frameRect.left()) +
"px");
441 m_decoratedWindow[
"style"].set(
"top", std::to_string(frameRect.top()) +
"px");
442 m_canvas[
"style"].set(
"width", std::to_string(clientAreaRect.width()) +
"px");
443 m_canvas[
"style"].set(
"height", std::to_string(clientAreaRect.height()) +
"px");
444 m_a11yContainer[
"style"].set(
"width", std::to_string(clientAreaRect.width()) +
"px");
445 m_a11yContainer[
"style"].set(
"height", std::to_string(clientAreaRect.height()) +
"px");
448 m_window[
"style"].set(
"width", std::to_string(clientAreaRect.width()) +
"px");
450 QSizeF canvasSize = clientAreaRect.size() * devicePixelRatio();
452 m_canvas.set(
"width", canvasSize.width());
453 m_canvas.set(
"height", canvasSize.height());
455 bool shouldInvalidate =
true;
456 if (!m_state.testFlag(Qt::WindowFullScreen) && !m_state.testFlag(Qt::WindowMaximized)) {
457 shouldInvalidate = m_normalGeometry.size() != clientAreaRect.size();
458 m_normalGeometry = clientAreaRect;
462 if (wasmInput && (QGuiApplication::focusWindow() == window()))
463 wasmInput->updateGeometry();
465 QWindowSystemInterface::handleGeometryChange(window(), clientAreaRect);
466 if (shouldInvalidate)
469 m_compositor->requestUpdateWindow(
this, QRect(QPoint(0, 0), geometry().size()));
475 const bool nowVisible = m_decoratedWindow[
"style"][
"display"].as<std::string>() ==
"block";
476 if (visible == nowVisible)
480 m_decoratedWindow[
"style"].set(
"display", visible ?
"block" :
"none");
481 if (window() == QGuiApplication::focusWindow())
486#if QT_CONFIG(accessibility)
487 QWasmAccessibility::onShowWindow(window());
494 return window()->isVisible();
499 const auto frameRect =
500 QRectF::fromDOMRect(m_decoratedWindow.call<emscripten::val>(
"getBoundingClientRect"));
501 const auto canvasRect =
502 QRectF::fromDOMRect(m_window.call<emscripten::val>(
"getBoundingClientRect"));
503 return QMarginsF(canvasRect.left() - frameRect.left(), canvasRect.top() - frameRect.top(),
504 frameRect.right() - canvasRect.right(),
505 frameRect.bottom() - canvasRect.bottom())
530 m_nonClientArea->propagateSizeHints();
535 m_decoratedWindow[
"style"].set(
"opacity", qBound(0.0, level, 1.0));
540 m_compositor->requestUpdateWindow(
this, QRect(QPoint(0, 0), geometry().size()));
545 dom::syncCSSClassWith(m_decoratedWindow,
"inactive", !active);
550 flags = fixTopLevelWindowFlags(flags);
552 if ((flags.testFlag(Qt::WindowStaysOnTopHint) != m_flags.testFlag(Qt::WindowStaysOnTopHint))
553 || (flags.testFlag(Qt::WindowStaysOnBottomHint)
554 != m_flags.testFlag(Qt::WindowStaysOnBottomHint))
555 || shouldBeAboveTransientParentFlags(flags) != shouldBeAboveTransientParentFlags(m_flags)) {
556 onPositionPreferenceChanged(positionPreferenceFromWindowFlags(flags));
559 dom::syncCSSClassWith(m_decoratedWindow,
"frameless", !hasFrame() || !window()->isTopLevel());
560 dom::syncCSSClassWith(m_decoratedWindow,
"has-border", hasBorder());
561 dom::syncCSSClassWith(m_decoratedWindow,
"has-shadow", hasShadow());
562 dom::syncCSSClassWith(m_decoratedWindow,
"has-title", hasTitleBar());
563 dom::syncCSSClassWith(m_decoratedWindow,
"transparent-for-input",
564 flags.testFlag(Qt::WindowTransparentForInput));
566 m_nonClientArea->titleBar()->setMaximizeVisible(hasMaximizeButton());
567 m_nonClientArea->titleBar()->setCloseVisible(m_flags.testFlag(Qt::WindowCloseButtonHint));
574 newState &= Qt::WindowActive;
576 const Qt::WindowStates oldState = m_state;
578 if (newState.testFlag(Qt::WindowMinimized)) {
579 newState.setFlag(Qt::WindowMinimized,
false);
580 qWarning(
"Qt::WindowMinimized is not implemented in wasm");
581 window()->setWindowStates(newState);
585 if (newState == oldState)
589 m_previousWindowState = oldState;
596 m_nonClientArea->titleBar()->setTitle(title);
601 const auto dpi = screen()->devicePixelRatio();
602 auto pixmap = icon.pixmap(10 * dpi, 10 * dpi);
603 if (pixmap.isNull()) {
604 m_nonClientArea->titleBar()->setIcon(
605 Base64IconStore::get()->getIcon(Base64IconStore::IconType::QtLogo),
"svg+xml");
610 QBuffer buffer(&bytes);
611 pixmap.save(&buffer,
"png");
612 m_nonClientArea->titleBar()->setIcon(bytes.toBase64().toStdString(),
"png");
619 const bool isFullscreen = m_state.testFlag(Qt::WindowFullScreen);
620 const bool isMaximized = m_state.testFlag(Qt::WindowMaximized);
623 else if (isMaximized)
624 newGeom = platformScreen()->availableGeometry().marginsRemoved(frameMargins());
628 dom::syncCSSClassWith(m_decoratedWindow,
"has-border", hasBorder());
629 dom::syncCSSClassWith(m_decoratedWindow,
"maximized", isMaximized);
631 m_nonClientArea->titleBar()->setRestoreVisible(isMaximized);
632 m_nonClientArea->titleBar()->setMaximizeVisible(hasMaximizeButton());
635 QWindowSystemInterface::handleWindowStateChanged(window(), m_state, m_previousWindowState);
639void QWasmWindow::commitParent(QWasmWindowTreeNode *parent)
641 onParentChanged(m_commitedParent, parent, positionPreferenceFromWindowFlags(window()->flags()));
642 m_commitedParent = parent;
647 qCDebug(qLcQpaWasmInputContext) <<
"handleKeyEvent";
649 if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive()) {
650 handleKeyForInputContextEvent(event);
652 if (processKey(event)) {
653 event.webEvent.call<
void>(
"preventDefault");
654 event.webEvent.call<
void>(
"stopPropagation");
661 constexpr bool ProceedToNativeEvent =
false;
664#if QT_CONFIG(clipboard)
665 const auto clipboardResult =
666 QWasmIntegration::get()->getWasmClipboard()->processKeyboard(event);
668 using ProcessKeyboardResult = QWasmClipboard::ProcessKeyboardResult;
669 if (clipboardResult == ProcessKeyboardResult::NativeClipboardEventNeeded)
670 return ProceedToNativeEvent;
673 const auto result = QWindowSystemInterface::handleKeyEvent(
674 0, event.type == EventType::KeyDown ? QEvent::KeyPress : QEvent::KeyRelease, event.key,
675 event.modifiers, event.text, event.autoRepeat);
677#if QT_CONFIG(clipboard)
678 return clipboardResult == ProcessKeyboardResult::NativeClipboardEventAndCopiedDataNeeded
679 ? ProceedToNativeEvent
697 bool useInputContext = [event]() ->
bool {
702 const auto keyString = QString::fromStdString(event[
"key"].as<std::string>());
703 qCDebug(qLcQpaWasmInputContext) <<
"Key callback" << keyString << keyString.size();
706 bool composing = event[
"isComposing"].as<
bool>();
710 bool androidUnidentified = (keyString ==
"Unidentified");
715 bool hasModifiers = event[
"ctrlKey"].as<
bool>()
716 || event[
"altKey"].as<
bool>()
717 || event[
"metaKey"].as<
bool>();
721 bool hasNoncharacterKeyString = keyString.size() != 1;
723 bool overrideCompose = !hasModifiers && !hasNoncharacterKeyString && wasmInput->inputMethodAccepted();
724 return composing || androidUnidentified || overrideCompose;
727 if (!useInputContext) {
728 qCDebug(qLcQpaWasmInputContext) <<
"processKey as KeyEvent";
729 if (processKeyForInputContext(keyEvent))
730 event.call<
void>(
"preventDefault");
731 event.call<
void>(
"stopImmediatePropagation");
737 qCDebug(qLcQpaWasmInputContext) << Q_FUNC_INFO;
740 QKeySequence keySeq(event.modifiers | event.key);
742 if (keySeq == QKeySequence::Paste) {
747 const auto result = QWindowSystemInterface::handleKeyEvent(
748 0, event.type == EventType::KeyDown ? QEvent::KeyPress : QEvent::KeyRelease, event.key,
749 event.modifiers, event.text);
751#if QT_CONFIG(clipboard)
753 if (keySeq == QKeySequence::Copy || keySeq == QKeySequence::Cut)
762 if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive())
763 inputContext->inputCallback(event);
765 m_focusHelper.set(
"innerHTML", std::string());
770 if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive())
771 inputContext->compositionStartCallback(event);
773 m_focusHelper.set(
"innerHTML", std::string());
778 if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive())
779 inputContext->compositionUpdateCallback(event);
781 m_focusHelper.set(
"innerHTML", std::string());
786 if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive())
787 inputContext->compositionEndCallback(event);
789 m_focusHelper.set(
"innerHTML", std::string());
794 if (processPointerEnterLeave(event))
795 event.webEvent.call<
void>(
"preventDefault");
803 switch (event
.type) {
807 QWindowSystemInterface::handleEnterEvent(
808 window(), mapFromGlobal(pointInScreen.toPoint()), pointInScreen);
823 switch (event
.type) {
824 case EventType::PointerDown:
825 if (event.isTargetedForQtElement())
826 m_window.call<
void>(
"setPointerCapture", event.pointerId);
828 if ((window()->flags() & Qt::WindowDoesNotAcceptFocus)
829 != Qt::WindowDoesNotAcceptFocus
830 && window()->isTopLevel())
831 window()->requestActivate();
833 case EventType::PointerUp:
834 if (event.isTargetedForQtElement())
835 m_window.call<
void>(
"releasePointerCapture", event.pointerId);
841 const bool eventAccepted = deliverPointerEvent(event);
842 if (!eventAccepted && event.type == EventType::PointerDown)
843 QGuiApplicationPrivate::instance()->closeAllPopups();
846 event.webEvent.call<
void>(
"preventDefault");
847 event.webEvent.call<
void>(
"stopPropagation");
857 const QPointF targetPointClippedToScreen(
858 qBound(geometryF.left(), pointInScreen.x(), geometryF.right()),
859 qBound(geometryF.top(), pointInScreen.y(), geometryF.bottom()));
862 const QEvent::Type eventType =
865 return eventType != QEvent::None
866 && QWindowSystemInterface::handleMouseEvent(
867 window(), QWasmIntegration::getTimestamp(),
868 window()->mapFromGlobal(targetPointClippedToScreen),
869 targetPointClippedToScreen, event.mouseButtons, event.mouseButton,
870 eventType, event.modifiers);
875 switch (event
.type) {
878 pressure = event.pressure;
887 qreal xTilt = qBound(-60.0, event.tiltX, 60.0);
888 qreal yTilt = qBound(-60.0, event.tiltY, 60.0);
890 qreal rotation = event.twist > 180.0 ? 360.0 - event.twist : event.twist;
891 return QWindowSystemInterface::handleTabletEvent(
892 window(), QWasmIntegration::getTimestamp(), platformScreen()->tabletDevice(),
893 window()->mapFromGlobal(targetPointClippedToScreen),
894 targetPointClippedToScreen, event.mouseButtons, pressure, xTilt, yTilt,
895 event.tangentialPressure, rotation, event.modifiers);
898 QWindowSystemInterface::TouchPoint *touchPoint;
900 QPointF pointInTargetWindowCoords =
901 QPointF(window()->mapFromGlobal(targetPointClippedToScreen));
902 QPointF normalPosition(pointInTargetWindowCoords.x() / window()->width(),
903 pointInTargetWindowCoords.y() / window()->height());
905 const auto tp = m_pointerIdToTouchPoints.find(event.pointerId);
906 if (event.pointerType != PointerType::Pen && tp != m_pointerIdToTouchPoints.end()) {
907 touchPoint = &tp.value();
909 touchPoint = &m_pointerIdToTouchPoints
910 .insert(event.pointerId, QWindowSystemInterface::TouchPoint())
918 touchPoint->state = QEventPoint::State::Pressed;
921 const bool stationaryTouchPoint = (normalPosition == touchPoint->normalPosition);
922 touchPoint->normalPosition = normalPosition;
923 touchPoint->area = QRectF(targetPointClippedToScreen, QSizeF(event.width, event.height))
924 .translated(-event.width / 2, -event.height / 2);
925 touchPoint->pressure = event.pressure;
927 switch (event
.type) {
928 case EventType::PointerUp:
929 touchPoint->state = QEventPoint::State::Released;
931 case EventType::PointerMove:
932 touchPoint->state = (stationaryTouchPoint ? QEventPoint::State::Stationary
933 : QEventPoint::State::Updated);
939 QList<QWindowSystemInterface::TouchPoint> touchPointList;
940 touchPointList.reserve(m_pointerIdToTouchPoints.size());
941 std::transform(m_pointerIdToTouchPoints.begin(), m_pointerIdToTouchPoints.end(),
942 std::back_inserter(touchPointList),
943 [](
const QWindowSystemInterface::TouchPoint &val) {
return val; });
945 if (event.type == EventType::PointerUp)
946 m_pointerIdToTouchPoints.remove(event.pointerId);
948 return event.type == EventType::PointerCancel
949 ? QWindowSystemInterface::handleTouchCancelEvent(
950 window(), QWasmIntegration::getTimestamp(), platformScreen()->touchDevice(),
952 : QWindowSystemInterface::handleTouchEvent(
953 window(), QWasmIntegration::getTimestamp(), platformScreen()->touchDevice(),
954 touchPointList, event.modifiers);
960 event.call<
void>(
"preventDefault");
966 const int scrollFactor = -([&event]() {
980 return QWindowSystemInterface::handleWheelEvent(
981 window(), QWasmIntegration::getTimestamp(), window()->mapFromGlobal(pointInScreen),
982 pointInScreen, (event.delta * scrollFactor).toPoint(),
983 (event.delta * scrollFactor).toPoint(), event.modifiers, Qt::NoScrollPhase,
984 Qt::MouseEventNotSynthesized, event.webkitDirectionInvertedFromDevice);
988Qt::WindowFlags
QWasmWindow::fixTopLevelWindowFlags(Qt::WindowFlags flags)
const
990 if (!(flags.testFlag(Qt::CustomizeWindowHint))) {
991 if (flags.testFlag(Qt::Window)) {
992 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint
993 |Qt::WindowMaximizeButtonHint|Qt::WindowCloseButtonHint;
995 if (flags.testFlag(Qt::Dialog) || flags.testFlag(Qt::Tool))
996 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
998 if ((flags & Qt::WindowType_Mask) == Qt::SplashScreen)
999 flags |= Qt::FramelessWindowHint;
1004bool QWasmWindow::shouldBeAboveTransientParentFlags(Qt::WindowFlags flags)
const
1012 if (flags.testFlag(Qt::Tool) ||
1013 flags.testFlag(Qt::SplashScreen) ||
1014 flags.testFlag(Qt::ToolTip) ||
1015 flags.testFlag(Qt::Popup))
1023QWasmWindowStack<>::PositionPreference
QWasmWindow::positionPreferenceFromWindowFlags(Qt::WindowFlags flags)
const
1025 flags = fixTopLevelWindowFlags(flags);
1027 if (flags.testFlag(Qt::WindowStaysOnTopHint))
1028 return QWasmWindowStack<>::PositionPreference::StayOnTop;
1029 if (flags.testFlag(Qt::WindowStaysOnBottomHint))
1030 return QWasmWindowStack<>::PositionPreference::StayOnBottom;
1031 if (shouldBeAboveTransientParentFlags(flags))
1032 return QWasmWindowStack<>::PositionPreference::StayAboveTransientParent;
1033 return QWasmWindowStack<>::PositionPreference::Regular;
1038 return m_normalGeometry;
1043 return screen()->devicePixelRatio();
1053 return !m_flags.testFlag(Qt::FramelessWindowHint);
1058 return hasFrame() && !m_state.testFlag(Qt::WindowFullScreen) && !m_flags.testFlag(Qt::SubWindow)
1059 && !windowIsPopupType(m_flags) && !parent();
1064 return hasBorder() && m_flags.testFlag(Qt::WindowTitleHint);
1069 return hasBorder() && !m_flags.testFlag(Qt::NoDropShadowWindowHint);
1074 return !m_state.testFlag(Qt::WindowMaximized) && m_flags.testFlag(Qt::WindowMaximizeButtonHint);
1077bool QWasmWindow::windowIsPopupType(Qt::WindowFlags flags)
const
1079 if (flags.testFlag(Qt::Tool))
1082 return (flags.testFlag(Qt::Popup));
1087 QWindow *modalWindow;
1088 if (QGuiApplicationPrivate::instance()->isWindowBlocked(window(), &modalWindow)) {
1098 QPlatformWindow::requestActivateWindow();
1103 if (QWasmAccessibility::isEnabled())
1106 m_focusHelper.call<
void>(
"focus");
1111 m_focusHelper.call<
void>(
"setAttribute", std::string(
"aria-hidden"), std::string(
"true"));
1112 m_inputElement.call<
void>(
"setAttribute", std::string(
"aria-hidden"), std::string(
"true"));
1123 switch (event->type()) {
1124 case QEvent::WindowBlocked:
1125 m_decoratedWindow[
"classList"].call<
void>(
"add", emscripten::val(
"blocked"));
1127 case QEvent::WindowUnblocked:;
1128 m_decoratedWindow[
"classList"].call<
void>(
"remove", emscripten::val(
"blocked"));
1131 return QPlatformWindow::windowEvent(event);
1137 if (region.isEmpty()) {
1138 m_decoratedWindow[
"style"].set(
"clipPath", emscripten::val(
""));
1142 std::ostringstream cssClipPath;
1143 cssClipPath <<
"path('";
1144 for (
const auto &rect : region) {
1145 const auto cssRect = rect.adjusted(0, 0, 1, 1);
1146 cssClipPath <<
"M " << cssRect.left() <<
" " << cssRect.top() <<
" ";
1147 cssClipPath <<
"L " << cssRect.right() <<
" " << cssRect.top() <<
" ";
1148 cssClipPath <<
"L " << cssRect.right() <<
" " << cssRect.bottom() <<
" ";
1149 cssClipPath <<
"L " << cssRect.left() <<
" " << cssRect.bottom() <<
" z ";
1151 cssClipPath <<
"')";
1152 m_decoratedWindow[
"style"].set(
"clipPath", emscripten::val(cssClipPath.str()));
1155void QWasmWindow::onTransientParentChanged(QWindow *newTransientParent)
1157 Q_UNUSED(newTransientParent);
1159 const auto positionPreference = positionPreferenceFromWindowFlags(window()->flags());
1160 QWasmWindowTreeNode::onParentChanged(parentNode(),
nullptr, positionPreference);
1161 QWasmWindowTreeNode::onParentChanged(
nullptr, parentNode(), positionPreference);
1166 const auto positionPreference = positionPreferenceFromWindowFlags(window()->flags());
1167 QWasmWindowTreeNode::onParentChanged(parentNode(),
nullptr, positionPreference);
1168 QWasmWindowTreeNode::onParentChanged(
nullptr, parentNode(), positionPreference);
1175 setWindowFlags(window()->flags());
1177 commitParent(parentNode());
1182 return "!qtwindow" + std::to_string(m_winId);
1203 QWasmWindowStack<>::PositionPreference positionPreference)
1206 previous->containerElement().call<
void>(
"removeChild", m_decoratedWindow);
1208 current->containerElement().call<
void>(
"appendChild", m_decoratedWindow);
1209 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)