diff options
| author | Mikolaj Boc <[email protected]> | 2023-01-26 18:38:21 +0100 | 
|---|---|---|
| committer | Mikolaj Boc <[email protected]> | 2023-02-22 18:07:35 +0100 | 
| commit | a596ea0fe278416b4827ddbb0fffd9c497bd4d88 (patch) | |
| tree | a1cd4d50ecf318ba8cb03ebec1c42b50a52be6bd /src/plugins/platforms/wasm/qwasmwindowstack.cpp | |
| parent | 96e031edd74e8e1eaea79d95320637eb27e8e2ba (diff) | |
Support always on top/bottom window flags on WASM
The window stack will now upkeep three groups of windows, always
on bottom (1), regular (2), always on top (3). Windows belonging to
(3) will always appear on top of (2) and (1), and windows from (2) will
always appear on top of (1).
The first window created in the application gets the (1) status, which
is in line with the root window mechanism used before.
Activation has now been decoupled from the top position on the window
stack as a window in (1) or (2) may be active, in spite of the top
window belonging to a higher group.
Fixes: QTBUG-110098
Change-Id: I51f4d2d47163fab26ce5ef28f7a4f23a522c7f91
Reviewed-by: Lorn Potter <[email protected]>
Diffstat (limited to 'src/plugins/platforms/wasm/qwasmwindowstack.cpp')
| -rw-r--r-- | src/plugins/platforms/wasm/qwasmwindowstack.cpp | 142 | 
1 files changed, 111 insertions, 31 deletions
| 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 | 
