Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qwasmwindow.cpp
Go to the documentation of this file.
1// Copyright (C) 2018 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
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>
12#include <QBuffer>
13
15#include "qwasmdom.h"
16#if QT_CONFIG(clipboard)
17#include "qwasmclipboard.h"
18#endif
21#include "qwasmwindow.h"
22#include "qwasmscreen.h"
24#include "qwasmevent.h"
27#if QT_CONFIG(draganddrop)
28#include "qwasmdrag.h"
29#endif
31
32#include <iostream>
33#include <sstream>
34
35#include <emscripten/val.h>
36
37#include <QtCore/private/qstdweb_p.h>
38#include <QKeySequence>
39
41
43
45 QWasmCompositor *compositor, QWasmBackingStore *backingStore,
46 WId nativeHandle)
48 m_compositor(compositor),
49 m_backingStore(backingStore),
51 m_decoratedWindow(m_document.call<emscripten::val>("createElement", emscripten::val("div"))),
52 m_window(m_document.call<emscripten::val>("createElement", emscripten::val("div"))),
53 m_a11yContainer(m_document.call<emscripten::val>("createElement", emscripten::val("div"))),
54 m_canvas(m_document.call<emscripten::val>("createElement", emscripten::val("canvas"))),
55 m_focusHelper(m_document.call<emscripten::val>("createElement", emscripten::val("div"))),
56 m_inputElement(m_document.call<emscripten::val>("createElement", emscripten::val("input")))
57
58{
59 m_decoratedWindow.set("className", "qt-decorated-window");
60 m_decoratedWindow["style"].set("display", std::string("none"));
61
62 m_nonClientArea = std::make_unique<NonClientArea>(this, m_decoratedWindow);
63 m_nonClientArea->titleBar()->setTitle(window()->title());
64
65 // If we are wrapping a foregin window, a.k.a. a native html element then that element becomes
66 // the m_window element. In this case setting up event handlers and accessibility etc is not
67 // needed since that is (presumably) handled by the native html element.
68 //
69 // The WId is an emscripten::val *, owned by QWindow user code. We dereference and make
70 // a copy of the val here and don't strictly need it to be kept alive, but that's an
71 // implementation detail. The pointer will be dereferenced again if the window is destroyed
72 // and recreated.
73 if (nativeHandle) {
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);
78 return;
79 }
80
81 m_window.set("className", "qt-window");
82 m_decoratedWindow.call<void>("appendChild", m_window);
83
84 m_canvas["classList"].call<void>("add", emscripten::val("qt-window-canvas"));
85
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);
91 }
92#endif
93
94 // Set up m_focusHelper, which is an invisible child element of the window which takes
95 // focus on behalf of the window any time the window has focus in general, but none
96 // of the special child elements such as the inputElment or a11y elements have focus.
97 // Set inputMode=none set to prevent the virtual keyboard from popping up.
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);
109
110 // Set up m_inputElement, which takes focus whenever a Qt text input UI element has
111 // foucus.
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);
124
125 // The canvas displays graphics only, and is not accessible or an event target
126 m_canvas.call<void>("setAttribute", std::string("aria-hidden"), std::string("true"));
127 m_canvas["style"].set("pointerEvents", "none");
128
129 m_window.call<void>("appendChild", m_canvas);
130
131 m_a11yContainer["classList"].call<void>("add", emscripten::val("qt-window-a11y-container"));
132 m_window.call<void>("appendChild", m_a11yContainer);
133
134 if (QWasmAccessibility::isEnabled())
136
137 const bool rendersTo2dContext = w->surfaceType() != QSurface::OpenGLSurface;
138 if (rendersTo2dContext)
139 m_context2d = m_canvas.call<emscripten::val>("getContext", emscripten::val("2d"));
140
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);
144
145 m_flags = window()->flags();
146
148
149 m_transientWindowChangedConnection =
150 QObject::connect(
151 window(), &QWindow::transientParentChanged,
152 window(), [this](QWindow *tp) { onTransientParentChanged(tp); });
153
154 m_modalityChangedConnection =
155 QObject::connect(
156 window(), &QWindow::modalityChanged,
157 window(), [this](Qt::WindowModality) { onModalityChanged(); });
158
159 setParent(parent());
160}
161
163{
164 m_pointerDownCallback = QWasmEventHandler(m_window, "pointerdown",
165 [this](emscripten::val event){ processPointer(PointerEvent(EventType::PointerDown, event)); }
166 );
167 m_pointerMoveCallback = QWasmEventHandler(m_window, "pointermove",
168 [this](emscripten::val event){ processPointer(PointerEvent(EventType::PointerMove, event)); }
169 );
170 m_pointerUpCallback = QWasmEventHandler(m_window, "pointerup",
171 [this](emscripten::val event){ processPointer(PointerEvent(EventType::PointerUp, event)); }
172 );
173 m_pointerCancelCallback = QWasmEventHandler(m_window, "pointercancel",
174 [this](emscripten::val event){ processPointer(PointerEvent(EventType::PointerCancel, event)); }
175 );
176 m_pointerEnterCallback = QWasmEventHandler(m_window, "pointerenter",
177 [this](emscripten::val event) { this->handlePointerEnterLeaveEvent(PointerEvent(EventType::PointerEnter, event)); }
178 );
179 m_pointerLeaveCallback = QWasmEventHandler(m_window, "pointerleave",
180 [this](emscripten::val event) { this->handlePointerEnterLeaveEvent(PointerEvent(EventType::PointerLeave, event)); }
181 );
182
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);
189 }
190 );
191 m_dragOverCallback = QWasmEventHandler(m_window, "dragover",
192 [this](emscripten::val event) {
193 DragEvent dragEvent(EventType::DragOver, event, window());
194 QWasmDrag::instance()->onNativeDragOver(&dragEvent);
195 }
196 );
197 m_dropCallback = QWasmEventHandler(m_window, "drop",
198 [this](emscripten::val event) {
199 DragEvent dragEvent(EventType::Drop, event, window());
200 QWasmDrag::instance()->onNativeDrop(&dragEvent);
201 }
202 );
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);
208 }
209 );
210 m_dragEnterCallback = QWasmEventHandler(m_window, "dragenter",
211 [this](emscripten::val event) {
212 DragEvent dragEvent(EventType::DragEnter, event, window());
213 QWasmDrag::instance()->onNativeDragEnter(&dragEvent);
214 }
215 );
216 m_dragLeaveCallback = QWasmEventHandler(m_window, "dragleave",
217 [this](emscripten::val event) {
218 DragEvent dragEvent(EventType::DragLeave, event, window());
219 QWasmDrag::instance()->onNativeDragLeave(&dragEvent);
220 }
221 );
222#endif // QT_CONFIG(draganddrop)
223
224 m_wheelEventCallback = QWasmEventHandler(m_window, "wheel",
225 [this](emscripten::val event) { this->handleWheelEvent(event); });
226
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)); });
231
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); });
242 }
243
245{
247
248#if QT_CONFIG(accessibility)
249 QWasmAccessibility::onRemoveWindow(window());
250#endif
251 QObject::disconnect(m_transientWindowChangedConnection);
252 QObject::disconnect(m_modalityChangedConnection);
253
254 shutdown();
255
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);
263}
264
265void QWasmWindow::shutdown()
266{
267 if (!window() ||
268 (QGuiApplication::focusWindow() && // Don't act if we have a focus window different from this
269 QGuiApplication::focusWindow() != window()))
270 return;
271
272 // Make a list of all windows sorted on active index.
273 // Skip windows with active index 0 as they have
274 // never been active.
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});
279 }
280
281 // window is not in all windows
282 if (getActiveIndex() > 0)
283 allWindows.insert({getActiveIndex(), this});
284
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;
290
291 if (lastW == this) // Only act if window is last to be active
292 prevW->requestActivateWindow();
293 }
294}
295
297{
298 return window()->requestedFormat();
299}
300
301QWasmWindow *QWasmWindow::fromWindow(const QWindow *window)
302{
303 if (!window ||!window->handle())
304 return nullptr;
305 return static_cast<QWasmWindow *>(window->handle());
306}
307
309{
310 if (!window())
311 return nullptr;
312
313 return fromWindow(window()->transientParent());
314}
315
317{
318 return window()->flags();
319}
320
321bool QWasmWindow::isModal() const
322{
323 return window()->isModal();
324}
325
327{
328 window()->setWindowState(Qt::WindowNoState);
329}
330
332{
333 window()->setWindowState(Qt::WindowMaximized);
334}
335
337{
338 window()->setWindowState(m_state.testFlag(Qt::WindowMaximized) ? Qt::WindowNoState
339 : Qt::WindowMaximized);
340}
341
343{
344 window()->close();
345}
346
348{
350 QGuiApplicationPrivate::instance()->closeAllPopups();
351}
352
354{
355 QPointF pointInScreen = platformScreen()->mapFromLocal(
356 dom::mapPoint(event.target(), platformScreen()->element(), event.localPoint));
357 return QWindowSystemInterface::handleMouseEvent(
358 window(), QWasmIntegration::getTimestamp(), window()->mapFromGlobal(pointInScreen),
359 pointInScreen, event.mouseButtons, event.mouseButton,
360 MouseEvent::mouseEventTypeFromEventType(event.type, WindowArea::NonClient),
361 event.modifiers);
362}
363
365{
366 auto initialGeometry = QPlatformWindow::initialGeometry(window(),
367 windowGeometry(), defaultWindowSize, defaultWindowSize);
368 m_normalGeometry = initialGeometry;
369
370 setWindowState(window()->windowStates());
371 setWindowFlags(window()->flags());
372 setWindowTitle(window()->title());
373 setMask(QHighDpi::toNativeLocalRegion(window()->mask(), window()));
374
375 if (window()->isTopLevel())
376 setWindowIcon(window()->icon());
377 QPlatformWindow::setGeometry(m_normalGeometry);
378
379#if QT_CONFIG(accessibility)
380 // Add accessibility-enable button. The user can activate this
381 // button to opt-in to accessibility.
382 if (window()->isTopLevel())
383 QWasmAccessibility::addAccessibilityEnableButton(window());
384#endif
385}
386
388{
389 return static_cast<QWasmScreen *>(window()->screen()->handle());
390}
391
393{
394 if (!m_backingStore || !isVisible() || m_context2d.isUndefined())
395 return;
396
397 auto image = m_backingStore->getUpdatedWebImage(this);
398 if (image.isUndefined())
399 return;
400 m_context2d.call<void>("putImageData", image, emscripten::val(0), emscripten::val(0));
401}
402
404{
405 m_decoratedWindow["style"].set("zIndex", std::to_string(z));
406}
407
408void QWasmWindow::setWindowCursor(QByteArray cssCursorName)
409{
410 m_window["style"].set("cursor", emscripten::val(cssCursorName.constData()));
411}
412
413void QWasmWindow::setGeometry(const QRect &rect)
414{
415 const auto margins = frameMargins();
416
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());
422
423 auto offset = rect.topLeft() - (!parent() ? screen()->geometry().topLeft() : QPoint());
424
425 // In viewport
426 auto containerGeometryInViewport =
427 QRectF::fromDOMRect(parentNode()->containerElement().call<emscripten::val>(
428 "getBoundingClientRect"))
429 .toRect();
430
431 auto rectInViewport = QRect(containerGeometryInViewport.topLeft() + offset, rect.size());
432
433 QRect cappedGeometry(rectInViewport);
434 if (!parent()) {
435 // Clamp top level windows top position to the screen bounds
436 cappedGeometry.moveTop(
437 std::max(std::min(rectInViewport.y(), containerGeometryInViewport.bottom()),
438 containerGeometryInViewport.y() + margins.top()));
439 }
440 cappedGeometry.setSize(
441 cappedGeometry.size().expandedTo(windowMinimumSize()).boundedTo(windowMaximumSize()));
442 return QRect(QPoint(rect.x(), rect.y() + cappedGeometry.y() - rectInViewport.y()),
443 rect.size());
444 })();
445 m_nonClientArea->onClientAreaWidthChange(clientAreaRect.width());
446
447 const auto frameRect =
448 clientAreaRect
449 .adjusted(-margins.left(), -margins.top(), margins.right(), margins.bottom())
450 .translated(!parent() ? -screen()->geometry().topLeft() : QPoint());
451
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");
458
459 // Important for the title flexbox to shrink correctly
460 m_window["style"].set("width", std::to_string(clientAreaRect.width()) + "px");
461
462 QSizeF canvasSize = clientAreaRect.size() * devicePixelRatio();
463
464 m_canvas.set("width", canvasSize.width());
465 m_canvas.set("height", canvasSize.height());
466
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;
471 }
472
473 QWasmInputContext *wasmInput = QWasmIntegration::get()->wasmInputContext();
474 if (wasmInput && (QGuiApplication::focusWindow() == window()))
475 wasmInput->updateGeometry();
476
477 QWindowSystemInterface::handleGeometryChange(window(), clientAreaRect);
478 if (shouldInvalidate)
479 invalidate();
480 else
481 m_compositor->requestUpdateWindow(this, QRect(QPoint(0, 0), geometry().size()));
482}
483
484void QWasmWindow::setVisible(bool visible)
485{
486 // TODO(mikolajboc): isVisible()?
487 const bool nowVisible = m_decoratedWindow["style"]["display"].as<std::string>() == "block";
488 if (visible == nowVisible)
489 return;
490
491 m_compositor->requestUpdateWindow(this, QRect(QPoint(0, 0), geometry().size()), QWasmCompositor::ExposeEventDelivery);
492 m_decoratedWindow["style"].set("display", visible ? "block" : "none");
493 if (window() == QGuiApplication::focusWindow())
494 focus();
495
496 if (visible) {
497 applyWindowState();
498#if QT_CONFIG(accessibility)
499 QWasmAccessibility::onShowWindow(window());
500#endif
501 }
502}
503
505{
506 return window()->isVisible();
507}
508
510{
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())
518 .toMargins();
519}
520
522{
523 bringToTop();
524 invalidate();
525}
526
528{
529 sendToBottom();
530 invalidate();
531}
532
534{
535 return m_winId;
536}
537
539{
540 // setGeometry() will take care of minimum and maximum size constraints
541 setGeometry(windowGeometry());
542 m_nonClientArea->propagateSizeHints();
543}
544
545void QWasmWindow::setOpacity(qreal level)
546{
547 m_decoratedWindow["style"].set("opacity", qBound(0.0, level, 1.0));
548}
549
550void QWasmWindow::invalidate()
551{
552 m_compositor->requestUpdateWindow(this, QRect(QPoint(0, 0), geometry().size()));
553}
554
556{
557 dom::syncCSSClassWith(m_decoratedWindow, "inactive", !active);
558}
559
560void QWasmWindow::setWindowFlags(Qt::WindowFlags flags)
561{
562 flags = fixTopLevelWindowFlags(flags);
563
564 if ((flags.testFlag(Qt::WindowStaysOnTopHint) != m_flags.testFlag(Qt::WindowStaysOnTopHint))
565 || (flags.testFlag(Qt::WindowStaysOnBottomHint)
566 != m_flags.testFlag(Qt::WindowStaysOnBottomHint))
567 || shouldBeAboveTransientParentFlags(flags) != shouldBeAboveTransientParentFlags(m_flags)) {
568 onPositionPreferenceChanged(positionPreferenceFromWindowFlags(flags));
569 }
570 m_flags = flags;
571 dom::syncCSSClassWith(m_decoratedWindow, "frameless", !hasFrame() || !window()->isTopLevel());
572 dom::syncCSSClassWith(m_decoratedWindow, "has-border", hasBorder());
573 dom::syncCSSClassWith(m_decoratedWindow, "has-shadow", hasShadow());
574 dom::syncCSSClassWith(m_decoratedWindow, "has-title", hasTitleBar());
575 dom::syncCSSClassWith(m_decoratedWindow, "transparent-for-input",
576 flags.testFlag(Qt::WindowTransparentForInput));
577
578 m_nonClientArea->titleBar()->setMaximizeVisible(hasMaximizeButton());
579 m_nonClientArea->titleBar()->setCloseVisible(m_flags.testFlag(Qt::WindowCloseButtonHint));
580}
581
582void QWasmWindow::setWindowState(Qt::WindowStates newState)
583{
584 // Child windows can not have window states other than Qt::WindowActive
585 if (parent())
586 newState &= Qt::WindowActive;
587
588 const Qt::WindowStates oldState = m_state;
589
590 if (newState.testFlag(Qt::WindowMinimized)) {
591 newState.setFlag(Qt::WindowMinimized, false);
592 qWarning("Qt::WindowMinimized is not implemented in wasm");
593 window()->setWindowStates(newState);
594 return;
595 }
596
597 if (newState == oldState)
598 return;
599
600 m_state = newState;
601 m_previousWindowState = oldState;
602
603 applyWindowState();
604}
605
606void QWasmWindow::setWindowTitle(const QString &title)
607{
608 m_nonClientArea->titleBar()->setTitle(title);
609}
610
611void QWasmWindow::setWindowIcon(const QIcon &icon)
612{
613 const auto dpi = screen()->devicePixelRatio();
614 auto pixmap = icon.pixmap(10 * dpi, 10 * dpi);
615 if (pixmap.isNull()) {
616 m_nonClientArea->titleBar()->setIcon(
617 Base64IconStore::get()->getIcon(Base64IconStore::IconType::QtLogo), "svg+xml");
618 return;
619 }
620
621 QByteArray bytes;
622 QBuffer buffer(&bytes);
623 pixmap.save(&buffer, "png");
624 m_nonClientArea->titleBar()->setIcon(bytes.toBase64().toStdString(), "png");
625}
626
627void QWasmWindow::applyWindowState()
628{
629 QRect newGeom;
630
631 const bool isFullscreen = m_state.testFlag(Qt::WindowFullScreen);
632 const bool isMaximized = m_state.testFlag(Qt::WindowMaximized);
633 if (isFullscreen)
634 newGeom = platformScreen()->geometry();
635 else if (isMaximized)
636 newGeom = platformScreen()->availableGeometry().marginsRemoved(frameMargins());
637 else
638 newGeom = normalGeometry();
639
640 dom::syncCSSClassWith(m_decoratedWindow, "has-border", hasBorder());
641 dom::syncCSSClassWith(m_decoratedWindow, "maximized", isMaximized);
642
643 m_nonClientArea->titleBar()->setRestoreVisible(isMaximized);
644 m_nonClientArea->titleBar()->setMaximizeVisible(hasMaximizeButton());
645
646 if (isVisible())
647 QWindowSystemInterface::handleWindowStateChanged(window(), m_state, m_previousWindowState);
648 setGeometry(newGeom);
649}
650
651void QWasmWindow::commitParent(QWasmWindowTreeNode *parent)
652{
653 onParentChanged(m_commitedParent, parent, positionPreferenceFromWindowFlags(window()->flags()));
654 m_commitedParent = parent;
655}
656
657void QWasmWindow::handleKeyEvent(const KeyEvent &event)
658{
659 qCDebug(qLcQpaWasmInputContext) << "handleKeyEvent";
660
661 if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive()) {
662 handleKeyForInputContextEvent(event);
663 } else {
664 if (processKey(event)) {
665 event.webEvent.call<void>("preventDefault");
666 event.webEvent.call<void>("stopPropagation");
667 }
668 }
669}
670
671bool QWasmWindow::processKey(const KeyEvent &event)
672{
673 constexpr bool ProceedToNativeEvent = false;
674 Q_ASSERT(event.type == EventType::KeyDown || event.type == EventType::KeyUp);
675
676#if QT_CONFIG(clipboard)
677 const auto clipboardResult =
678 QWasmIntegration::get()->getWasmClipboard()->processKeyboard(event);
679
680 using ProcessKeyboardResult = QWasmClipboard::ProcessKeyboardResult;
681 if (clipboardResult == ProcessKeyboardResult::NativeClipboardEventNeeded)
682 return ProceedToNativeEvent;
683#endif
684
685 const auto result = QWindowSystemInterface::handleKeyEvent(
686 0, event.type == EventType::KeyDown ? QEvent::KeyPress : QEvent::KeyRelease, event.key,
687 event.modifiers, event.text, event.autoRepeat);
688
689#if QT_CONFIG(clipboard)
690 return clipboardResult == ProcessKeyboardResult::NativeClipboardEventAndCopiedDataNeeded
691 ? ProceedToNativeEvent
692 : result;
693#else
694 return result;
695#endif
696}
697
698void QWasmWindow::handleKeyForInputContextEvent(const KeyEvent &keyEvent)
699{
700 // Don't send Qt key events if the key event is a part of input composition,
701 // let those be handled by by the input event key handler. Check for the
702 // keyCode 229 as well as isComposing in order catch all cases (see mdn
703 // docs for the keyDown event)
704 if (keyEvent.isComposing || keyEvent.keyCode == 229)
705 return;
706
707 qCDebug(qLcQpaWasmInputContext) << "processKey as KeyEvent";
708 emscripten::val event = keyEvent.webEvent;
709 if (processKeyForInputContext(keyEvent))
710 event.call<void>("preventDefault");
711 event.call<void>("stopImmediatePropagation");
712}
713
714bool QWasmWindow::processKeyForInputContext(const KeyEvent &event)
715{
716 qCDebug(qLcQpaWasmInputContext) << Q_FUNC_INFO;
717 Q_ASSERT(event.type == EventType::KeyDown || event.type == EventType::KeyUp);
718
719 QKeySequence keySeq(event.modifiers | event.key);
720
721 if (keySeq == QKeySequence::Paste) {
722 // Process it in pasteCallback and inputCallback
723 return false;
724 }
725
726 const auto result = QWindowSystemInterface::handleKeyEvent(
727 0, event.type == EventType::KeyDown ? QEvent::KeyPress : QEvent::KeyRelease, event.key,
728 event.modifiers, event.text);
729
730#if QT_CONFIG(clipboard)
731 // Copy/Cut callback required to copy qtClipboard to system clipboard
732 if (keySeq == QKeySequence::Copy || keySeq == QKeySequence::Cut)
733 return false;
734#endif
735
736 return result;
737}
738
739void QWasmWindow::handleInputEvent(emscripten::val event)
740{
741 if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive())
742 inputContext->inputCallback(event);
743 else
744 m_focusHelper.set("innerHTML", std::string());
745}
746
747void QWasmWindow::handleCompositionStartEvent(emscripten::val event)
748{
749 if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive())
750 inputContext->compositionStartCallback(event);
751 else
752 m_focusHelper.set("innerHTML", std::string());
753}
754
755void QWasmWindow::handleCompositionUpdateEvent(emscripten::val event)
756{
757 if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive())
758 inputContext->compositionUpdateCallback(event);
759 else
760 m_focusHelper.set("innerHTML", std::string());
761}
762
763void QWasmWindow::handleCompositionEndEvent(emscripten::val event)
764{
765 if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive())
766 inputContext->compositionEndCallback(event);
767 else
768 m_focusHelper.set("innerHTML", std::string());
769}
770
771void QWasmWindow::handleBeforeInputEvent(emscripten::val event)
772{
773 if (QWasmInputContext *inputContext = QWasmIntegration::get()->wasmInputContext(); inputContext->isActive())
774 inputContext->beforeInputCallback(event);
775 else
776 m_focusHelper.set("innerHTML", std::string());
777}
778
779void QWasmWindow::handlePointerEnterLeaveEvent(const PointerEvent &event)
780{
781 if (processPointerEnterLeave(event))
782 event.webEvent.call<void>("preventDefault");
783}
784
785bool QWasmWindow::processPointerEnterLeave(const PointerEvent &event)
786{
788 return false;
789
790 switch (event.type) {
792 const auto pointInScreen = platformScreen()->mapFromLocal(
793 dom::mapPoint(event.target(), platformScreen()->element(), event.localPoint));
794 QWindowSystemInterface::handleEnterEvent(
795 window(), mapFromGlobal(pointInScreen.toPoint()), pointInScreen);
796 break;
797 }
800 break;
801 default:
802 break;
803 }
804
805 return false;
806}
807
808void QWasmWindow::releasePointerGrab(const MouseEvent &event)
809{
810 // We check hasPointerCapture due to the implicit release
811 // browsers do.
812 if (m_capturedPointerId && event.isTargetedForElement(m_window) &&
813 m_window.call<bool>("hasPointerCapture", *m_capturedPointerId)) {
814 m_window.call<void>("releasePointerCapture", *m_capturedPointerId);
815 m_capturedPointerId = std::nullopt;
816 }
817}
818
819void QWasmWindow::processPointer(const PointerEvent &event)
820{
821 // Process pointer events targeted at the window only, and not
822 // for instance events for the accessibility elements.
823 if (!event.isTargetedForElement(m_window))
824 return;
825
826 switch (event.type) {
827 case EventType::PointerDown:
828 m_capturedPointerId = event.pointerId;
829 m_window.call<void>("setPointerCapture", event.pointerId);
830
831 if ((window()->flags() & Qt::WindowDoesNotAcceptFocus)
832 != Qt::WindowDoesNotAcceptFocus
833 && window()->isTopLevel())
834 window()->requestActivate();
835 break;
837 releasePointerGrab(event);
838 break;
839 default:
840 break;
841 };
842
843 const bool eventAccepted = deliverPointerEvent(event);
844 if (!eventAccepted && event.type == EventType::PointerDown)
845 QGuiApplicationPrivate::instance()->closeAllPopups();
846
847 if (eventAccepted) {
848 event.webEvent.call<void>("preventDefault");
849 event.webEvent.call<void>("stopPropagation");
850 }
851}
852
853bool QWasmWindow::deliverPointerEvent(const PointerEvent &event)
854{
855 const auto pointInScreen = platformScreen()->mapFromLocal(
856 dom::mapPoint(event.target(), platformScreen()->element(), event.localPoint));
857
858 const auto geometryF = platformScreen()->geometry().toRectF();
859 const QPointF targetPointClippedToScreen(
860 qBound(geometryF.left(), pointInScreen.x(), geometryF.right()),
861 qBound(geometryF.top(), pointInScreen.y(), geometryF.bottom()));
862
863 if (event.pointerType == PointerType::Mouse) {
864 const QEvent::Type eventType =
865 MouseEvent::mouseEventTypeFromEventType(event.type, WindowArea::Client);
866
867 return eventType != QEvent::None
868 && QWindowSystemInterface::handleMouseEvent(
869 window(), QWasmIntegration::getTimestamp(),
870 window()->mapFromGlobal(targetPointClippedToScreen),
871 targetPointClippedToScreen, event.mouseButtons, event.mouseButton,
872 eventType, event.modifiers);
873 }
874
875 if (event.pointerType == PointerType::Pen) {
876 qreal pressure;
877 switch (event.type) {
880 pressure = event.pressure;
881 break;
883 pressure = 0.0;
884 break;
885 default:
886 return false;
887 }
888 // Tilt in the browser is in the range +-90, but QTabletEvent only goes to +-60.
889 qreal xTilt = qBound(-60.0, event.tiltX, 60.0);
890 qreal yTilt = qBound(-60.0, event.tiltY, 60.0);
891 // Barrel rotation is reported as 0 to 359, but QTabletEvent wants a signed value.
892 qreal rotation = event.twist > 180.0 ? 360.0 - event.twist : event.twist;
893 return QWindowSystemInterface::handleTabletEvent(
894 window(), QWasmIntegration::getTimestamp(), platformScreen()->tabletDevice(),
895 window()->mapFromGlobal(targetPointClippedToScreen),
896 targetPointClippedToScreen, event.mouseButtons, pressure, xTilt, yTilt,
897 event.tangentialPressure, rotation, event.modifiers);
898 }
899
900 QWindowSystemInterface::TouchPoint *touchPoint;
901
902 QPointF pointInTargetWindowCoords =
903 QPointF(window()->mapFromGlobal(targetPointClippedToScreen));
904 QPointF normalPosition(pointInTargetWindowCoords.x() / window()->width(),
905 pointInTargetWindowCoords.y() / window()->height());
906
907 const auto tp = m_pointerIdToTouchPoints.find(event.pointerId);
908 if (event.pointerType != PointerType::Pen && tp != m_pointerIdToTouchPoints.end()) {
909 touchPoint = &tp.value();
910 } else {
911 touchPoint = &m_pointerIdToTouchPoints
912 .insert(event.pointerId, QWindowSystemInterface::TouchPoint())
913 .value();
914
915 // Assign touch point id. TouchPoint::id is int, but QGuiApplicationPrivate::processTouchEvent()
916 // will not synthesize mouse events for touch points with negative id; use the absolute value for
917 // the touch point id.
918 touchPoint->id = qAbs(event.pointerId);
919
920 touchPoint->state = QEventPoint::State::Pressed;
921 }
922
923 const bool stationaryTouchPoint = (normalPosition == touchPoint->normalPosition);
924 touchPoint->normalPosition = normalPosition;
925 touchPoint->area = QRectF(targetPointClippedToScreen, QSizeF(event.width, event.height))
926 .translated(-event.width / 2, -event.height / 2);
927 touchPoint->pressure = event.pressure;
928
929 switch (event.type) {
930 case EventType::PointerUp:
931 touchPoint->state = QEventPoint::State::Released;
932 break;
933 case EventType::PointerMove:
934 touchPoint->state = (stationaryTouchPoint ? QEventPoint::State::Stationary
935 : QEventPoint::State::Updated);
936 break;
937 default:
938 break;
939 }
940
941 QList<QWindowSystemInterface::TouchPoint> touchPointList;
942 touchPointList.reserve(m_pointerIdToTouchPoints.size());
943 std::transform(m_pointerIdToTouchPoints.begin(), m_pointerIdToTouchPoints.end(),
944 std::back_inserter(touchPointList),
945 [](const QWindowSystemInterface::TouchPoint &val) { return val; });
946
947 if (event.type == EventType::PointerUp || event.type == EventType::PointerCancel)
948 m_pointerIdToTouchPoints.remove(event.pointerId);
949
950 return event.type == EventType::PointerCancel
951 ? QWindowSystemInterface::handleTouchCancelEvent(
952 window(), QWasmIntegration::getTimestamp(), platformScreen()->touchDevice(),
953 event.modifiers)
954 : QWindowSystemInterface::handleTouchEvent(
955 window(), QWasmIntegration::getTimestamp(), platformScreen()->touchDevice(),
956 touchPointList, event.modifiers);
957}
958
959void QWasmWindow::handleWheelEvent(const emscripten::val &event)
960{
961 if (processWheel(WheelEvent(EventType::Wheel, event)))
962 event.call<void>("preventDefault");
963}
964
965bool QWasmWindow::processWheel(const WheelEvent &event)
966{
967 // Web scroll deltas are inverted from Qt deltas - negate.
968 const int scrollFactor = -([&event]() {
969 switch (event.deltaMode) {
970 case DeltaMode::Pixel:
971 return 1;
972 case DeltaMode::Line:
973 return 12;
974 case DeltaMode::Page:
975 return 20;
976 };
977 })();
978
979 const auto pointInScreen = platformScreen()->mapFromLocal(
980 dom::mapPoint(event.target(), platformScreen()->element(), event.localPoint));
981
982 return QWindowSystemInterface::handleWheelEvent(
983 window(), QWasmIntegration::getTimestamp(), window()->mapFromGlobal(pointInScreen),
984 pointInScreen, (event.delta * scrollFactor).toPoint(),
985 (event.delta * scrollFactor).toPoint(), event.modifiers, Qt::NoScrollPhase,
986 Qt::MouseEventNotSynthesized, event.webkitDirectionInvertedFromDevice);
987}
988
989// Fix top level window flags in case only the type flags are passed.
990Qt::WindowFlags QWasmWindow::fixTopLevelWindowFlags(Qt::WindowFlags flags) const
991{
992 if (!(flags.testFlag(Qt::CustomizeWindowHint))) {
993 if (flags.testFlag(Qt::Window)) {
994 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint
995 |Qt::WindowMaximizeButtonHint|Qt::WindowCloseButtonHint;
996 }
997 if (flags.testFlag(Qt::Dialog) || flags.testFlag(Qt::Tool))
998 flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
999
1000 if ((flags & Qt::WindowType_Mask) == Qt::SplashScreen)
1001 flags |= Qt::FramelessWindowHint;
1002 }
1003 return flags;
1004}
1005
1006bool QWasmWindow::shouldBeAboveTransientParentFlags(Qt::WindowFlags flags) const
1007{
1008 if (!transientParent())
1009 return false;
1010
1011 if (isModal())
1012 return true;
1013
1014 if (flags.testFlag(Qt::Tool) ||
1015 flags.testFlag(Qt::SplashScreen) ||
1016 flags.testFlag(Qt::ToolTip) ||
1017 flags.testFlag(Qt::Popup))
1018 {
1019 return true;
1020 }
1021
1022 return false;
1023}
1024
1025QWasmWindowStack<>::PositionPreference QWasmWindow::positionPreferenceFromWindowFlags(Qt::WindowFlags flags) const
1026{
1027 flags = fixTopLevelWindowFlags(flags);
1028
1029 if (flags.testFlag(Qt::WindowStaysOnTopHint))
1030 return QWasmWindowStack<>::PositionPreference::StayOnTop;
1031 if (flags.testFlag(Qt::WindowStaysOnBottomHint))
1032 return QWasmWindowStack<>::PositionPreference::StayOnBottom;
1033 if (shouldBeAboveTransientParentFlags(flags))
1034 return QWasmWindowStack<>::PositionPreference::StayAboveTransientParent;
1035 return QWasmWindowStack<>::PositionPreference::Regular;
1036}
1037
1039{
1040 return m_normalGeometry;
1041}
1042
1044{
1045 return screen()->devicePixelRatio();
1046}
1047
1049{
1050 m_compositor->requestUpdateWindow(this, QRect(QPoint(0, 0), geometry().size()), QWasmCompositor::UpdateRequestDelivery);
1051}
1052
1053bool QWasmWindow::hasFrame() const
1054{
1055 return !m_flags.testFlag(Qt::FramelessWindowHint);
1056}
1057
1058bool QWasmWindow::hasBorder() const
1059{
1060 return hasFrame() && !m_state.testFlag(Qt::WindowFullScreen) && !m_flags.testFlag(Qt::SubWindow)
1061 && !windowIsPopupType(m_flags) && !parent();
1062}
1063
1064bool QWasmWindow::hasTitleBar() const
1065{
1066 return hasBorder() && m_flags.testFlag(Qt::WindowTitleHint);
1067}
1068
1069bool QWasmWindow::hasShadow() const
1070{
1071 return hasBorder() && !m_flags.testFlag(Qt::NoDropShadowWindowHint);
1072}
1073
1074bool QWasmWindow::hasMaximizeButton() const
1075{
1076 return !m_state.testFlag(Qt::WindowMaximized) && m_flags.testFlag(Qt::WindowMaximizeButtonHint);
1077}
1078
1079bool QWasmWindow::windowIsPopupType(Qt::WindowFlags flags) const
1080{
1081 if (flags.testFlag(Qt::Tool))
1082 return false; // Qt::Tool has the Popup bit set but isn't an actual Popup window
1083
1084 return (flags.testFlag(Qt::Popup));
1085}
1086
1088{
1089 QWindow *modalWindow;
1090 if (QGuiApplicationPrivate::instance()->isWindowBlocked(window(), &modalWindow)) {
1091 static_cast<QWasmWindow *>(modalWindow->handle())->requestActivateWindow();
1092 return;
1093 }
1094
1095 raise();
1096 setAsActiveNode();
1097
1098 if (!QWasmIntegration::get()->inputContext())
1099 focus();
1100 QPlatformWindow::requestActivateWindow();
1101}
1102
1104{
1105 if (QWasmAccessibility::isEnabled())
1106 return;
1107
1108 m_focusHelper.call<void>("focus");
1109}
1110
1112{
1113 m_focusHelper.call<void>("setAttribute", std::string("aria-hidden"), std::string("true"));
1114 m_inputElement.call<void>("setAttribute", std::string("aria-hidden"), std::string("true"));
1115}
1116
1118{
1119 Q_UNUSED(grab);
1120 return false;
1121}
1122
1123bool QWasmWindow::windowEvent(QEvent *event)
1124{
1125 switch (event->type()) {
1126 case QEvent::WindowBlocked:
1127 m_decoratedWindow["classList"].call<void>("add", emscripten::val("blocked"));
1128 return false; // Propagate further
1129 case QEvent::WindowUnblocked:;
1130 m_decoratedWindow["classList"].call<void>("remove", emscripten::val("blocked"));
1131 return false; // Propagate further
1132 default:
1133 return QPlatformWindow::windowEvent(event);
1134 }
1135}
1136
1137void QWasmWindow::setMask(const QRegion &region)
1138{
1139 if (region.isEmpty()) {
1140 m_decoratedWindow["style"].set("clipPath", emscripten::val(""));
1141 return;
1142 }
1143
1144 std::ostringstream cssClipPath;
1145 cssClipPath << "path('";
1146 for (const auto &rect : region) {
1147 const auto cssRect = rect.adjusted(0, 0, 1, 1);
1148 cssClipPath << "M " << cssRect.left() << " " << cssRect.top() << " ";
1149 cssClipPath << "L " << cssRect.right() << " " << cssRect.top() << " ";
1150 cssClipPath << "L " << cssRect.right() << " " << cssRect.bottom() << " ";
1151 cssClipPath << "L " << cssRect.left() << " " << cssRect.bottom() << " z ";
1152 }
1153 cssClipPath << "')";
1154 m_decoratedWindow["style"].set("clipPath", emscripten::val(cssClipPath.str()));
1155}
1156
1157void QWasmWindow::onTransientParentChanged(QWindow *newTransientParent)
1158{
1159 Q_UNUSED(newTransientParent);
1160
1161 const auto positionPreference = positionPreferenceFromWindowFlags(window()->flags());
1162 QWasmWindowTreeNode::onParentChanged(parentNode(), nullptr, positionPreference);
1163 QWasmWindowTreeNode::onParentChanged(nullptr, parentNode(), positionPreference);
1164}
1165
1167{
1168 const auto positionPreference = positionPreferenceFromWindowFlags(window()->flags());
1169 QWasmWindowTreeNode::onParentChanged(parentNode(), nullptr, positionPreference);
1170 QWasmWindowTreeNode::onParentChanged(nullptr, parentNode(), positionPreference);
1171}
1172
1173void QWasmWindow::setParent(const QPlatformWindow *)
1174{
1175 // The window flags depend on whether we are a
1176 // child window or not, so update them here.
1177 setWindowFlags(window()->flags());
1178
1179 commitParent(parentNode());
1180}
1181
1183{
1184 return "!qtwindow" + std::to_string(m_winId);
1185}
1186
1188{
1189 return m_window;
1190}
1191
1193{
1194 if (parent())
1195 return static_cast<QWasmWindow *>(parent());
1196 return platformScreen();
1197}
1198
1200{
1201 return this;
1202}
1203
1204void QWasmWindow::onParentChanged(QWasmWindowTreeNode *previous, QWasmWindowTreeNode *current,
1205 QWasmWindowStack<>::PositionPreference positionPreference)
1206{
1207 if (previous)
1208 previous->containerElement().call<void>("removeChild", m_decoratedWindow);
1209 if (current)
1210 current->containerElement().call<void>("appendChild", m_decoratedWindow);
1211 QWasmWindowTreeNode::onParentChanged(previous, current, positionPreference);
1212}
1213
1214QT_END_NAMESPACE
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.
void onToggleMaximized()
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 &region) final
Reimplement to be able to let Qt set the mask of a window.
QWasmWindow * transientParent() const
QWasmWindowTreeNode * parentNode() final
void onModalityChanged()
void initialize() override
Called as part of QWindow::create(), after constructing the window.
bool isModal() const
Qt::WindowFlags windowFlags() const
bool isVisible() const
void registerEventHandlers()
~QWasmWindow() final
void onMaximizeClicked()
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 onRestoreClicked()
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
void onCloseClicked()
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.
Definition qwasmdom.h:30
Q_GUI_EXPORT int qt_defaultDpiX()
Definition qfont.cpp:132
QDebug Q_GUI_EXPORT & operator<<(QDebug &s, const QVectorPath &path)
DeltaMode
Definition qwasmevent.h:53
PointerType
Definition qwasmevent.h:41
EventType
Definition qwasmevent.h:23
WindowArea
Definition qwasmevent.h:48
int keyCode
Definition qwasmevent.h:76
bool isComposing
Definition qwasmevent.h:75
PointerType pointerType
Definition qwasmevent.h:130
DeltaMode deltaMode
Definition qwasmevent.h:159