diff options
Diffstat (limited to 'src/plugins/platforms/wasm/qwasmcompositor.cpp')
-rw-r--r-- | src/plugins/platforms/wasm/qwasmcompositor.cpp | 168 |
1 files changed, 61 insertions, 107 deletions
diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp index 1fafd5d9e8..c534cce9ef 100644 --- a/src/plugins/platforms/wasm/qwasmcompositor.cpp +++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp @@ -4,29 +4,17 @@ #include "qwasmcompositor.h" #include "qwasmwindow.h" +#include <private/qeventdispatcher_wasm_p.h> + #include <qpa/qwindowsysteminterface.h> #include <emscripten/html5.h> -namespace { -QWasmWindow *asWasmWindow(QWindow *window) -{ - return static_cast<QWasmWindow*>(window->handle()); -} - -QWasmWindowStack::PositionPreference positionPreferenceFromWindowFlags(Qt::WindowFlags flags) -{ - if (flags.testFlag(Qt::WindowStaysOnTopHint)) - return QWasmWindowStack::PositionPreference::StayOnTop; - if (flags.testFlag(Qt::WindowStaysOnBottomHint)) - return QWasmWindowStack::PositionPreference::StayOnBottom; - return QWasmWindowStack::PositionPreference::Regular; -} +using namespace emscripten; -} // namespace +bool QWasmCompositor::m_requestUpdateHoldEnabled = true; -QWasmCompositor::QWasmCompositor(QWasmScreen *screen) - : QObject(screen), m_windowStack(std::bind(&QWasmCompositor::onTopWindowChanged, this)) +QWasmCompositor::QWasmCompositor(QWasmScreen *screen) : QObject(screen) { QWindowSystemInterface::setSynchronousWindowSystemEvents(true); } @@ -41,92 +29,49 @@ QWasmCompositor::~QWasmCompositor() m_isEnabled = false; // prevent frame() from creating a new m_context } -void QWasmCompositor::addWindow(QWasmWindow *window) -{ - if (m_windowStack.empty()) - window->window()->setFlag(Qt::WindowStaysOnBottomHint); - m_windowStack.pushWindow(window, positionPreferenceFromWindowFlags(window->window()->flags())); - window->requestActivateWindow(); - setActive(window); - - updateEnabledState(); -} - -void QWasmCompositor::removeWindow(QWasmWindow *window) -{ - m_requestUpdateWindows.remove(window); - m_windowStack.removeWindow(window); - if (m_windowStack.topWindow()) { - m_windowStack.topWindow()->requestActivateWindow(); - setActive(m_windowStack.topWindow()); - } - - updateEnabledState(); -} - -void QWasmCompositor::setActive(QWasmWindow *window) -{ - m_activeWindow = window; - - auto it = m_windowStack.begin(); - if (it == m_windowStack.end()) { - return; - } - for (; it != m_windowStack.end(); ++it) { - (*it)->onActivationChanged(*it == m_activeWindow); - } -} - -void QWasmCompositor::updateEnabledState() -{ - m_isEnabled = std::any_of(m_windowStack.begin(), m_windowStack.end(), [](QWasmWindow *window) { - return !window->context2d().isUndefined(); - }); -} - -void QWasmCompositor::raise(QWasmWindow *window) -{ - m_windowStack.raise(window); -} - -void QWasmCompositor::lower(QWasmWindow *window) -{ - m_windowStack.lower(window); -} - -void QWasmCompositor::windowPositionPreferenceChanged(QWasmWindow *window, Qt::WindowFlags flags) +void QWasmCompositor::onWindowTreeChanged(QWasmWindowTreeNodeChangeType changeType, + QWasmWindow *window) { - m_windowStack.windowPositionPreferenceChanged(window, positionPreferenceFromWindowFlags(flags)); + auto allWindows = screen()->allWindows(); + setEnabled(std::any_of(allWindows.begin(), allWindows.end(), [](QWasmWindow *element) { + return !element->context2d().isUndefined(); + })); + if (changeType == QWasmWindowTreeNodeChangeType::NodeRemoval) + m_requestUpdateWindows.remove(window); } -QWindow *QWasmCompositor::windowAt(QPoint targetPointInScreenCoords, int padding) const +void QWasmCompositor::setEnabled(bool enabled) { - const auto found = std::find_if( - m_windowStack.begin(), m_windowStack.end(), - [padding, &targetPointInScreenCoords](const QWasmWindow *window) { - const QRect geometry = window->windowFrameGeometry().adjusted(-padding, -padding, - padding, padding); - - return window->isVisible() && geometry.contains(targetPointInScreenCoords); - }); - return found != m_windowStack.end() ? (*found)->window() : nullptr; + m_isEnabled = enabled; } -QWindow *QWasmCompositor::keyWindow() const +// requestUpdate delivery is initially disabled at startup, while Qt completes +// startup tasks such as font loading. This function enables requestUpdate delivery +// again. +bool QWasmCompositor::releaseRequestUpdateHold() { - return m_activeWindow ? m_activeWindow->window() : nullptr; + const bool wasEnabled = m_requestUpdateHoldEnabled; + m_requestUpdateHoldEnabled = false; + return wasEnabled; } -void QWasmCompositor::requestUpdateWindow(QWasmWindow *window, UpdateRequestDeliveryType updateType) +void QWasmCompositor::requestUpdateWindow(QWasmWindow *window, const QRect &updateRect, UpdateRequestDeliveryType updateType) { auto it = m_requestUpdateWindows.find(window); if (it == m_requestUpdateWindows.end()) { - m_requestUpdateWindows.insert(window, updateType); + m_requestUpdateWindows.insert(window, std::make_tuple(updateRect, updateType)); } else { // Already registered, but upgrade ExposeEventDeliveryType to UpdateRequestDeliveryType. // if needed, to make sure QWindow::updateRequest's are matched. - if (it.value() == ExposeEventDelivery && updateType == UpdateRequestDelivery) - it.value() = UpdateRequestDelivery; + if (std::get<0>(it.value()) != updateRect) { + QRegion region; + region |= std::get<0>(it.value()); + region |= updateRect; + std::get<0>(it.value()) = region.boundingRect(); + } + if (std::get<1>(it.value()) == ExposeEventDelivery && + updateType == UpdateRequestDelivery) + std::get<1>(it.value()) = UpdateRequestDelivery; } requestUpdate(); @@ -138,6 +83,9 @@ void QWasmCompositor::requestUpdate() if (m_requestAnimationFrameId != -1) return; + if (m_requestUpdateHoldEnabled) + return; + static auto frame = [](double frameTime, void *context) -> int { Q_UNUSED(frameTime); @@ -163,35 +111,48 @@ void QWasmCompositor::deliverUpdateRequests() // update type: QWindow subclasses expect that requested and delivered updateRequests matches // exactly. m_inDeliverUpdateRequest = true; - for (auto it = requestUpdateWindows.constBegin(); it != requestUpdateWindows.constEnd(); ++it) { auto *window = it.key(); - UpdateRequestDeliveryType updateType = it.value(); - deliverUpdateRequest(window, updateType); + + const QRect updateRect = std::get<0>(it.value()); + const UpdateRequestDeliveryType updateType = std::get<1>(it.value()); + deliverUpdateRequest(window, updateRect, updateType); } m_inDeliverUpdateRequest = false; frame(requestUpdateWindows.keys()); } -void QWasmCompositor::deliverUpdateRequest(QWasmWindow *window, UpdateRequestDeliveryType updateType) +void QWasmCompositor::deliverUpdateRequest( + QWasmWindow *window, + const QRect &updateRect, + UpdateRequestDeliveryType updateType) { - // update by deliverUpdateRequest and expose event accordingly. + QWindow *qwindow = window->window(); + + // Make sure the DPR value for the window is up to date on expose/repaint. + // FIXME: listen to native DPR change events instead, if/when available. + QWindowSystemInterface::handleWindowDevicePixelRatioChanged(qwindow); + + // Update by deliverUpdateRequest and expose event according to requested update + // type. If the window has not yet been exposed then we must expose it first regardless + // of update type. The deliverUpdateRequest must still be sent in this case in order + // to maintain correct window update state. if (updateType == UpdateRequestDelivery) { + if (qwindow->isExposed() == false) + QWindowSystemInterface::handleExposeEvent(qwindow, updateRect); window->deliverUpdateRequest(); } else { - QWindow *qwindow = window->window(); - QWindowSystemInterface::handleExposeEvent( - qwindow, QRect(QPoint(0, 0), qwindow->geometry().size())); + QWindowSystemInterface::handleExposeEvent(qwindow, updateRect); } } -void QWasmCompositor::handleBackingStoreFlush(QWindow *window) +void QWasmCompositor::handleBackingStoreFlush(QWindow *window, const QRect &updateRect) { // Request update to flush the updated backing store content, unless we are currently // processing an update, in which case the new content will flushed as a part of that update. if (!m_inDeliverUpdateRequest) - requestUpdateWindow(asWasmWindow(window)); + requestUpdateWindow(static_cast<QWasmWindow *>(window->handle()), updateRect); } void QWasmCompositor::frame(const QList<QWasmWindow *> &windows) @@ -199,15 +160,8 @@ void QWasmCompositor::frame(const QList<QWasmWindow *> &windows) if (!m_isEnabled || !screen()) return; - std::for_each(windows.begin(), windows.end(), [](QWasmWindow *window) { window->paint(); }); -} - -void QWasmCompositor::onTopWindowChanged() -{ - constexpr int zOrderForElementInFrontOfScreen = 3; - int z = zOrderForElementInFrontOfScreen; - std::for_each(m_windowStack.rbegin(), m_windowStack.rend(), - [&z](QWasmWindow *window) { window->setZOrder(z++); }); + for (QWasmWindow *window : windows) + window->paint(); } QWasmScreen *QWasmCompositor::screen() |