From abf22570c7c3d88f0338c0ce05246a388e484327 Mon Sep 17 00:00:00 2001 From: Aleix Pol Date: Wed, 21 Jul 2021 01:41:38 +0200 Subject: [PATCH] inputmethod: Reduce consecutive activation+deactivation+activation sequences So far calling setActive(true) would issue a deactivation then another activation. This sometimes makes maliit crash and we can achieve the same result just by just issuing a reset. --- autotests/integration/inputmethod_test.cpp | 54 ++++++++++++++++++++++ src/inputmethod.cpp | 14 ++++-- 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/autotests/integration/inputmethod_test.cpp b/autotests/integration/inputmethod_test.cpp index 53803d08cb..b9fc2966fb 100644 --- a/autotests/integration/inputmethod_test.cpp +++ b/autotests/integration/inputmethod_test.cpp @@ -27,10 +27,12 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -51,6 +53,7 @@ private Q_SLOTS: void testOpenClose(); void testEnableDisableV3(); + void testEnableActive(); }; @@ -181,6 +184,57 @@ void InputMethodTest::testEnableDisableV3() QVERIFY(!InputMethod::self()->isActive()); } +void InputMethodTest::testEnableActive() +{ + QVERIFY(!InputMethod::self()->isActive()); + + QSignalSpy clientAddedSpy(workspace(), &Workspace::clientAdded); + QSignalSpy clientRemovedSpy(workspace(), &Workspace::clientRemoved); + + QSignalSpy activateSpy(InputMethod::self(), &InputMethod::activeChanged); + + // Create an xdg_toplevel surface and wait for the compositor to catch up. + QScopedPointer surface(Test::createSurface()); + QScopedPointer shellSurface(Test::createXdgToplevelSurface(surface.data())); + AbstractClient *client = Test::renderAndWaitForShown(surface.data(), QSize(1280, 1024), Qt::red); + QVERIFY(client); + QVERIFY(client->isActive()); + QCOMPARE(client->frameGeometry().size(), QSize(1280, 1024)); + QSignalSpy frameGeometryChangedSpy(client, &AbstractClient::frameGeometryChanged); + QVERIFY(frameGeometryChangedSpy.isValid()); + QSignalSpy toplevelConfigureRequestedSpy(shellSurface.data(), &Test::XdgToplevel::configureRequested); + QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested); + + QScopedPointer textInput(Test::waylandTextInputManager()->createTextInput(Test::waylandSeat())); + + QVERIFY(!textInput.isNull()); + textInput->enable(surface.data()); + QVERIFY(surfaceConfigureRequestedSpy.wait()); + QCOMPARE(clientAddedSpy.count(), 1); + + // Show the keyboard + textInput->showInputPanel(); + QVERIFY(clientAddedSpy.wait()); + + QCOMPARE(workspace()->activeClient(), client); + + activateSpy.clear(); + textInput->enable(surface.get()); + textInput->showInputPanel(); + activateSpy.wait(200); + QVERIFY(activateSpy.isEmpty()); + QVERIFY(InputMethod::self()->isActive()); + auto keyboardClient = Test::inputPanelClient(); + QVERIFY(keyboardClient); + textInput->enable(surface.get()); + + QVERIFY(InputMethod::self()->isActive()); + + // Destroy the test client. + shellSurface.reset(); + QVERIFY(Test::waitForWindowDestroyed(client)); +} + WAYLANDTEST_MAIN(InputMethodTest) #include "inputmethod_test.moc" diff --git a/src/inputmethod.cpp b/src/inputmethod.cpp index d82d92aa8d..72f04d1089 100644 --- a/src/inputmethod.cpp +++ b/src/inputmethod.cpp @@ -118,15 +118,21 @@ void InputMethod::hide() void InputMethod::setActive(bool active) { - bool wasActive = waylandServer()->inputMethod()->context(); - waylandServer()->inputMethod()->sendDeactivate(); + const bool wasActive = waylandServer()->inputMethod()->context(); + if (wasActive && !active) { + waylandServer()->inputMethod()->sendDeactivate(); + } if (active) { if (!m_enabled) { return; } - waylandServer()->inputMethod()->sendActivate(); + if (!wasActive) { + waylandServer()->inputMethod()->sendActivate(); + } else { + waylandServer()->inputMethod()->context()->sendReset(); + } adoptInputMethodContext(); } else { updateInputPanelState(); @@ -144,7 +150,7 @@ void InputMethod::clientAdded(AbstractClient *_client) } if (m_inputClient) { - qCWarning(KWIN_VIRTUALKEYBOARD) << "Replacing input client" << m_inputClient; + qCWarning(KWIN_VIRTUALKEYBOARD) << "Replacing input client" << m_inputClient << "with" << _client; disconnect(m_inputClient, nullptr, this, nullptr); }