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
qwasmcompositor.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
6#include "qwasmwindow.h"
7
8#include <private/qeventdispatcher_wasm_p.h>
9#include <private/qwasmsuspendresumecontrol_p.h>
10
11#include <qpa/qwindowsysteminterface.h>
12
13#include <emscripten/html5.h>
14
15using namespace emscripten;
16
17bool QWasmCompositor::m_requestUpdateHoldEnabled = false;
18
19QWasmCompositor::QWasmCompositor(QWasmScreen *screen)
20: QObject(screen)
21{
22 QWindowSystemInterface::setSynchronousWindowSystemEvents(true);
23}
24
26{
27 if (m_drawCallbackHandle != 0)
28 QWasmAnimationFrameMultiHandler::instance()->unregisterDrawCallback(m_drawCallbackHandle);
29
30 // TODO(mikolaj.boc): Investigate if m_isEnabled is needed at all. It seems like a frame should
31 // not be generated after this instead.
32 m_isEnabled = false; // prevent frame() from creating a new m_context
33}
34
36 QWasmWindow *window)
37{
38 auto allWindows = screen()->allWindows();
39 setEnabled(std::any_of(allWindows.begin(), allWindows.end(), [](QWasmWindow *element) {
40 return !element->context2d().isUndefined();
41 }));
42 if (changeType == QWasmWindowTreeNodeChangeType::NodeRemoval)
43 m_requestUpdateWindows.remove(window);
44}
45
46void QWasmCompositor::setEnabled(bool enabled)
47{
48 m_isEnabled = enabled;
49}
50
51// requestUpdate delivery is initially disabled at startup, while Qt completes
52// startup tasks such as font loading. This function enables requestUpdate delivery
53// again.
55{
56 const bool wasEnabled = m_requestUpdateHoldEnabled;
57 m_requestUpdateHoldEnabled = false;
58 return wasEnabled;
59}
60
61void QWasmCompositor::requestUpdateWindow(QWasmWindow *window, const QRect &updateRect, UpdateRequestDeliveryType updateType)
62{
63 auto it = m_requestUpdateWindows.find(window);
64 if (it == m_requestUpdateWindows.end()) {
65 m_requestUpdateWindows.insert(window, std::make_tuple(updateRect, updateType));
66 } else {
67 // Already registered, but upgrade ExposeEventDeliveryType to UpdateRequestDeliveryType.
68 // if needed, to make sure QWindow::updateRequest's are matched.
69 if (std::get<0>(it.value()) != updateRect) {
70 QRegion region;
71 region |= std::get<0>(it.value());
72 region |= updateRect;
73 std::get<0>(it.value()) = region.boundingRect();
74 }
75 if (std::get<1>(it.value()) == ExposeEventDelivery &&
76 updateType == UpdateRequestDelivery)
77 std::get<1>(it.value()) = UpdateRequestDelivery;
78 }
79
81}
82
83// Requests an update/new frame using RequestAnimationFrame
85{
86 if (m_drawCallbackHandle != 0)
87 return;
88
89 if (m_requestUpdateHoldEnabled)
90 return;
91
92 m_drawCallbackHandle = QWasmAnimationFrameMultiHandler::instance()->registerDrawCallback(
93 [this](double frametime) {
94 Q_UNUSED(frametime);
95 m_drawCallbackHandle = 0;
96 deliverUpdateRequests();
97 });
98}
99
100void QWasmCompositor::deliverUpdateRequests()
101{
102 // We may get new update requests during the window content update below:
103 // prepare for recording the new update set by setting aside the current
104 // update set.
105 auto requestUpdateWindows = m_requestUpdateWindows;
106 m_requestUpdateWindows.clear();
107
108 // Update window content, either all windows or a spesific set of windows. Use the correct
109 // update type: QWindow subclasses expect that requested and delivered updateRequests matches
110 // exactly.
111 m_inDeliverUpdateRequest = true;
112 for (auto it = requestUpdateWindows.constBegin(); it != requestUpdateWindows.constEnd(); ++it) {
113 auto *window = it.key();
114
115 const QRect updateRect = std::get<0>(it.value());
116 const UpdateRequestDeliveryType updateType = std::get<1>(it.value());
117 deliverUpdateRequest(window, updateRect, updateType);
118 }
119
120 m_inDeliverUpdateRequest = false;
121 frame(requestUpdateWindows.keys());
122}
123
124void QWasmCompositor::deliverUpdateRequest(
125 QWasmWindow *window,
126 const QRect &updateRect,
127 UpdateRequestDeliveryType updateType)
128{
129 QWindow *qwindow = window->window();
130
131 // Make sure the DPR value for the window is up to date on expose/repaint.
132 // FIXME: listen to native DPR change events instead, if/when available.
133 QWindowSystemInterface::handleWindowDevicePixelRatioChanged(qwindow);
134
135 // Update by deliverUpdateRequest and expose event according to requested update
136 // type. If the window has not yet been exposed then we must expose it first regardless
137 // of update type. The deliverUpdateRequest must still be sent in this case in order
138 // to maintain correct window update state.
139 if (updateType == UpdateRequestDelivery) {
140 if (qwindow->isExposed() == false)
141 QWindowSystemInterface::handleExposeEvent(qwindow, updateRect);
142 window->deliverUpdateRequest();
143 } else {
144 QWindowSystemInterface::handleExposeEvent(qwindow, updateRect);
145 }
146}
147
148void QWasmCompositor::handleBackingStoreFlush(QWindow *window, const QRect &updateRect)
149{
150 // Request update to flush the updated backing store content, unless we are currently
151 // processing an update, in which case the new content will flushed as a part of that update.
152 if (!m_inDeliverUpdateRequest)
153 requestUpdateWindow(static_cast<QWasmWindow *>(window->handle()), updateRect);
154}
155
156void QWasmCompositor::frame(const QList<QWasmWindow *> &windows)
157{
158 if (!m_isEnabled || !screen())
159 return;
160
161 for (QWasmWindow *window : windows)
162 window->paint();
163}
164
166{
167 return static_cast<QWasmScreen *>(parent());
168}
void onWindowTreeChanged(QWasmWindowTreeNodeChangeType changeType, QWasmWindow *window)
static bool releaseRequestUpdateHold()
void setEnabled(bool enabled)
QWasmScreen * screen()
QWasmCompositor(QWasmScreen *screen)
friend class QWasmCompositor
QWasmWindowTreeNodeChangeType