diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/plugins/platforms/wasm/qwasmcompositor.cpp | 51 | ||||
| -rw-r--r-- | src/plugins/platforms/wasm/qwasmcompositor.h | 3 | ||||
| -rw-r--r-- | src/plugins/platforms/wasm/qwasmwindow.cpp | 7 | ||||
| -rw-r--r-- | src/plugins/platforms/wasm/qwasmwindowstack.cpp | 142 | ||||
| -rw-r--r-- | src/plugins/platforms/wasm/qwasmwindowstack.h | 23 |
5 files changed, 171 insertions, 55 deletions
diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp index 56b0592d6b0..922e802732c 100644 --- a/src/plugins/platforms/wasm/qwasmcompositor.cpp +++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp @@ -22,6 +22,16 @@ 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; +} + } // namespace using namespace emscripten; @@ -67,8 +77,11 @@ void QWasmCompositor::destroy() void QWasmCompositor::addWindow(QWasmWindow *window) { - m_windowStack.pushWindow(window); - m_windowStack.topWindow()->requestActivateWindow(); + if (m_windowStack.empty()) + window->window()->setFlag(Qt::WindowStaysOnBottomHint); + m_windowStack.pushWindow(window, positionPreferenceFromWindowFlags(window->window()->flags())); + window->requestActivateWindow(); + setActive(window); updateEnabledState(); } @@ -77,12 +90,27 @@ void QWasmCompositor::removeWindow(QWasmWindow *window) { m_requestUpdateWindows.remove(window); m_windowStack.removeWindow(window); - if (m_windowStack.topWindow()) + 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) { @@ -100,6 +128,11 @@ void QWasmCompositor::lower(QWasmWindow *window) m_windowStack.lower(window); } +void QWasmCompositor::windowPositionPreferenceChanged(QWasmWindow *window, Qt::WindowFlags flags) +{ + m_windowStack.windowPositionPreferenceChanged(window, positionPreferenceFromWindowFlags(flags)); +} + QWindow *QWasmCompositor::windowAt(QPoint targetPointInScreenCoords, int padding) const { const auto found = std::find_if( @@ -115,7 +148,7 @@ QWindow *QWasmCompositor::windowAt(QPoint targetPointInScreenCoords, int padding QWindow *QWasmCompositor::keyWindow() const { - return m_windowStack.topWindow() ? m_windowStack.topWindow()->window() : nullptr; + return m_activeWindow ? m_activeWindow->window() : nullptr; } void QWasmCompositor::requestUpdateAllWindows() @@ -234,16 +267,6 @@ void QWasmCompositor::onTopWindowChanged() int z = zOrderForElementInFrontOfScreen; std::for_each(m_windowStack.rbegin(), m_windowStack.rend(), [&z](QWasmWindow *window) { window->setZOrder(z++); }); - - auto it = m_windowStack.begin(); - if (it == m_windowStack.end()) { - return; - } - (*it)->onActivationChanged(true); - ++it; - for (; it != m_windowStack.end(); ++it) { - (*it)->onActivationChanged(false); - } } QWasmScreen *QWasmCompositor::screen() diff --git a/src/plugins/platforms/wasm/qwasmcompositor.h b/src/plugins/platforms/wasm/qwasmcompositor.h index 5b8f22aaac3..617d14eecea 100644 --- a/src/plugins/platforms/wasm/qwasmcompositor.h +++ b/src/plugins/platforms/wasm/qwasmcompositor.h @@ -34,8 +34,10 @@ public: void removeWindow(QWasmWindow *window); void setVisible(QWasmWindow *window, bool visible); + void setActive(QWasmWindow *window); void raise(QWasmWindow *window); void lower(QWasmWindow *window); + void windowPositionPreferenceChanged(QWasmWindow *window, Qt::WindowFlags flags); void onScreenDeleting(); @@ -69,6 +71,7 @@ private: void updateEnabledState(); QWasmWindowStack m_windowStack; + QWasmWindow *m_activeWindow = nullptr; bool m_isEnabled = true; QMap<QWasmWindow *, UpdateRequestDeliveryType> m_requestUpdateWindows; diff --git a/src/plugins/platforms/wasm/qwasmwindow.cpp b/src/plugins/platforms/wasm/qwasmwindow.cpp index 1bc09ee2704..bc6659c76ab 100644 --- a/src/plugins/platforms/wasm/qwasmwindow.cpp +++ b/src/plugins/platforms/wasm/qwasmwindow.cpp @@ -93,6 +93,7 @@ QWasmWindow::QWasmWindow(QWindow *w, QWasmDeadKeySupport *deadKeySupport, emscripten::val::module_property("specialHTMLTargets").set(canvasSelector(), m_canvas); m_compositor->addWindow(this); + m_flags = window()->flags(); const auto pointerCallback = std::function([this](emscripten::val event) { if (processPointer(*PointerEvent::fromWeb(event))) @@ -360,6 +361,8 @@ void QWasmWindow::onActivationChanged(bool active) void QWasmWindow::setWindowFlags(Qt::WindowFlags flags) { + if (flags.testFlag(Qt::WindowStaysOnTopHint) != m_flags.testFlag(Qt::WindowStaysOnTopHint)) + m_compositor->windowPositionPreferenceChanged(this, flags); m_flags = flags; dom::syncCSSClassWith(m_qtWindow, "has-frame", hasFrame()); dom::syncCSSClassWith(m_qtWindow, "has-shadow", !flags.testFlag(Qt::NoDropShadowWindowHint)); @@ -573,8 +576,10 @@ void QWasmWindow::requestActivateWindow() return; } - if (window()->isTopLevel()) + if (window()->isTopLevel()) { raise(); + m_compositor->setActive(this); + } if (!QWasmIntegration::get()->inputContext()) m_canvas.call<void>("focus"); diff --git a/src/plugins/platforms/wasm/qwasmwindowstack.cpp b/src/plugins/platforms/wasm/qwasmwindowstack.cpp index 098f1c1ff20..d3769c7a1bb 100644 --- a/src/plugins/platforms/wasm/qwasmwindowstack.cpp +++ b/src/plugins/platforms/wasm/qwasmwindowstack.cpp @@ -5,20 +5,38 @@ QT_BEGIN_NAMESPACE -QWasmWindowStack::QWasmWindowStack(TopWindowChangedCallbackType topWindowChangedCallback) - : m_topWindowChangedCallback(std::move(topWindowChangedCallback)) +QWasmWindowStack::QWasmWindowStack(WindowOrderChangedCallbackType windowOrderChangedCallback) + : m_windowOrderChangedCallback(std::move(windowOrderChangedCallback)), + m_regularWindowsBegin(m_windowStack.begin()), + m_alwaysOnTopWindowsBegin(m_windowStack.begin()) { } QWasmWindowStack::~QWasmWindowStack() = default; -void QWasmWindowStack::pushWindow(QWasmWindow *window) +void QWasmWindowStack::pushWindow(QWasmWindow *window, PositionPreference position) { Q_ASSERT(m_windowStack.count(window) == 0); - m_windowStack.push_back(window); - - m_topWindowChangedCallback(); + if (position == PositionPreference::StayOnTop) { + const auto stayOnTopDistance = + std::distance(m_windowStack.begin(), m_alwaysOnTopWindowsBegin); + const auto regularDistance = std::distance(m_windowStack.begin(), m_regularWindowsBegin); + m_windowStack.push_back(window); + m_alwaysOnTopWindowsBegin = m_windowStack.begin() + stayOnTopDistance; + m_regularWindowsBegin = m_windowStack.begin() + regularDistance; + } else if (position == PositionPreference::Regular) { + const auto regularDistance = std::distance(m_windowStack.begin(), m_regularWindowsBegin); + m_alwaysOnTopWindowsBegin = m_windowStack.insert(m_alwaysOnTopWindowsBegin, window) + 1; + m_regularWindowsBegin = m_windowStack.begin() + regularDistance; + } else { + const auto stayOnTopDistance = + std::distance(m_windowStack.begin(), m_alwaysOnTopWindowsBegin); + m_regularWindowsBegin = m_windowStack.insert(m_regularWindowsBegin, window) + 1; + m_alwaysOnTopWindowsBegin = m_windowStack.begin() + stayOnTopDistance + 1; + } + + m_windowOrderChangedCallback(); } void QWasmWindowStack::removeWindow(QWasmWindow *window) @@ -26,41 +44,105 @@ void QWasmWindowStack::removeWindow(QWasmWindow *window) Q_ASSERT(m_windowStack.count(window) == 1); auto it = std::find(m_windowStack.begin(), m_windowStack.end(), window); - const bool removingBottom = m_windowStack.begin() == it; - const bool removingTop = m_windowStack.end() - 1 == it; - if (removingBottom) - m_firstWindowTreatment = FirstWindowTreatment::Regular; + const auto position = getWindowPositionPreference(it); + const auto stayOnTopDistance = std::distance(m_windowStack.begin(), m_alwaysOnTopWindowsBegin); + const auto regularDistance = std::distance(m_windowStack.begin(), m_regularWindowsBegin); m_windowStack.erase(it); - if (removingTop) - m_topWindowChangedCallback(); + m_alwaysOnTopWindowsBegin = m_windowStack.begin() + stayOnTopDistance + - (position != PositionPreference::StayOnTop ? 1 : 0); + m_regularWindowsBegin = m_windowStack.begin() + regularDistance + - (position == PositionPreference::StayOnBottom ? 1 : 0); + + m_windowOrderChangedCallback(); } void QWasmWindowStack::raise(QWasmWindow *window) { Q_ASSERT(m_windowStack.count(window) == 1); - if (window == rootWindow() || window == topWindow()) + if (window == topWindow()) return; - auto it = std::find(regularWindowsBegin(), m_windowStack.end(), window); - std::rotate(it, it + 1, m_windowStack.end()); - m_topWindowChangedCallback(); + auto it = std::find(m_windowStack.begin(), m_windowStack.end(), window); + auto itEnd = ([this, position = getWindowPositionPreference(it)]() { + switch (position) { + case PositionPreference::StayOnTop: + return m_windowStack.end(); + case PositionPreference::Regular: + return m_alwaysOnTopWindowsBegin; + case PositionPreference::StayOnBottom: + return m_regularWindowsBegin; + } + })(); + std::rotate(it, it + 1, itEnd); + m_windowOrderChangedCallback(); } void QWasmWindowStack::lower(QWasmWindow *window) { Q_ASSERT(m_windowStack.count(window) == 1); - if (window == rootWindow()) + if (window == *m_windowStack.begin()) return; - const bool loweringTopWindow = topWindow() == window; - auto it = std::find(regularWindowsBegin(), m_windowStack.end(), window); - std::rotate(regularWindowsBegin(), it, it + 1); - if (loweringTopWindow && topWindow() != window) - m_topWindowChangedCallback(); + auto it = std::find(m_windowStack.begin(), m_windowStack.end(), window); + auto itBegin = ([this, position = getWindowPositionPreference(it)]() { + switch (position) { + case PositionPreference::StayOnTop: + return m_alwaysOnTopWindowsBegin; + case PositionPreference::Regular: + return m_regularWindowsBegin; + case PositionPreference::StayOnBottom: + return m_windowStack.begin(); + } + })(); + + std::rotate(itBegin, it, it + 1); + m_windowOrderChangedCallback(); +} + +void QWasmWindowStack::windowPositionPreferenceChanged(QWasmWindow *window, + PositionPreference position) +{ + auto it = std::find(m_windowStack.begin(), m_windowStack.end(), window); + const auto currentPosition = getWindowPositionPreference(it); + + const auto zones = static_cast<int>(position) - static_cast<int>(currentPosition); + Q_ASSERT(zones != 0); + + if (zones < 0) { + // Perform right rotation so that the window lands on top of regular windows + const auto begin = std::make_reverse_iterator(it + 1); + const auto end = position == PositionPreference::Regular + ? std::make_reverse_iterator(m_alwaysOnTopWindowsBegin) + : std::make_reverse_iterator(m_regularWindowsBegin); + std::rotate(begin, begin + 1, end); + if (zones == -2) { + ++m_alwaysOnTopWindowsBegin; + ++m_regularWindowsBegin; + } else if (position == PositionPreference::Regular) { + ++m_alwaysOnTopWindowsBegin; + } else { + ++m_regularWindowsBegin; + } + } else { + // Perform left rotation so that the window lands at the bottom of always on top windows + const auto begin = it; + const auto end = position == PositionPreference::Regular ? m_regularWindowsBegin + : m_alwaysOnTopWindowsBegin; + std::rotate(begin, begin + 1, end); + if (zones == 2) { + --m_alwaysOnTopWindowsBegin; + --m_regularWindowsBegin; + } else if (position == PositionPreference::Regular) { + --m_regularWindowsBegin; + } else { + --m_alwaysOnTopWindowsBegin; + } + } + m_windowOrderChangedCallback(); } QWasmWindowStack::iterator QWasmWindowStack::begin() @@ -103,21 +185,19 @@ size_t QWasmWindowStack::size() const return m_windowStack.size(); } -QWasmWindow *QWasmWindowStack::rootWindow() const -{ - return m_firstWindowTreatment == FirstWindowTreatment::AlwaysAtBottom ? m_windowStack.first() - : nullptr; -} - QWasmWindow *QWasmWindowStack::topWindow() const { return m_windowStack.empty() ? nullptr : m_windowStack.last(); } -QWasmWindowStack::StorageType::iterator QWasmWindowStack::regularWindowsBegin() +QWasmWindowStack::PositionPreference +QWasmWindowStack::getWindowPositionPreference(StorageType::iterator windowIt) const { - return m_windowStack.begin() - + (m_firstWindowTreatment == FirstWindowTreatment::AlwaysAtBottom ? 1 : 0); + if (windowIt >= m_alwaysOnTopWindowsBegin) + return PositionPreference::StayOnTop; + if (windowIt >= m_regularWindowsBegin) + return PositionPreference::Regular; + return PositionPreference::StayOnBottom; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/wasm/qwasmwindowstack.h b/src/plugins/platforms/wasm/qwasmwindowstack.h index 2eb48b08659..c75001157a0 100644 --- a/src/plugins/platforms/wasm/qwasmwindowstack.h +++ b/src/plugins/platforms/wasm/qwasmwindowstack.h @@ -24,7 +24,7 @@ class QWasmWindow; class Q_AUTOTEST_EXPORT QWasmWindowStack { public: - using TopWindowChangedCallbackType = std::function<void()>; + using WindowOrderChangedCallbackType = std::function<void()>; using StorageType = QList<QWasmWindow *>; @@ -32,13 +32,20 @@ public: using const_iterator = StorageType::const_reverse_iterator; using const_reverse_iterator = StorageType::const_iterator; - explicit QWasmWindowStack(TopWindowChangedCallbackType topWindowChangedCallback); + enum class PositionPreference { + StayOnBottom, + Regular, + StayOnTop, + }; + + explicit QWasmWindowStack(WindowOrderChangedCallbackType topWindowChangedCallback); ~QWasmWindowStack(); - void pushWindow(QWasmWindow *window); + void pushWindow(QWasmWindow *window, PositionPreference position); void removeWindow(QWasmWindow *window); void raise(QWasmWindow *window); void lower(QWasmWindow *window); + void windowPositionPreferenceChanged(QWasmWindow *window, PositionPreference position); // Iterates top-to-bottom iterator begin(); @@ -55,14 +62,12 @@ public: QWasmWindow *topWindow() const; private: - enum class FirstWindowTreatment { AlwaysAtBottom, Regular }; - - QWasmWindow *rootWindow() const; - StorageType::iterator regularWindowsBegin(); + PositionPreference getWindowPositionPreference(StorageType::iterator windowIt) const; - TopWindowChangedCallbackType m_topWindowChangedCallback; + WindowOrderChangedCallbackType m_windowOrderChangedCallback; QList<QWasmWindow *> m_windowStack; - FirstWindowTreatment m_firstWindowTreatment = FirstWindowTreatment::AlwaysAtBottom; + StorageType::iterator m_regularWindowsBegin; + StorageType::iterator m_alwaysOnTopWindowsBegin; }; QT_END_NAMESPACE |
