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: a95cfb1c45/gtk/gtkimcontextwayland.c (L555)
This commit is contained in:
Weng Xuetian 2022-10-24 16:38:40 -07:00 committed by Xuetian Weng
parent 7f7fa69135
commit 84f54e9ffa
6 changed files with 57 additions and 0 deletions

View file

@ -188,8 +188,12 @@ void InputMethodTest::testEnableDisableV3()
auto textInputV3 = std::make_unique<Test::TextInputV3>(); auto textInputV3 = std::make_unique<Test::TextInputV3>();
textInputV3->init(Test::waylandTextInputManagerV3()->get_text_input(*(Test::waylandSeat()))); textInputV3->init(Test::waylandTextInputManagerV3()->get_text_input(*(Test::waylandSeat())));
// Show the keyboard
touchNow();
textInputV3->enable(); textInputV3->enable();
QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded);
QSignalSpy inputMethodActiveSpy(kwinApp()->inputMethod(), &InputMethod::activeChanged); QSignalSpy inputMethodActiveSpy(kwinApp()->inputMethod(), &InputMethod::activeChanged);
// just enabling the text-input should not show it but rather on commit // just enabling the text-input should not show it but rather on commit
QVERIFY(!kwinApp()->inputMethod()->isActive()); QVERIFY(!kwinApp()->inputMethod()->isActive());
@ -197,6 +201,24 @@ void InputMethodTest::testEnableDisableV3()
QVERIFY(inputMethodActiveSpy.count() || inputMethodActiveSpy.wait()); QVERIFY(inputMethodActiveSpy.count() || inputMethodActiveSpy.wait());
QVERIFY(kwinApp()->inputMethod()->isActive()); QVERIFY(kwinApp()->inputMethod()->isActive());
QVERIFY(windowAddedSpy.wait());
Window *keyboardClient = windowAddedSpy.last().first().value<Window *>();
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 // disable text input and ensure that it is not hiding input panel without commit
inputMethodActiveSpy.clear(); inputMethodActiveSpy.clear();
QVERIFY(kwinApp()->inputMethod()->isActive()); QVERIFY(kwinApp()->inputMethod()->isActive());

View file

@ -130,6 +130,7 @@ void InputMethod::init()
connect(textInputV3, &TextInputV3Interface::contentTypeChanged, this, &InputMethod::contentTypeChanged); connect(textInputV3, &TextInputV3Interface::contentTypeChanged, this, &InputMethod::contentTypeChanged);
connect(textInputV3, &TextInputV3Interface::stateCommitted, this, &InputMethod::stateCommitted); connect(textInputV3, &TextInputV3Interface::stateCommitted, this, &InputMethod::stateCommitted);
connect(textInputV3, &TextInputV3Interface::enabledChanged, this, &InputMethod::textInputInterfaceV3EnabledChanged); connect(textInputV3, &TextInputV3Interface::enabledChanged, this, &InputMethod::textInputInterfaceV3EnabledChanged);
connect(textInputV3, &TextInputV3Interface::enableRequested, this, &InputMethod::textInputInterfaceV3EnableRequested);
connect(input()->keyboard()->xkb(), &Xkb::modifierStateChanged, this, [this]() { connect(input()->keyboard()->xkb(), &Xkb::modifierStateChanged, this, [this]() {
m_hasPendingModifiers = true; m_hasPendingModifiers = true;
@ -851,4 +852,9 @@ void InputMethod::forceActivate()
show(); show();
} }
void InputMethod::textInputInterfaceV3EnableRequested()
{
refreshActive();
show();
}
} }

View file

@ -92,6 +92,7 @@ private Q_SLOTS:
void textInputInterfaceV3EnabledChanged(); void textInputInterfaceV3EnabledChanged();
void stateCommitted(uint32_t serial); void stateCommitted(uint32_t serial);
void textInputInterfaceV2StateUpdated(quint32 serial, KWaylandServer::TextInputV2Interface::UpdateReason reason); void textInputInterfaceV2StateUpdated(quint32 serial, KWaylandServer::TextInputV2Interface::UpdateReason reason);
void textInputInterfaceV3EnableRequested();
// inputcontext slots // inputcontext slots
void setPreeditString(uint32_t serial, const QString &text, const QString &commit); void setPreeditString(uint32_t serial, const QString &text, const QString &commit);

