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)
|
QWasmCompositor::QWasmCompositor(QWasmScreen *screen)
|
||||||
: QObject(screen),
|
: QObject(screen),
|
||||||
m_windowManipulation(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_blitter(new QOpenGLTextureBlitter),
|
||||||
m_eventTranslator(std::make_unique<QWasmEventTranslator>())
|
m_eventTranslator(std::make_unique<QWasmEventTranslator>())
|
||||||
{
|
{
|
||||||
@ -174,6 +174,7 @@ void QWasmCompositor::addWindow(QWasmWindow *window)
|
|||||||
{
|
{
|
||||||
m_windowVisibility.insert(window, false);
|
m_windowVisibility.insert(window, false);
|
||||||
m_windowStack.pushWindow(window);
|
m_windowStack.pushWindow(window);
|
||||||
|
m_windowStack.topWindow()->requestActivateWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWasmCompositor::removeWindow(QWasmWindow *window)
|
void QWasmCompositor::removeWindow(QWasmWindow *window)
|
||||||
@ -181,6 +182,8 @@ void QWasmCompositor::removeWindow(QWasmWindow *window)
|
|||||||
m_windowVisibility.remove(window);
|
m_windowVisibility.remove(window);
|
||||||
m_requestUpdateWindows.remove(window);
|
m_requestUpdateWindows.remove(window);
|
||||||
m_windowStack.removeWindow(window);
|
m_windowStack.removeWindow(window);
|
||||||
|
if (m_windowStack.topWindow())
|
||||||
|
m_windowStack.topWindow()->requestActivateWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWasmCompositor::setVisible(QWasmWindow *window, bool visible)
|
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();
|
requestUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +176,7 @@ private:
|
|||||||
std::unique_ptr<OperationState> m_state;
|
std::unique_ptr<OperationState> m_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
void onTopWindowChanged(QWasmWindow *window);
|
void onTopWindowChanged();
|
||||||
void drawWindow(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, const QWasmWindow *window);
|
void drawWindow(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, const QWasmWindow *window);
|
||||||
void drawWindowContent(QOpenGLTextureBlitter *blitter, QWasmScreen *screen,
|
void drawWindowContent(QOpenGLTextureBlitter *blitter, QWasmScreen *screen,
|
||||||
const QWasmWindow *window);
|
const QWasmWindow *window);
|
||||||
|
@ -421,6 +421,12 @@ bool QWasmWindow::windowIsPopupType(Qt::WindowFlags flags) const
|
|||||||
|
|
||||||
void QWasmWindow::requestActivateWindow()
|
void QWasmWindow::requestActivateWindow()
|
||||||
{
|
{
|
||||||
|
QWindow *modalWindow;
|
||||||
|
if (QGuiApplicationPrivate::instance()->isWindowBlocked(window(), &modalWindow)) {
|
||||||
|
static_cast<QWasmWindow *>(modalWindow->handle())->requestActivateWindow();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (window()->isTopLevel())
|
if (window()->isTopLevel())
|
||||||
raise();
|
raise();
|
||||||
QPlatformWindow::requestActivateWindow();
|
QPlatformWindow::requestActivateWindow();
|
||||||
|
@ -18,7 +18,7 @@ void QWasmWasmWindowStack::pushWindow(QWasmWindow *window)
|
|||||||
|
|
||||||
m_windowStack.push_back(window);
|
m_windowStack.push_back(window);
|
||||||
|
|
||||||
m_topWindowChangedCallback(window);
|
m_topWindowChangedCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWasmWasmWindowStack::removeWindow(QWasmWindow *window)
|
void QWasmWasmWindowStack::removeWindow(QWasmWindow *window)
|
||||||
@ -34,7 +34,7 @@ void QWasmWasmWindowStack::removeWindow(QWasmWindow *window)
|
|||||||
m_windowStack.erase(it);
|
m_windowStack.erase(it);
|
||||||
|
|
||||||
if (removingTop)
|
if (removingTop)
|
||||||
m_topWindowChangedCallback(topWindow());
|
m_topWindowChangedCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWasmWasmWindowStack::raise(QWasmWindow *window)
|
void QWasmWasmWindowStack::raise(QWasmWindow *window)
|
||||||
@ -46,7 +46,7 @@ void QWasmWasmWindowStack::raise(QWasmWindow *window)
|
|||||||
|
|
||||||
auto it = std::find(regularWindowsBegin(), m_windowStack.end(), window);
|
auto it = std::find(regularWindowsBegin(), m_windowStack.end(), window);
|
||||||
std::rotate(it, it + 1, m_windowStack.end());
|
std::rotate(it, it + 1, m_windowStack.end());
|
||||||
m_topWindowChangedCallback(topWindow());
|
m_topWindowChangedCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWasmWasmWindowStack::lower(QWasmWindow *window)
|
void QWasmWasmWindowStack::lower(QWasmWindow *window)
|
||||||
@ -60,7 +60,7 @@ void QWasmWasmWindowStack::lower(QWasmWindow *window)
|
|||||||
auto it = std::find(regularWindowsBegin(), m_windowStack.end(), window);
|
auto it = std::find(regularWindowsBegin(), m_windowStack.end(), window);
|
||||||
std::rotate(regularWindowsBegin(), it, it + 1);
|
std::rotate(regularWindowsBegin(), it, it + 1);
|
||||||
if (loweringTopWindow && topWindow() != window)
|
if (loweringTopWindow && topWindow() != window)
|
||||||
m_topWindowChangedCallback(topWindow());
|
m_topWindowChangedCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
QWasmWasmWindowStack::iterator QWasmWasmWindowStack::begin()
|
QWasmWasmWindowStack::iterator QWasmWasmWindowStack::begin()
|
||||||
|
@ -24,7 +24,7 @@ class QWasmWindow;
|
|||||||
Q_AUTOTEST_EXPORT class QWasmWasmWindowStack
|
Q_AUTOTEST_EXPORT class QWasmWasmWindowStack
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using TopWindowChangedCallbackType = std::function<void(QWasmWindow *window)>;
|
using TopWindowChangedCallbackType = std::function<void()>;
|
||||||
|
|
||||||
using StorageType = QList<QWasmWindow *>;
|
using StorageType = QList<QWasmWindow *>;
|
||||||
|
|
||||||
|
@ -23,8 +23,7 @@ class tst_QWasmWindowStack : public QObject
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
tst_QWasmWindowStack()
|
tst_QWasmWindowStack()
|
||||||
: m_mockCallback(
|
: m_mockCallback(std::bind(&tst_QWasmWindowStack::onTopWindowChanged, this))
|
||||||
std::bind(&tst_QWasmWindowStack::onTopWindowChanged, this, std::placeholders::_1))
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,11 +38,11 @@ private slots:
|
|||||||
void removingTheRoot();
|
void removingTheRoot();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onTopWindowChanged(QWasmWindow *topWindow)
|
void onTopWindowChanged()
|
||||||
{
|
{
|
||||||
++m_topLevelChangedCallCount;
|
++m_topLevelChangedCallCount;
|
||||||
if (m_onTopLevelChangedAction)
|
if (m_onTopLevelChangedAction)
|
||||||
m_onTopLevelChangedAction(topWindow);
|
m_onTopLevelChangedAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
void verifyTopWindowChangedCalled(int expected = 1)
|
void verifyTopWindowChangedCalled(int expected = 1)
|
||||||
@ -76,19 +75,15 @@ void tst_QWasmWindowStack::insertion()
|
|||||||
{
|
{
|
||||||
QWasmWasmWindowStack stack(m_mockCallback);
|
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);
|
stack.pushWindow(&m_root);
|
||||||
verifyTopWindowChangedCalled();
|
verifyTopWindowChangedCalled();
|
||||||
|
|
||||||
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
m_onTopLevelChangedAction = [this, &stack]() { QVERIFY(stack.topWindow() == &m_window1); };
|
||||||
QVERIFY(topWindow == &m_window1);
|
|
||||||
};
|
|
||||||
stack.pushWindow(&m_window1);
|
stack.pushWindow(&m_window1);
|
||||||
verifyTopWindowChangedCalled();
|
verifyTopWindowChangedCalled();
|
||||||
|
|
||||||
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
m_onTopLevelChangedAction = [this, &stack]() { QVERIFY(stack.topWindow() == &m_window2); };
|
||||||
QVERIFY(topWindow == &m_window2);
|
|
||||||
};
|
|
||||||
stack.pushWindow(&m_window2);
|
stack.pushWindow(&m_window2);
|
||||||
verifyTopWindowChangedCalled();
|
verifyTopWindowChangedCalled();
|
||||||
}
|
}
|
||||||
@ -111,9 +106,7 @@ void tst_QWasmWindowStack::raisingTheRootIsImpossible()
|
|||||||
|
|
||||||
QCOMPARE(&m_window5, stack.topWindow());
|
QCOMPARE(&m_window5, stack.topWindow());
|
||||||
|
|
||||||
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
m_onTopLevelChangedAction = [this, &stack]() { QVERIFY(stack.topWindow() == &m_window2); };
|
||||||
QVERIFY(topWindow == &m_window2);
|
|
||||||
};
|
|
||||||
stack.raise(&m_window2);
|
stack.raise(&m_window2);
|
||||||
verifyTopWindowChangedCalled();
|
verifyTopWindowChangedCalled();
|
||||||
}
|
}
|
||||||
@ -133,9 +126,7 @@ void tst_QWasmWindowStack::raising()
|
|||||||
|
|
||||||
QCOMPARE(&m_window5, stack.topWindow());
|
QCOMPARE(&m_window5, stack.topWindow());
|
||||||
|
|
||||||
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
m_onTopLevelChangedAction = [this, &stack]() { QVERIFY(stack.topWindow() == &m_window1); };
|
||||||
QVERIFY(topWindow == &m_window1);
|
|
||||||
};
|
|
||||||
stack.raise(&m_window1);
|
stack.raise(&m_window1);
|
||||||
verifyTopWindowChangedCalled();
|
verifyTopWindowChangedCalled();
|
||||||
QCOMPARE(&m_window1, stack.topWindow());
|
QCOMPARE(&m_window1, stack.topWindow());
|
||||||
@ -144,9 +135,7 @@ void tst_QWasmWindowStack::raising()
|
|||||||
verifyTopWindowChangedCalled(0);
|
verifyTopWindowChangedCalled(0);
|
||||||
QCOMPARE(&m_window1, stack.topWindow());
|
QCOMPARE(&m_window1, stack.topWindow());
|
||||||
|
|
||||||
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
m_onTopLevelChangedAction = [this, &stack]() { QVERIFY(stack.topWindow() == &m_window3); };
|
||||||
QVERIFY(topWindow == &m_window3);
|
|
||||||
};
|
|
||||||
stack.raise(&m_window3);
|
stack.raise(&m_window3);
|
||||||
verifyTopWindowChangedCalled();
|
verifyTopWindowChangedCalled();
|
||||||
QCOMPARE(&m_window3, stack.topWindow());
|
QCOMPARE(&m_window3, stack.topWindow());
|
||||||
@ -168,9 +157,7 @@ void tst_QWasmWindowStack::lowering()
|
|||||||
|
|
||||||
QCOMPARE(&m_window5, stack.topWindow());
|
QCOMPARE(&m_window5, stack.topWindow());
|
||||||
|
|
||||||
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
m_onTopLevelChangedAction = [this, &stack]() { QVERIFY(stack.topWindow() == &m_window4); };
|
||||||
QVERIFY(topWindow == &m_window4);
|
|
||||||
};
|
|
||||||
stack.lower(&m_window5);
|
stack.lower(&m_window5);
|
||||||
// Window order: 4 3 2 1 5 R
|
// Window order: 4 3 2 1 5 R
|
||||||
verifyTopWindowChangedCalled();
|
verifyTopWindowChangedCalled();
|
||||||
@ -201,9 +188,7 @@ void tst_QWasmWindowStack::removing()
|
|||||||
|
|
||||||
QCOMPARE(&m_window5, stack.topWindow());
|
QCOMPARE(&m_window5, stack.topWindow());
|
||||||
|
|
||||||
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
m_onTopLevelChangedAction = [this, &stack]() { QVERIFY(stack.topWindow() == &m_window4); };
|
||||||
QVERIFY(topWindow == &m_window4);
|
|
||||||
};
|
|
||||||
stack.removeWindow(&m_window5);
|
stack.removeWindow(&m_window5);
|
||||||
// Window order: 4 3 2 1 R
|
// Window order: 4 3 2 1 R
|
||||||
verifyTopWindowChangedCalled();
|
verifyTopWindowChangedCalled();
|
||||||
@ -237,9 +222,7 @@ void tst_QWasmWindowStack::removingTheRoot()
|
|||||||
verifyTopWindowChangedCalled(0);
|
verifyTopWindowChangedCalled(0);
|
||||||
QCOMPARE(&m_window3, stack.topWindow());
|
QCOMPARE(&m_window3, stack.topWindow());
|
||||||
|
|
||||||
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
m_onTopLevelChangedAction = [this, &stack]() { QVERIFY(stack.topWindow() == &m_window1); };
|
||||||
QVERIFY(topWindow == &m_window1);
|
|
||||||
};
|
|
||||||
// Check that the new bottom window is not treated specially as a root
|
// Check that the new bottom window is not treated specially as a root
|
||||||
stack.raise(&m_window1);
|
stack.raise(&m_window1);
|
||||||
// Window order: 1 3 2
|
// Window order: 1 3 2
|
||||||
@ -248,9 +231,7 @@ void tst_QWasmWindowStack::removingTheRoot()
|
|||||||
QVERIFY(std::equal(expectedWindowOrder.begin(), expectedWindowOrder.end(),
|
QVERIFY(std::equal(expectedWindowOrder.begin(), expectedWindowOrder.end(),
|
||||||
getWindowsFrontToBack(&stack).begin()));
|
getWindowsFrontToBack(&stack).begin()));
|
||||||
|
|
||||||
m_onTopLevelChangedAction = [this](QWasmWindow *topWindow) {
|
m_onTopLevelChangedAction = [this, &stack]() { QVERIFY(stack.topWindow() == &m_window3); };
|
||||||
QVERIFY(topWindow == &m_window3);
|
|
||||||
};
|
|
||||||
// Check that the new bottom window is not treated specially as a root
|
// Check that the new bottom window is not treated specially as a root
|
||||||
stack.lower(&m_window1);
|
stack.lower(&m_window1);
|
||||||
// Window order: 3 2 1
|
// Window order: 3 2 1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user