From 422522d15b6519eb426dfaa65fa0d0bea8419573 Mon Sep 17 00:00:00 2001 From: Aleix Pol Date: Wed, 21 Jul 2021 02:04:33 +0200 Subject: [PATCH] inputmethod: Also expose the visibility on dbus Since we adapted inputmethod to support methods like ibus, the input method can be active but not have a visible panel. This includes an extra property that will indicate us if the panel is visible at any time. This will allow us to properly render the virtual keyboard hide button in Plasma Mobile (or wherever we need it). --- autotests/integration/inputmethod_test.cpp | 41 ++++++++++++++++++++++ src/inputmethod.cpp | 8 +++++ src/inputmethod.h | 2 ++ src/virtualkeyboard_dbus.cpp | 6 ++++ src/virtualkeyboard_dbus.h | 3 ++ 5 files changed, 60 insertions(+) diff --git a/autotests/integration/inputmethod_test.cpp b/autotests/integration/inputmethod_test.cpp index b9fc2966fb..7e0a20bee3 100644 --- a/autotests/integration/inputmethod_test.cpp +++ b/autotests/integration/inputmethod_test.cpp @@ -54,6 +54,7 @@ private Q_SLOTS: void testOpenClose(); void testEnableDisableV3(); void testEnableActive(); + void testHidePanel(); }; @@ -235,6 +236,46 @@ void InputMethodTest::testEnableActive() QVERIFY(Test::waitForWindowDestroyed(client)); } +void InputMethodTest::testHidePanel() +{ + QVERIFY(!InputMethod::self()->isActive()); + + QSignalSpy clientAddedSpy(workspace(), &Workspace::clientAdded); + QSignalSpy clientRemovedSpy(workspace(), &Workspace::clientRemoved); + QVERIFY(clientAddedSpy.isValid()); + + QSignalSpy activateSpy(InputMethod::self(), &InputMethod::activeChanged); + QScopedPointer textInput(Test::waylandTextInputManager()->createTextInput(Test::waylandSeat())); + textInput->showInputPanel(); + QVERIFY(clientAddedSpy.wait()); + + // 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); + waylandServer()->seat()->setFocusedTextInputSurface(client->surface()); + + QCOMPARE(workspace()->activeClient(), client); + + QCOMPARE(clientAddedSpy.count(), 2); + QVERIFY(activateSpy.count() || activateSpy.wait()); + QVERIFY(InputMethod::self()->isActive()); + + auto keyboardClient = Test::inputPanelClient(); + auto ipsurface = Test::inputPanelSurface(); + QVERIFY(keyboardClient); + clientRemovedSpy.clear(); + delete ipsurface; + QVERIFY(InputMethod::self()->isVisible()); + QVERIFY(clientRemovedSpy.count() || clientRemovedSpy.wait()); + QVERIFY(!InputMethod::self()->isVisible()); + + // 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 72f04d1089..0e64ee7f51 100644 --- a/src/inputmethod.cpp +++ b/src/inputmethod.cpp @@ -165,6 +165,10 @@ void InputMethod::clientAdded(AbstractClient *_client) connect(m_inputClient, &AbstractClient::frameGeometryChanged, this, &InputMethod::updateInputPanelState); connect(m_inputClient, &AbstractClient::windowHidden, this, &InputMethod::updateInputPanelState); connect(m_inputClient, &AbstractClient::windowClosed, this, &InputMethod::updateInputPanelState); + connect(m_inputClient, &AbstractClient::windowShown, this, &InputMethod::visibleChanged); + connect(m_inputClient, &AbstractClient::windowHidden, this, &InputMethod::visibleChanged); + connect(m_inputClient, &AbstractClient::windowClosed, this, &InputMethod::visibleChanged); + Q_EMIT visibleChanged(); updateInputPanelState(); } @@ -688,5 +692,9 @@ void InputMethod::installKeyboardGrab(KWaylandServer::InputMethodGrabV1 *keyboar }); } +bool InputMethod::isVisible() const +{ + return m_inputClient && m_inputClient->isShown(false); } +} diff --git a/src/inputmethod.h b/src/inputmethod.h index f891d52494..c598dffbb7 100644 --- a/src/inputmethod.h +++ b/src/inputmethod.h @@ -51,12 +51,14 @@ public: void setActive(bool active); void hide(); void show(); + bool isVisible() const; void setInputMethodCommand(const QString &path); Q_SIGNALS: void activeChanged(bool active); void enabledChanged(bool enabled); + void visibleChanged(); private Q_SLOTS: void clientAdded(AbstractClient* client); diff --git a/src/virtualkeyboard_dbus.cpp b/src/virtualkeyboard_dbus.cpp index 9a66cf7f2e..351feb3322 100644 --- a/src/virtualkeyboard_dbus.cpp +++ b/src/virtualkeyboard_dbus.cpp @@ -22,6 +22,7 @@ VirtualKeyboardDBus::VirtualKeyboardDBus(InputMethod *parent) QDBusConnection::ExportAllSlots); connect(parent, &InputMethod::activeChanged, this, &VirtualKeyboardDBus::activeChanged); connect(parent, &InputMethod::enabledChanged, this, &VirtualKeyboardDBus::enabledChanged); + connect(parent, &InputMethod::visibleChanged, this, &VirtualKeyboardDBus::visibleChanged); } VirtualKeyboardDBus::~VirtualKeyboardDBus() = default; @@ -46,4 +47,9 @@ bool VirtualKeyboardDBus::isEnabled() const return m_inputMethod->isEnabled(); } +bool VirtualKeyboardDBus::isVisible() const +{ + return m_inputMethod->isVisible(); +} + } diff --git a/src/virtualkeyboard_dbus.h b/src/virtualkeyboard_dbus.h index e07a7d6a62..f55a20a2e9 100644 --- a/src/virtualkeyboard_dbus.h +++ b/src/virtualkeyboard_dbus.h @@ -20,11 +20,13 @@ class KWIN_EXPORT VirtualKeyboardDBus : public QObject Q_CLASSINFO("D-Bus Interface", "org.kde.kwin.VirtualKeyboard") Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged) Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged) + Q_PROPERTY(bool visible READ isVisible NOTIFY visibleChanged) public: explicit VirtualKeyboardDBus(InputMethod *inputMethod); ~VirtualKeyboardDBus() override; bool isEnabled() const; + bool isVisible() const; bool isActive() const; void setEnabled(bool enabled); void setActive(bool active); @@ -32,6 +34,7 @@ public: Q_SIGNALS: Q_SCRIPTABLE void enabledChanged(); Q_SCRIPTABLE void activeChanged(); + Q_SCRIPTABLE void visibleChanged(); private: InputMethod *const m_inputMethod;