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