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