From 84f54e9ffa5d68bcc531874be7f6818b299f1610 Mon Sep 17 00:00:00 2001 From: Weng Xuetian Date: Mon, 24 Oct 2022 16:38:40 -0700 Subject: [PATCH] Implement a enableRequested signal for text-input-v3 The signal will be emitted if text-input-v3 applies a new enable state if it's already enabled. In Gtk's implementation, sending text_input_v3.enable for the second time has the similar semantics of text-input-v2.showInputPanel. Try to connect them together and add corresponding test. See also: https://github.com/GNOME/gtk/blob/a95cfb1c457cbd3ff365f7f1244c42dda8540b66/gtk/gtkimcontextwayland.c#L555 --- autotests/integration/inputmethod_test.cpp | 22 +++++++++++++++++++ src/inputmethod.cpp | 6 +++++ src/inputmethod.h | 1 + .../server/test_textinputv3_interface.cpp | 16 ++++++++++++++ src/wayland/textinput_v3_interface.cpp | 5 +++++ src/wayland/textinput_v3_interface.h | 7 ++++++ 6 files changed, 57 insertions(+) diff --git a/autotests/integration/inputmethod_test.cpp b/autotests/integration/inputmethod_test.cpp index acd390cb58..0f2c8456ea 100644 --- a/autotests/integration/inputmethod_test.cpp +++ b/autotests/integration/inputmethod_test.cpp @@ -188,8 +188,12 @@ void InputMethodTest::testEnableDisableV3() auto textInputV3 = std::make_unique(); textInputV3->init(Test::waylandTextInputManagerV3()->get_text_input(*(Test::waylandSeat()))); + + // Show the keyboard + touchNow(); textInputV3->enable(); + QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded); QSignalSpy inputMethodActiveSpy(kwinApp()->inputMethod(), &InputMethod::activeChanged); // just enabling the text-input should not show it but rather on commit QVERIFY(!kwinApp()->inputMethod()->isActive()); @@ -197,6 +201,24 @@ void InputMethodTest::testEnableDisableV3() QVERIFY(inputMethodActiveSpy.count() || inputMethodActiveSpy.wait()); QVERIFY(kwinApp()->inputMethod()->isActive()); + QVERIFY(windowAddedSpy.wait()); + Window *keyboardClient = windowAddedSpy.last().first().value(); + QVERIFY(keyboardClient); + QVERIFY(keyboardClient->isInputMethod()); + QVERIFY(keyboardClient->isShown()); + + // Text input v3 doesn't have hideInputPanel, just simiulate the hide from dbus call + kwinApp()->inputMethod()->hide(); + QVERIFY(!keyboardClient->isShown()); + + QSignalSpy windowShownSpy(keyboardClient, &Window::windowShown); + // Force enable the text input object. This is what's done by Gtk. + textInputV3->enable(); + textInputV3->commit(); + + windowShownSpy.wait(); + QVERIFY(keyboardClient->isShown()); + // disable text input and ensure that it is not hiding input panel without commit inputMethodActiveSpy.clear(); QVERIFY(kwinApp()->inputMethod()->isActive()); diff --git a/src/inputmethod.cpp b/src/inputmethod.cpp index 3a73fb565c..d3d62f26a3 100644 --- a/src/inputmethod.cpp +++ b/src/inputmethod.cpp @@ -130,6 +130,7 @@ void InputMethod::init() connect(textInputV3, &TextInputV3Interface::contentTypeChanged, this, &InputMethod::contentTypeChanged); connect(textInputV3, &TextInputV3Interface::stateCommitted, this, &InputMethod::stateCommitted); connect(textInputV3, &TextInputV3Interface::enabledChanged, this, &InputMethod::textInputInterfaceV3EnabledChanged); + connect(textInputV3, &TextInputV3Interface::enableRequested, this, &InputMethod::textInputInterfaceV3EnableRequested); connect(input()->keyboard()->xkb(), &Xkb::modifierStateChanged, this, [this]() { m_hasPendingModifiers = true; @@ -851,4 +852,9 @@ void InputMethod::forceActivate() show(); } +void InputMethod::textInputInterfaceV3EnableRequested() +{ + refreshActive(); + show(); +} } diff --git a/src/inputmethod.h b/src/inputmethod.h index 3f48281abd..9d262f7e4f 100644 --- a/src/inputmethod.h +++ b/src/inputmethod.h @@ -92,6 +92,7 @@ private Q_SLOTS: void textInputInterfaceV3EnabledChanged(); void stateCommitted(uint32_t serial); void textInputInterfaceV2StateUpdated(quint32 serial, KWaylandServer::TextInputV2Interface::UpdateReason reason); + void textInputInterfaceV3EnableRequested(); // inputcontext slots void setPreeditString(uint32_t serial, const QString &text, const QString &commit); diff --git a/src/wayland/autotests/server/test_textinputv3_interface.cpp b/src/wayland/autotests/server/test_textinputv3_interface.cpp index 707241ba8d..849cab062e 100644 --- a/src/wayland/autotests/server/test_textinputv3_interface.cpp +++ b/src/wayland/autotests/server/test_textinputv3_interface.cpp @@ -224,6 +224,7 @@ void TestTextInputV3Interface::testEnableDisable() QSignalSpy focusedSurfaceChangedSpy(m_seat, &SeatInterface::focusedTextInputSurfaceChanged); QSignalSpy textInputEnabledSpy(m_serverTextInputV3, &TextInputV3Interface::enabledChanged); QSignalSpy cursorRectangleChangedSpy(m_serverTextInputV3, &TextInputV3Interface::cursorRectangleChanged); + QSignalSpy enableRequestedSpy(m_serverTextInputV3, &TextInputV3Interface::enableRequested); QSignalSpy surfaceEnterSpy(m_clientTextInputV3, &TextInputV3::surface_enter); QSignalSpy surfaceLeaveSpy(m_clientTextInputV3, &TextInputV3::surface_leave); @@ -251,6 +252,7 @@ void TestTextInputV3Interface::testEnableDisable() QVERIFY(textInputEnabledSpy.wait()); m_totalCommits++; + QCOMPARE(enableRequestedSpy.count(), 0); QCOMPARE(textInputEnabledSpy.count(), 1); QCOMPARE(cursorRectangleChangedSpy.count(), 1); QCOMPARE(m_serverTextInputV3->cursorRectangle(), QRect(0, 0, 20, 20)); @@ -258,6 +260,20 @@ void TestTextInputV3Interface::testEnableDisable() QCOMPARE(m_serverTextInputV3->surroundingTextCursorPosition(), 0); QCOMPARE(m_serverTextInputV3->surroundingTextSelectionAnchor(), 3); + // Do another enable when it's already enabled. + m_clientTextInputV3->enable(); + m_clientTextInputV3->set_cursor_rectangle(0, 0, 20, 20); + m_clientTextInputV3->set_surrounding_text("KDE Plasma Desktop", 0, 3); + m_clientTextInputV3->commit(); + QVERIFY(enableRequestedSpy.wait()); + QCOMPARE(textInputEnabledSpy.count(), 1); + QCOMPARE(cursorRectangleChangedSpy.count(), 1); + QCOMPARE(m_serverTextInputV3->cursorRectangle(), QRect(0, 0, 20, 20)); + QCOMPARE(m_serverTextInputV3->surroundingText(), QString("KDE Plasma Desktop")); + QCOMPARE(m_serverTextInputV3->surroundingTextCursorPosition(), 0); + QCOMPARE(m_serverTextInputV3->surroundingTextSelectionAnchor(), 3); + m_totalCommits++; + // disabling we should not get the event m_clientTextInputV3->disable(); QCOMPARE(textInputEnabledSpy.count(), 1); diff --git a/src/wayland/textinput_v3_interface.cpp b/src/wayland/textinput_v3_interface.cpp index 624c399cec..5184be74a7 100644 --- a/src/wayland/textinput_v3_interface.cpp +++ b/src/wayland/textinput_v3_interface.cpp @@ -355,6 +355,7 @@ void TextInputV3InterfacePrivate::zwp_text_input_v3_commit(Resource *resource) serialHash[resource]++; auto &resourceEnabled = enabled[resource]; + const auto oldResourceEnabled = resourceEnabled; if (resourceEnabled != pending.enabled) { resourceEnabled = pending.enabled; } @@ -398,6 +399,10 @@ void TextInputV3InterfacePrivate::zwp_text_input_v3_commit(Resource *resource) send_preedit_string(resource->handle, preeditText, preeditCursorBegin, preeditCursorEnd); } send_done(resource->handle, serialHash[resource]); + + if (resourceEnabled && oldResourceEnabled) { + Q_EMIT q->enableRequested(); + } } void TextInputV3InterfacePrivate::defaultPending() diff --git a/src/wayland/textinput_v3_interface.h b/src/wayland/textinput_v3_interface.h index 547dfd4967..eabab14c3b 100644 --- a/src/wayland/textinput_v3_interface.h +++ b/src/wayland/textinput_v3_interface.h @@ -188,6 +188,13 @@ Q_SIGNALS: */ void stateCommitted(quint32 serial); + /** + * Emitted whenever this TextInputV3Interface is already enabled, but received another enable from client. + * @see isEnabled + * @see surface + */ + void enableRequested(); + private: friend class TextInputManagerV3InterfacePrivate; friend class SeatInterface;