1007964f2d
The old stack structure used to keep track of windows has been improved to conform to the actual windowing assumptions: there shall be one root window, which is always at the bottom. The first created window immediately becomes the root window. Should the root window be removed, all windows are non-root, i.e. any of them can become the top-level window Fixes: QTBUG-105094 Pick-to: 6.4 Change-Id: Ic553244fa9f5bc3ee590b702935e66cfc62d5f8f Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
265 lines
7.5 KiB
C++
265 lines
7.5 KiB
C++
// Copyright (C) 2022 The Qt Company Ltd.
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
|
|
#include "../../../src/plugins/platforms/wasm/qwasmwindowstack.h"
|
|
#include <QtGui/QWindow>
|
|
#include <QTest>
|
|
#include <emscripten/val.h>
|
|
|
|
class QWasmWindow
|
|
{
|
|
};
|
|
|
|
namespace {
|
|
std::vector<QWasmWindow *> getWindowsFrontToBack(const QWasmWasmWindowStack *stack)
|
|
{
|
|
return std::vector<QWasmWindow *>(stack->begin(), stack->end());
|
|
}
|
|
}
|
|
|
|
class tst_QWasmWindowStack : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
tst_QWasmWindowStack()
|
|
: m_mockCallback(
|
|
std::bind(&tst_QWasmWindowStack::onTopWindowChanged, this, std::placeholders::_1))
|
|
{
|
|
}
|
|
|
|
private slots:
|
|
void init();
|
|
|
|
void insertion();
|
|
void raisingTheRootIsImpossible();
|
|
void raising();
|
|
void lowering();
|
|
void removing();
|
|
void removingTheRoot();
|
|
|
|
private:
|
|
void onTopWindowChanged(QWasmWindow *topWindow)
|
|
{
|
|
++m_topLevelChangedCallCount;
|
|
if (m_onTopLevelChangedAction)
|
|
m_onTopLevelChangedAction(topWindow);
|
|
}
|
|
|
|
void verifyTopWindowChangedCalled(int expected = 1)
|
|
{
|
|
QCOMPARE(expected, m_topLevelChangedCallCount);
|
|
clearCallbackCounter();
|
|
}
|
|
|
|
void clearCallbackCounter() { m_topLevelChangedCallCount = 0; }
|
|
|
|
QWasmWasmWindowStack::TopWindowChangedCallbackType m_mockCallback;
|
|
QWasmWasmWindowStack::TopWindowChangedCallbackType m_onTopLevelChangedAction;
|
|
int m_topLevelChangedCallCount = 0;
|
|
|
|
QWasmWindow m_root;
|
|
QWasmWindow m_window1;
|
|
QWasmWindow m_window2;
|
|
QWasmWindow m_window3;
|
|
QWasmWindow m_window4;
|
|
QWasmWindow m_window5;
|
|
};
|
|
|
|
void tst_QWasmWindowStack::init()
|
|
{
|
|
m_onTopLevelChangedAction = QWasmWasmWindowStack::TopWindowChangedCallbackType();
|
|
clearCallbackCounter();
|
|
}
|
|
|
|
void tst_QWasmWindowStack::insertion()
|
|
{
|
|
QWasmWasmWindowStack stack(m_mockCallback);
|
|
|
|
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) { QVERIFY(topWindow == &m_root); };
|
|
stack.pushWindow(&m_root);
|
|
verifyTopWindowChangedCalled();
|
|
|
|
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
|
QVERIFY(topWindow == &m_window1);
|
|
};
|
|
stack.pushWindow(&m_window1);
|
|
verifyTopWindowChangedCalled();
|
|
|
|
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
|
QVERIFY(topWindow == &m_window2);
|
|
};
|
|
stack.pushWindow(&m_window2);
|
|
verifyTopWindowChangedCalled();
|
|
}
|
|
|
|
void tst_QWasmWindowStack::raisingTheRootIsImpossible()
|
|
{
|
|
QWasmWasmWindowStack stack(m_mockCallback);
|
|
|
|
stack.pushWindow(&m_root);
|
|
stack.pushWindow(&m_window1);
|
|
stack.pushWindow(&m_window2);
|
|
stack.pushWindow(&m_window3);
|
|
stack.pushWindow(&m_window4);
|
|
stack.pushWindow(&m_window5);
|
|
|
|
clearCallbackCounter();
|
|
|
|
stack.raise(&m_root);
|
|
verifyTopWindowChangedCalled(0);
|
|
|
|
QCOMPARE(&m_window5, stack.topWindow());
|
|
|
|
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
|
QVERIFY(topWindow == &m_window2);
|
|
};
|
|
stack.raise(&m_window2);
|
|
verifyTopWindowChangedCalled();
|
|
}
|
|
|
|
void tst_QWasmWindowStack::raising()
|
|
{
|
|
QWasmWasmWindowStack stack(m_mockCallback);
|
|
|
|
stack.pushWindow(&m_root);
|
|
stack.pushWindow(&m_window1);
|
|
stack.pushWindow(&m_window2);
|
|
stack.pushWindow(&m_window3);
|
|
stack.pushWindow(&m_window4);
|
|
stack.pushWindow(&m_window5);
|
|
|
|
clearCallbackCounter();
|
|
|
|
QCOMPARE(&m_window5, stack.topWindow());
|
|
|
|
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
|
QVERIFY(topWindow == &m_window1);
|
|
};
|
|
stack.raise(&m_window1);
|
|
verifyTopWindowChangedCalled();
|
|
QCOMPARE(&m_window1, stack.topWindow());
|
|
|
|
stack.raise(&m_window1);
|
|
verifyTopWindowChangedCalled(0);
|
|
QCOMPARE(&m_window1, stack.topWindow());
|
|
|
|
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
|
QVERIFY(topWindow == &m_window3);
|
|
};
|
|
stack.raise(&m_window3);
|
|
verifyTopWindowChangedCalled();
|
|
QCOMPARE(&m_window3, stack.topWindow());
|
|
}
|
|
|
|
void tst_QWasmWindowStack::lowering()
|
|
{
|
|
QWasmWasmWindowStack stack(m_mockCallback);
|
|
|
|
stack.pushWindow(&m_root);
|
|
stack.pushWindow(&m_window1);
|
|
stack.pushWindow(&m_window2);
|
|
stack.pushWindow(&m_window3);
|
|
stack.pushWindow(&m_window4);
|
|
stack.pushWindow(&m_window5);
|
|
// Window order: 5 4 3 2 1 R
|
|
|
|
clearCallbackCounter();
|
|
|
|
QCOMPARE(&m_window5, stack.topWindow());
|
|
|
|
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
|
QVERIFY(topWindow == &m_window4);
|
|
};
|
|
stack.lower(&m_window5);
|
|
// Window order: 4 3 2 1 5 R
|
|
verifyTopWindowChangedCalled();
|
|
QCOMPARE(&m_window4, stack.topWindow());
|
|
|
|
stack.lower(&m_window3);
|
|
// Window order: 4 2 1 5 3 R
|
|
verifyTopWindowChangedCalled(0);
|
|
std::vector<QWasmWindow *> expectedWindowOrder = { &m_window4, &m_window2, &m_window1,
|
|
&m_window5, &m_window3, &m_root };
|
|
QVERIFY(std::equal(expectedWindowOrder.begin(), expectedWindowOrder.end(),
|
|
getWindowsFrontToBack(&stack).begin()));
|
|
}
|
|
|
|
void tst_QWasmWindowStack::removing()
|
|
{
|
|
QWasmWasmWindowStack stack(m_mockCallback);
|
|
|
|
stack.pushWindow(&m_root);
|
|
stack.pushWindow(&m_window1);
|
|
stack.pushWindow(&m_window2);
|
|
stack.pushWindow(&m_window3);
|
|
stack.pushWindow(&m_window4);
|
|
stack.pushWindow(&m_window5);
|
|
// Window order: 5 4 3 2 1 R
|
|
|
|
clearCallbackCounter();
|
|
|
|
QCOMPARE(&m_window5, stack.topWindow());
|
|
|
|
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
|
QVERIFY(topWindow == &m_window4);
|
|
};
|
|
stack.removeWindow(&m_window5);
|
|
// Window order: 4 3 2 1 R
|
|
verifyTopWindowChangedCalled();
|
|
QCOMPARE(&m_window4, stack.topWindow());
|
|
|
|
stack.removeWindow(&m_window2);
|
|
// Window order: 4 3 1 R
|
|
verifyTopWindowChangedCalled(0);
|
|
std::vector<QWasmWindow *> expectedWindowOrder = { &m_window4, &m_window3, &m_window1,
|
|
&m_root };
|
|
QVERIFY(std::equal(expectedWindowOrder.begin(), expectedWindowOrder.end(),
|
|
getWindowsFrontToBack(&stack).begin()));
|
|
}
|
|
|
|
void tst_QWasmWindowStack::removingTheRoot()
|
|
{
|
|
QWasmWasmWindowStack stack(m_mockCallback);
|
|
|
|
stack.pushWindow(&m_root);
|
|
stack.pushWindow(&m_window1);
|
|
stack.pushWindow(&m_window2);
|
|
stack.pushWindow(&m_window3);
|
|
// Window order: 3 2 1 R
|
|
|
|
clearCallbackCounter();
|
|
|
|
QCOMPARE(&m_window3, stack.topWindow());
|
|
|
|
stack.removeWindow(&m_root);
|
|
// Window order: 3 2 1
|
|
verifyTopWindowChangedCalled(0);
|
|
QCOMPARE(&m_window3, stack.topWindow());
|
|
|
|
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
|
QVERIFY(topWindow == &m_window1);
|
|
};
|
|
// Check that the new bottom window is not treated specially as a root
|
|
stack.raise(&m_window1);
|
|
// Window order: 1 3 2
|
|
verifyTopWindowChangedCalled();
|
|
std::vector<QWasmWindow *> expectedWindowOrder = { &m_window1, &m_window3, &m_window2 };
|
|
QVERIFY(std::equal(expectedWindowOrder.begin(), expectedWindowOrder.end(),
|
|
getWindowsFrontToBack(&stack).begin()));
|
|
|
|
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
|
QVERIFY(topWindow == &m_window3);
|
|
};
|
|
// Check that the new bottom window is not treated specially as a root
|
|
stack.lower(&m_window1);
|
|
// Window order: 3 2 1
|
|
verifyTopWindowChangedCalled();
|
|
expectedWindowOrder = { &m_window3, &m_window2, &m_window1 };
|
|
QVERIFY(std::equal(expectedWindowOrder.begin(), expectedWindowOrder.end(),
|
|
getWindowsFrontToBack(&stack).begin()));
|
|
}
|
|
|
|
QTEST_MAIN(tst_QWasmWindowStack)
|
|
#include "tst_qwasmwindowstack.moc"
|