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