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.
This commit is contained in:
Aleix Pol 2021-07-21 01:41:38 +02:00
parent 9b5b02c957
commit abf22570c7
2 changed files with 64 additions and 4 deletions
autotests/integration
src

View file

@ -27,10 +27,12 @@
#include <QDBusPendingReply>
#include <KWaylandServer/clientconnection.h>
#include <KWaylandServer/display.h>
#include <KWaylandServer/seat_interface.h>
#include <KWaylandServer/surface_interface.h>
#include <KWayland/Client/compositor.h>
#include <KWayland/Client/output.h>
#include <KWayland/Client/region.h>
#include <KWayland/Client/surface.h>
#include <KWayland/Client/textinput.h>
#include <KWayland/Client/seat.h>
@ -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> surface(Test::createSurface());
QScopedPointer<Test::XdgToplevel> 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> 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"

View file

@ -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);
}