View file

@ -224,6 +224,7 @@ void TestTextInputV3Interface::testEnableDisable()
QSignalSpy focusedSurfaceChangedSpy(m_seat, &SeatInterface::focusedTextInputSurfaceChanged); QSignalSpy focusedSurfaceChangedSpy(m_seat, &SeatInterface::focusedTextInputSurfaceChanged);
QSignalSpy textInputEnabledSpy(m_serverTextInputV3, &TextInputV3Interface::enabledChanged); QSignalSpy textInputEnabledSpy(m_serverTextInputV3, &TextInputV3Interface::enabledChanged);
QSignalSpy cursorRectangleChangedSpy(m_serverTextInputV3, &TextInputV3Interface::cursorRectangleChanged); QSignalSpy cursorRectangleChangedSpy(m_serverTextInputV3, &TextInputV3Interface::cursorRectangleChanged);
QSignalSpy enableRequestedSpy(m_serverTextInputV3, &TextInputV3Interface::enableRequested);
QSignalSpy surfaceEnterSpy(m_clientTextInputV3, &TextInputV3::surface_enter); QSignalSpy surfaceEnterSpy(m_clientTextInputV3, &TextInputV3::surface_enter);
QSignalSpy surfaceLeaveSpy(m_clientTextInputV3, &TextInputV3::surface_leave); QSignalSpy surfaceLeaveSpy(m_clientTextInputV3, &TextInputV3::surface_leave);
@ -251,6 +252,7 @@ void TestTextInputV3Interface::testEnableDisable()
QVERIFY(textInputEnabledSpy.wait()); QVERIFY(textInputEnabledSpy.wait());
m_totalCommits++; m_totalCommits++;
QCOMPARE(enableRequestedSpy.count(), 0);
QCOMPARE(textInputEnabledSpy.count(), 1); QCOMPARE(textInputEnabledSpy.count(), 1);
QCOMPARE(cursorRectangleChangedSpy.count(), 1); QCOMPARE(cursorRectangleChangedSpy.count(), 1);
QCOMPARE(m_serverTextInputV3->cursorRectangle(), QRect(0, 0, 20, 20)); QCOMPARE(m_serverTextInputV3->cursorRectangle(), QRect(0, 0, 20, 20));
@ -258,6 +260,20 @@ void TestTextInputV3Interface::testEnableDisable()
QCOMPARE(m_serverTextInputV3->surroundingTextCursorPosition(), 0); QCOMPARE(m_serverTextInputV3->surroundingTextCursorPosition(), 0);
QCOMPARE(m_serverTextInputV3->surroundingTextSelectionAnchor(), 3); 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 // disabling we should not get the event
m_clientTextInputV3->disable(); m_clientTextInputV3->disable();
QCOMPARE(textInputEnabledSpy.count(), 1); QCOMPARE(textInputEnabledSpy.count(), 1);

View file

@ -355,6 +355,7 @@ void TextInputV3InterfacePrivate::zwp_text_input_v3_commit(Resource *resource)
serialHash[resource]++; serialHash[resource]++;
auto &resourceEnabled = enabled[resource]; auto &resourceEnabled = enabled[resource];
const auto oldResourceEnabled = resourceEnabled;
if (resourceEnabled != pending.enabled) { if (resourceEnabled != pending.enabled) {
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_preedit_string(resource->handle, preeditText, preeditCursorBegin, preeditCursorEnd);
} }
send_done(resource->handle, serialHash[resource]); send_done(resource->handle, serialHash[resource]);
if (resourceEnabled && oldResourceEnabled) {
Q_EMIT q->enableRequested();
}
} }
void TextInputV3InterfacePrivate::defaultPending() void TextInputV3InterfacePrivate::defaultPending()

View file

@ -188,6 +188,13 @@ Q_SIGNALS:
*/ */
void stateCommitted(quint32 serial); void stateCommitted(quint32 serial);
/**
* Emitted whenever this TextInputV3Interface is already enabled, but received another enable from client.
* @see isEnabled
* @see surface
*/
void enableRequested();
private: private:
friend class TextInputManagerV3InterfacePrivate; friend class TextInputManagerV3InterfacePrivate;
friend class SeatInterface; friend class SeatInterface;