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 <private/qpixmapcache_p.h>
9#include <QtGui/qopenglfunctions.h>
29#include <emscripten/val.h>
31#include <QtCore/private/qstdweb_p.h>
53 m_backingStore(backingStore),
54 m_deadKeySupport(deadKeySupport),
55 m_document(
dom::document()),
62 m_qtWindow.set(
"className",
"qt-window");
63 m_qtWindow[
"style"].set(
"display", std::string(
"none"));
65 m_nonClientArea = std::make_unique<NonClientArea>(
this, m_qtWindow);
66 m_nonClientArea->titleBar()->setTitle(
window()->
title());
68 m_clientArea = std::make_unique<ClientArea>(
this,
compositor->screen(), m_windowContents);
70 m_windowContents.set(
"className",
"qt-window-contents");
71 m_qtWindow.call<
void>(
"appendChild", m_windowContents);
73 m_canvas[
"classList"].call<
void>(
"add", emscripten::val(
"qt-window-content"));
77 m_canvas.set(
"contentEditable", std::string(
"true"));
78 m_canvas[
"style"].set(
"outline", std::string(
"none"));
84 m_canvas.set(
"inputmode", std::string(
"none"));
87 m_canvas.call<
void>(
"setAttribute", std::string(
"aria-hidden"), std::string(
"true"));
89 m_windowContents.call<
void>(
"appendChild", m_canvasContainer);
91 m_canvasContainer[
"classList"].call<
void>(
"add", emscripten::val(
"qt-window-canvas-container"));
92 m_canvasContainer.call<
void>(
"appendChild", m_canvas);
94 m_canvasContainer.call<
void>(
"appendChild", m_a11yContainer);
95 m_a11yContainer[
"classList"].call<
void>(
"add", emscripten::val(
"qt-window-a11y-container"));
98 if (rendersTo2dContext)
99 m_context2d = m_canvas.call<emscripten::val>(
"getContext", emscripten::val(
"2d"));
100 static int serialNo = 0;
101 m_winId = ++serialNo;
102 m_qtWindow.set(
"id",
"qt-window-" + std::to_string(m_winId));
103 emscripten::val::module_property(
"specialHTMLTargets").set(
canvasSelector(), m_canvas);
107 const auto pointerCallback = std::function([
this](emscripten::val
event) {
109 event.call<
void>(
"preventDefault");
112 m_pointerEnterCallback =
113 std::make_unique<qstdweb::EventCallback>(m_qtWindow,
"pointerenter", pointerCallback);
114 m_pointerLeaveCallback =
115 std::make_unique<qstdweb::EventCallback>(m_qtWindow,
"pointerleave", pointerCallback);
117 m_dropCallback = std::make_unique<qstdweb::EventCallback>(
118 m_qtWindow,
"drop", [
this](emscripten::val
event) {
120 event.call<
void>(
"preventDefault");
123 m_wheelEventCallback = std::make_unique<qstdweb::EventCallback>(
124 m_qtWindow,
"wheel", [
this](emscripten::val
event) {
126 event.call<
void>(
"preventDefault");
129 const auto keyCallback = std::function([
this](emscripten::val
event) {
131 event.call<
void>(
"preventDefault");
132 event.call<
void>(
"stopPropagation");
136 std::make_unique<qstdweb::EventCallback>(m_qtWindow,
"keydown", keyCallback);
137 m_keyUpCallback = std::make_unique<qstdweb::EventCallback>(m_qtWindow,
"keyup", keyCallback);
144 emscripten::val::module_property(
"specialHTMLTargets").delete_(
canvasSelector());
145 m_canvasContainer.call<
void>(
"removeChild", m_canvas);
146 m_context2d = emscripten::val::undefined();
147 commitParent(
nullptr);
148 if (m_requestAnimationFrameId > -1)
149 emscripten_cancel_animation_frame(m_requestAnimationFrameId);
150#if QT_CONFIG(accessibility)
151 QWasmAccessibility::removeAccessibilityEnableButton(
window());
157 return window()->requestedFormat();
193 pointInScreen,
event.mouseButtons,
event.mouseButton,
203 const bool shouldRestrictMinSize =
205 const bool isMinSizeUninitialized =
window()->minimumSize() ==
QSize(0, 0);
207 if (shouldRestrictMinSize && isMinSizeUninitialized)
208 window()->setMinimumSize(
QSize(minSizeForRegularWindows, minSizeForRegularWindows));
213 const QSize targetSize = !
rect.isEmpty() ?
rect.size() : minimumSize;
221 if (
window()->isTopLevel())
223 m_normalGeometry =
rect;
226#if QT_CONFIG(accessibility)
229 if (
window()->isTopLevel())
230 QWasmAccessibility::addAccessibilityEnableButton(
window());
241 if (!m_backingStore || !
isVisible() || m_context2d.isUndefined())
245 if (
image.isUndefined())
247 m_context2d.call<
void>(
"putImageData",
image, emscripten::val(0), emscripten::val(0));
252 m_qtWindow[
"style"].set(
"zIndex", std::to_string(
z));
257 m_windowContents[
"style"].set(
"cursor", emscripten::val(cssCursorName.
constData()));
264 const QRect clientAreaRect = ([
this, &
rect, &margins]() {
273 auto containerGeometryInViewport =
275 "getBoundingClientRect"))
278 auto rectInViewport =
QRect(containerGeometryInViewport.topLeft() +
offset,
rect.size());
280 QRect cappedGeometry(rectInViewport);
282 std::max(std::min(rectInViewport.y(), containerGeometryInViewport.bottom()),
283 containerGeometryInViewport.y() + margins.top()));
289 m_nonClientArea->onClientAreaWidthChange(clientAreaRect.
width());
291 const auto frameRect =
293 .
adjusted(-margins.left(), -margins.top(), margins.right(), margins.bottom())
296 m_qtWindow[
"style"].set(
"left", std::to_string(frameRect.left()) +
"px");
297 m_qtWindow[
"style"].set(
"top", std::to_string(frameRect.top()) +
"px");
298 m_canvasContainer[
"style"].set(
"width", std::to_string(clientAreaRect.
width()) +
"px");
299 m_canvasContainer[
"style"].set(
"height", std::to_string(clientAreaRect.
height()) +
"px");
300 m_a11yContainer[
"style"].set(
"width", std::to_string(clientAreaRect.
width()) +
"px");
301 m_a11yContainer[
"style"].set(
"height", std::to_string(clientAreaRect.
height()) +
"px");
304 m_windowContents[
"style"].set(
"width", std::to_string(clientAreaRect.
width()) +
"px");
308 m_canvas.set(
"width", canvasSize.
width());
309 m_canvas.set(
"height", canvasSize.
height());
311 bool shouldInvalidate =
true;
313 shouldInvalidate = m_normalGeometry.
size() != clientAreaRect.
size();
314 m_normalGeometry = clientAreaRect;
317 if (shouldInvalidate)
326 const bool nowVisible = m_qtWindow[
"style"][
"display"].as<std::string>() ==
"block";
327 if (visible == nowVisible)
331 m_qtWindow[
"style"].set(
"display", visible ?
"block" :
"none");
333 m_canvas.call<
void>(
"focus");
340 return window()->isVisible();
345 const auto frameRect =
346 QRectF::fromDOMRect(m_qtWindow.call<emscripten::val>(
"getBoundingClientRect"));
347 const auto canvasRect =
348 QRectF::fromDOMRect(m_windowContents.call<emscripten::val>(
"getBoundingClientRect"));
349 return QMarginsF(canvasRect.left() - frameRect.left(), canvasRect.top() - frameRect.top(),
350 frameRect.right() - canvasRect.right(),
351 frameRect.bottom() - canvasRect.bottom())
380 m_nonClientArea->propagateSizeHints();
385 m_qtWindow[
"style"].set(
"opacity",
qBound(0.0,
level, 1.0));
388void QWasmWindow::invalidate()
413 m_nonClientArea->titleBar()->setMaximizeVisible(hasMaximizeButton());
423 const Qt::WindowStates oldState = m_state;
427 qWarning(
"Qt::WindowMinimized is not implemented in wasm");
436 m_previousWindowState = oldState;
443 m_nonClientArea->titleBar()->setTitle(
title);
451 m_nonClientArea->titleBar()->setIcon(
462void QWasmWindow::applyWindowState()
470 else if (isMaximized)
478 m_nonClientArea->titleBar()->setRestoreVisible(isMaximized);
479 m_nonClientArea->titleBar()->setMaximizeVisible(hasMaximizeButton());
489 m_commitedParent =
parent;
494 constexpr bool ProceedToNativeEvent =
false;
497 const auto clipboardResult =
501 if (clipboardResult == ProcessKeyboardResult::NativeClipboardEventNeeded)
502 return ProceedToNativeEvent;
507 return clipboardResult == ProcessKeyboardResult::NativeClipboardEventAndCopiedDataNeeded
508 ? ProceedToNativeEvent
517 switch (
event.type) {
522 window(), m_window->mapFromGlobal(pointInScreen), pointInScreen);
541 image.loadFromData(fileContent, nullptr);
544 [
this,
event](std::unique_ptr<QMimeData>
data) {
545 QWindowSystemInterface::handleDrag(window(), data.get(),
546 event.pointInPage.toPoint(), event.dropAction,
547 event.mouseButton, event.modifiers);
549 QWindowSystemInterface::handleDrop(window(), data.get(),
550 event.pointInPage.toPoint(), event.dropAction,
551 event.mouseButton, event.modifiers);
553 QWindowSystemInterface::handleDrag(window(), nullptr, QPoint(), Qt::IgnoreAction,
562 const int scrollFactor = -([&
event]() {
563 switch (
event.deltaMode) {
578 pointInScreen, (
event.delta * scrollFactor).toPoint(),
585 return m_normalGeometry;
598bool QWasmWindow::hasBorder()
const
601 && !windowIsPopupType(m_flags);
604bool QWasmWindow::hasShadow()
const
610bool QWasmWindow::hasMaximizeButton()
const
615bool QWasmWindow::windowIsPopupType(Qt::WindowFlags
flags)
const
635 m_canvas.call<
void>(
"focus");
648 switch (
event->type()) {
650 m_qtWindow[
"classList"].call<
void>(
"add", emscripten::val(
"blocked"));
653 m_qtWindow[
"classList"].call<
void>(
"remove", emscripten::val(
"blocked"));
663 m_qtWindow[
"style"].set(
"clipPath", emscripten::val(
""));
667 std::ostringstream cssClipPath;
668 cssClipPath <<
"path('";
669 for (
const auto &
rect : region) {
670 const auto cssRect =
rect.adjusted(0, 0, 1, 1);
671 cssClipPath <<
"M " << cssRect.left() <<
" " << cssRect.top() <<
" ";
672 cssClipPath <<
"L " << cssRect.right() <<
" " << cssRect.top() <<
" ";
673 cssClipPath <<
"L " << cssRect.right() <<
" " << cssRect.bottom() <<
" ";
674 cssClipPath <<
"L " << cssRect.left() <<
" " << cssRect.bottom() <<
" z ";
677 m_qtWindow[
"style"].set(
"clipPath", emscripten::val(cssClipPath.str()));
687 return "!qtwindow" + std::to_string(m_winId);
692 return m_windowContents;
static Base64IconStore * get()
\inmodule QtCore \reentrant
std::string toStdString() const
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
QByteArray toBase64(Base64Options options=Base64Encoding) const
virtual bool closeAllPopups()
static QGuiApplicationPrivate * instance()
The QIcon class provides scalable icons in different modes and states.
QPixmap pixmap(const QSize &size, Mode mode=Normal, State state=Off) const
Returns a pixmap with the requested size, mode, and state, generating one if necessary.
constexpr QMargins toMargins() const noexcept
Returns an integer-based copy of this margins object.
\inmodule QtCore\reentrant
\inmodule QtCore\reentrant
\inmodule QtCore\reentrant
constexpr int height() const noexcept
Returns the height of the rectangle.
constexpr QRect marginsRemoved(const QMargins &margins) const noexcept
Removes the margins from the rectangle, shrinking it.
constexpr QPoint topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
constexpr void setSize(const QSize &s) noexcept
Sets the size of the rectangle to the given size.
constexpr QRect adjusted(int x1, int y1, int x2, int y2) const noexcept
Returns a new rectangle with dx1, dy1, dx2 and dy2 added respectively to the existing coordinates of ...
constexpr QSize size() const noexcept
Returns the size of the rectangle.
constexpr int width() const noexcept
Returns the width of the rectangle.
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
constexpr void moveTop(int pos) noexcept
Moves the rectangle vertically, leaving the rectangle's top edge at the given y coordinate.
The QRegion class specifies a clip region for a painter.
bool isEmpty() const
Returns true if the region is empty; otherwise returns false.
QPlatformScreen * handle() const
Get the platform screen handle.
constexpr qreal width() const noexcept
Returns the width.
constexpr qreal height() const noexcept
Returns the height.
constexpr int height() const noexcept
Returns the height.
constexpr int width() const noexcept
Returns the width.
constexpr QSize expandedTo(const QSize &) const noexcept
Returns a size holding the maximum width and height of this size and the given otherSize.
\macro QT_RESTRICTED_CAST_FROM_ASCII
emscripten::val getUpdatedWebImage(QWasmWindow *window)
static void installEventHandlers(const emscripten::val &target)
ProcessKeyboardResult processKeyboard(const KeyEvent &event)
void requestUpdateWindow(QWasmWindow *window, UpdateRequestDeliveryType updateType=ExposeEventDelivery)
static QWasmIntegration * get()
QWasmClipboard * getWasmClipboard()
static quint64 getTimestamp()
QPointF mapFromLocal(const QPointF &p) const
QRect geometry() const override
Reimplement in subclass to return the pixel geometry of the screen.
virtual void onParentChanged(QWasmWindowTreeNode *previous, QWasmWindowTreeNode *current, QWasmWindowStack::PositionPreference positionPreference)
virtual emscripten::val containerElement()=0
void onPositionPreferenceChanged(QWasmWindowStack::PositionPreference positionPreference)
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.
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.
QWasmWindow(QWindow *w, QWasmDeadKeySupport *deadKeySupport, QWasmCompositor *compositor, QWasmBackingStore *backingStore)
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
void onParentChanged(QWasmWindowTreeNode *previous, QWasmWindowTreeNode *current, QWasmWindowStack::PositionPreference positionPreference) final
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.
QWasmWindowTreeNode * parentNode() final
void initialize() override
Called as part of QWindow::create(), after constructing the window.
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 setOpacity(qreal level) override
Reimplement to be able to let Qt set the opacity level of a window.
void onActivationChanged(bool active)
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.
static void handleLeaveEvent(QWindow *window)
static bool handleMouseEvent(QWindow *window, const QPointF &local, const QPointF &global, Qt::MouseButtons state, Qt::MouseButton button, QEvent::Type type, Qt::KeyboardModifiers mods=Qt::NoModifier, Qt::MouseEventSource source=Qt::MouseEventNotSynthesized)
static void handleGeometryChange(QWindow *window, const QRect &newRect)
static bool handleKeyEvent(QWindow *window, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString &text=QString(), bool autorep=false, ushort count=1)
static void handleEnterEvent(QWindow *window, const QPointF &local=QPointF(), const QPointF &global=QPointF())
static bool handleWheelEvent(QWindow *window, const QPointF &local, const QPointF &global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods=Qt::NoModifier, Qt::ScrollPhase phase=Qt::NoScrollPhase, Qt::MouseEventSource source=Qt::MouseEventNotSynthesized)
static void handleWindowStateChanged(QWindow *window, Qt::WindowStates newState, int oldState=-1)
Qt::WindowFlags flags
the window flags of the window
bool close()
Close the window.
EGLImageKHR int int EGLuint64KHR * modifiers
void newState(QList< State > &states, const char *token, const char *lexem, bool pre)
Combined button and popup list for selecting options.
QWasmWindowStack::PositionPreference positionPreferenceFromWindowFlags(Qt::WindowFlags flags)
@ MouseEventNotSynthesized
@ WindowStaysOnBottomHint
@ WindowMaximizeButtonHint
@ WindowTransparentForInput
void syncCSSClassWith(emscripten::val element, std::string cssClassName, bool flag)
QPointF mapPoint(emscripten::val source, emscripten::val target, const QPointF &point)
std::shared_ptr< CancellationFlag > readDataTransfer(emscripten::val webDataTransfer, std::function< QVariant(QByteArray)> imageReader, std::function< void(std::unique_ptr< QMimeData >)> onDone)
constexpr const T & qBound(const T &min, const T &val, const T &max)
static QOpenGLCompositor * compositor
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat z
GLenum GLuint GLint level
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLintptr offset
Q_GUI_EXPORT int qt_defaultDpiX()
static std::optional< DragEvent > fromWeb(emscripten::val webEvent)
static std::optional< KeyEvent > fromWebWithDeadKeyTranslation(emscripten::val webEvent, QWasmDeadKeySupport *deadKeySupport)
static constexpr QEvent::Type mouseEventTypeFromEventType(EventType eventType, WindowArea windowArea)
static std::optional< PointerEvent > fromWeb(emscripten::val webEvent)
static std::optional< WheelEvent > fromWeb(emscripten::val webEvent)
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent