Resolve window focusing problems on WASM
- Moved the modal window resolution to QWasmWindow::requestActivateWindow so that multiple async activation events are not issued in unpredictable patterns. - Request activation on added windows and on stack top in case of window removal Pick-to: 6.4 Change-Id: I6f02cf1b7e83abb7961caf311ffc83e91c8bf810 Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
This commit is contained in:
parent
0acb56518d
commit
11f12521bc
@ -53,7 +53,7 @@ EMSCRIPTEN_BINDINGS(qtMouseModule) {
|
||||
QWasmCompositor::QWasmCompositor(QWasmScreen *screen)
|
||||
: QObject(screen),
|
||||
m_windowManipulation(screen),
|
||||
m_windowStack(std::bind(&QWasmCompositor::onTopWindowChanged, this, std::placeholders::_1)),
|
||||
m_windowStack(std::bind(&QWasmCompositor::onTopWindowChanged, this)),
|
||||
m_blitter(new QOpenGLTextureBlitter),
|
||||
m_eventTranslator(std::make_unique<QWasmEventTranslator>())
|
||||
{
|
||||
@ -174,6 +174,7 @@ void QWasmCompositor::addWindow(QWasmWindow *window)
|
||||
{
|
||||
m_windowVisibility.insert(window, false);
|
||||
m_windowStack.pushWindow(window);
|
||||
m_windowStack.topWindow()->requestActivateWindow();
|
||||
}
|
||||
|
||||
void QWasmCompositor::removeWindow(QWasmWindow *window)
|
||||
@ -181,6 +182,8 @@ void QWasmCompositor::removeWindow(QWasmWindow *window)
|
||||
m_windowVisibility.remove(window);
|
||||
m_requestUpdateWindows.remove(window);
|
||||
m_windowStack.removeWindow(window);
|
||||
if (m_windowStack.topWindow())
|
||||
m_windowStack.topWindow()->requestActivateWindow();
|
||||
}
|
||||
|
||||
void QWasmCompositor::setVisible(QWasmWindow *window, bool visible)
|
||||
@ -755,21 +758,8 @@ void QWasmCompositor::WindowManipulation::resizeWindow(const QPoint& amount)
|
||||
));
|
||||
}
|
||||
|
||||
void QWasmCompositor::onTopWindowChanged(QWasmWindow *window)
|
||||
void QWasmCompositor::onTopWindowChanged()
|
||||
{
|
||||
if (!QGuiApplication::focusWindow())
|
||||
window->requestActivateWindow();
|
||||
|
||||
QWindow *modalWindow;
|
||||
const bool isTargetWindowBlocked =
|
||||
QGuiApplicationPrivate::instance()->isWindowBlocked(window->window(), &modalWindow);
|
||||
|
||||
if (isTargetWindowBlocked) {
|
||||
modalWindow->requestActivate();
|
||||
raise(asWasmWindow(modalWindow));
|
||||
return;
|
||||
}
|
||||
|
||||
requestUpdate();
|
||||
}
|
||||
|
||||
|
@ -176,7 +176,7 @@ private:
|
||||
std::unique_ptr<OperationState> m_state;
|
||||
};
|
||||
|
||||
void onTopWindowChanged(QWasmWindow *window);
|
||||
void onTopWindowChanged();
|
||||
void drawWindow(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, const QWasmWindow *window);
|
||||
void drawWindowContent(QOpenGLTextureBlitter *blitter, QWasmScreen *screen,
|
||||
const QWasmWindow *window);
|
||||
|
@ -421,6 +421,12 @@ bool QWasmWindow::windowIsPopupType(Qt::WindowFlags flags) const
|
||||
|
||||
void QWasmWindow::requestActivateWindow()
|
||||
{
|
||||
QWindow *modalWindow;
|
||||
if (QGuiApplicationPrivate::instance()->isWindowBlocked(window(), &modalWindow)) {
|
||||
static_cast<QWasmWindow *>(modalWindow->handle())->requestActivateWindow();
|
||||
return;
|
||||
}
|
||||
|
||||
if (window()->isTopLevel())
|
||||
raise();
|
||||
QPlatformWindow::requestActivateWindow();
|
||||
|
@ -18,7 +18,7 @@ void QWasmWasmWindowStack::pushWindow(QWasmWindow *window)
|
||||
|
||||
m_windowStack.push_back(window);
|
||||
|
||||
m_topWindowChangedCallback(window);
|
||||
m_topWindowChangedCallback();
|
||||
}
|
||||
|
||||
void QWasmWasmWindowStack::removeWindow(QWasmWindow *window)
|
||||
@ -34,7 +34,7 @@ void QWasmWasmWindowStack::removeWindow(QWasmWindow *window)
|
||||
m_windowStack.erase(it);
|
||||
|
||||
if (removingTop)
|
||||
m_topWindowChangedCallback(topWindow());
|
||||
m_topWindowChangedCallback();
|
||||
}
|
||||
|
||||
void QWasmWasmWindowStack::raise(QWasmWindow *window)
|
||||
@ -46,7 +46,7 @@ void QWasmWasmWindowStack::raise(QWasmWindow *window)
|
||||
|
||||
auto it = std::find(regularWindowsBegin(), m_windowStack.end(), window);
|
||||
std::rotate(it, it + 1, m_windowStack.end());
|
||||
m_topWindowChangedCallback(topWindow());
|
||||
m_topWindowChangedCallback();
|
||||
}
|
||||
|
||||
void QWasmWasmWindowStack::lower(QWasmWindow *window)
|
||||
@ -60,7 +60,7 @@ void QWasmWasmWindowStack::lower(QWasmWindow *window)
|
||||
auto it = std::find(regularWindowsBegin(), m_windowStack.end(), window);
|
||||
std::rotate(regularWindowsBegin(), it, it + 1);
|
||||
if (loweringTopWindow && topWindow() != window)
|
||||
m_topWindowChangedCallback(topWindow());
|
||||
m_topWindowChangedCallback();
|
||||
}
|
||||
|
||||
QWasmWasmWindowStack::iterator QWasmWasmWindowStack::begin()
|
||||
|
@ -24,7 +24,7 @@ class QWasmWindow;
|
||||
Q_AUTOTEST_EXPORT class QWasmWasmWindowStack
|
||||
{
|
||||
public:
|
||||
using TopWindowChangedCallbackType = std::function<void(QWasmWindow *window)>;
|
||||
using TopWindowChangedCallbackType = std::function<void()>;
|
||||
|
||||
using StorageType = QList<QWasmWindow *>;
|
||||
|
||||
|
@ -23,8 +23,7 @@ class tst_QWasmWindowStack : public QObject
|
||||
|
||||
public:
|
||||
tst_QWasmWindowStack()
|
||||
: m_mockCallback(
|
||||
std::bind(&tst_QWasmWindowStack::onTopWindowChanged, this, std::placeholders::_1))
|
||||
: m_mockCallback(std::bind(&tst_QWasmWindowStack::onTopWindowChanged, this))
|
||||
{
|
||||
}
|
||||
|
||||
@ -39,11 +38,11 @@ private slots:
|
||||
void removingTheRoot();
|
||||
|
||||
private:
|
||||
void onTopWindowChanged(QWasmWindow *topWindow)
|
||||
void onTopWindowChanged()
|
||||
{
|
||||
++m_topLevelChangedCallCount;
|
||||
if (m_onTopLevelChangedAction)
|
||||
m_onTopLevelChangedAction(topWindow);
|
||||
m_onTopLevelChangedAction();
|
||||
}
|
||||
|
||||
void verifyTopWindowChangedCalled(int expected = 1)
|
||||
@ -76,19 +75,15 @@ void tst_QWasmWindowStack::insertion()
|
||||
{
|
||||
QWasmWasmWindowStack stack(m_mockCallback);
|
||||
|
||||
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) { QVERIFY(topWindow == &m_root); };
|
||||
m_onTopLevelChangedAction = [this, &stack]() { QVERIFY(stack.topWindow() == &m_root); };
|
||||
stack.pushWindow(&m_root);
|
||||
verifyTopWindowChangedCalled();
|
||||
|
||||
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
||||
QVERIFY(topWindow == &m_window1);
|
||||
};
|
||||
m_onTopLevelChangedAction = [this, &stack]() { QVERIFY(stack.topWindow() == &m_window1); };
|
||||
stack.pushWindow(&m_window1);
|
||||
verifyTopWindowChangedCalled();
|
||||
|
||||
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
||||
QVERIFY(topWindow == &m_window2);
|
||||
};
|
||||
m_onTopLevelChangedAction = [this, &stack]() { QVERIFY(stack.topWindow() == &m_window2); };
|
||||
stack.pushWindow(&m_window2);
|
||||
verifyTopWindowChangedCalled();
|
||||
}
|
||||
@ -111,9 +106,7 @@ void tst_QWasmWindowStack::raisingTheRootIsImpossible()
|
||||
|
||||
QCOMPARE(&m_window5, stack.topWindow());
|
||||
|
||||
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
||||
QVERIFY(topWindow == &m_window2);
|
||||
};
|
||||
m_onTopLevelChangedAction = [this, &stack]() { QVERIFY(stack.topWindow() == &m_window2); };
|
||||
stack.raise(&m_window2);
|
||||
verifyTopWindowChangedCalled();
|
||||
}
|
||||
@ -133,9 +126,7 @@ void tst_QWasmWindowStack::raising()
|
||||
|
||||
QCOMPARE(&m_window5, stack.topWindow());
|
||||
|
||||
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
||||
QVERIFY(topWindow == &m_window1);
|
||||
};
|
||||
m_onTopLevelChangedAction = [this, &stack]() { QVERIFY(stack.topWindow() == &m_window1); };
|
||||
stack.raise(&m_window1);
|
||||
verifyTopWindowChangedCalled();
|
||||
QCOMPARE(&m_window1, stack.topWindow());
|
||||
@ -144,9 +135,7 @@ void tst_QWasmWindowStack::raising()
|
||||
verifyTopWindowChangedCalled(0);
|
||||
QCOMPARE(&m_window1, stack.topWindow());
|
||||
|
||||
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
||||
QVERIFY(topWindow == &m_window3);
|
||||
};
|
||||
m_onTopLevelChangedAction = [this, &stack]() { QVERIFY(stack.topWindow() == &m_window3); };
|
||||
stack.raise(&m_window3);
|
||||
verifyTopWindowChangedCalled();
|
||||
QCOMPARE(&m_window3, stack.topWindow());
|
||||
@ -168,9 +157,7 @@ void tst_QWasmWindowStack::lowering()
|
||||
|
||||
QCOMPARE(&m_window5, stack.topWindow());
|
||||
|
||||
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
||||
QVERIFY(topWindow == &m_window4);
|
||||
};
|
||||
m_onTopLevelChangedAction = [this, &stack]() { QVERIFY(stack.topWindow() == &m_window4); };
|
||||
stack.lower(&m_window5);
|
||||
// Window order: 4 3 2 1 5 R
|
||||
verifyTopWindowChangedCalled();
|
||||
@ -201,9 +188,7 @@ void tst_QWasmWindowStack::removing()
|
||||
|
||||
QCOMPARE(&m_window5, stack.topWindow());
|
||||
|
||||
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
||||
QVERIFY(topWindow == &m_window4);
|
||||
};
|
||||
m_onTopLevelChangedAction = [this, &stack]() { QVERIFY(stack.topWindow() == &m_window4); };
|
||||
stack.removeWindow(&m_window5);
|
||||
// Window order: 4 3 2 1 R
|
||||
verifyTopWindowChangedCalled();
|
||||
@ -237,9 +222,7 @@ void tst_QWasmWindowStack::removingTheRoot()
|
||||
verifyTopWindowChangedCalled(0);
|
||||
QCOMPARE(&m_window3, stack.topWindow());
|
||||
|
||||
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
||||
QVERIFY(topWindow == &m_window1);
|
||||
};
|
||||
m_onTopLevelChangedAction = [this, &stack]() { QVERIFY(stack.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
|
||||
@ -248,9 +231,7 @@ void tst_QWasmWindowStack::removingTheRoot()
|
||||
QVERIFY(std::equal(expectedWindowOrder.begin(), expectedWindowOrder.end(),
|
||||
getWindowsFrontToBack(&stack).begin()));
|
||||
|
||||
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
||||
QVERIFY(topWindow == &m_window3);
|
||||
};
|
||||
m_onTopLevelChangedAction = [this, &stack]() { QVERIFY(stack.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
|
||||
|
Loading…
x
Reference in New Issue
Block a user