inputmethod: Provide DBus API so the shell can integrate with it

It makes it possible to show if the virtual keyboard is being shown and
if it is to hide it.
This commit is contained in:
Aleix Pol 2021-02-23 16:12:38 +01:00 committed by Aleix Pol Gonzalez
parent 6a26540065
commit 63a7b25801
8 changed files with 123 additions and 93 deletions

View file

@ -3,4 +3,5 @@
set(KWIN_INTERFACE "@PACKAGE_KDE_INSTALL_DBUSINTERFACEDIR@/org.kde.KWin.xml")
set(KWIN_COMPOSITING_INTERFACE "@PACKAGE_KDE_INSTALL_DBUSINTERFACEDIR@/org.kde.kwin.Compositing.xml")
set(KWIN_EFFECTS_INTERFACE "@PACKAGE_KDE_INSTALL_DBUSINTERFACEDIR@/org.kde.kwin.Effects.xml")
set(KWIN_VIRTUALKEYBOARD_INTERFACE "@PACKAGE_KDE_INSTALL_DBUSINTERFACEDIR@/org.kde.kwin.VirtualKeyboard.xml")
set(KWIN_WAYLAND_BIN_PATH "@CMAKE_INSTALL_FULL_BINDIR@/kwin_wayland")

View file

@ -380,7 +380,9 @@ if (HAVE_GBM)
ecm_mark_as_test(testGbmSurface)
endif()
add_executable(testVirtualKeyboardDBus test_virtualkeyboard_dbus.cpp ../src/virtualkeyboard_dbus.cpp)
qt5_add_dbus_interfaces(DBUS_SRCS ${CMAKE_BINARY_DIR}/src/org.kde.kwin.VirtualKeyboard.xml)
add_executable(testVirtualKeyboardDBus test_virtualkeyboard_dbus.cpp ../src/virtualkeyboard_dbus.cpp ${DBUS_SRCS})
target_link_libraries(testVirtualKeyboardDBus
Qt::DBus
Qt::Test

View file

@ -12,6 +12,7 @@
#include <QDBusPendingReply>
#include <QSignalSpy>
#include <virtualkeyboardinterface.h>
#include "virtualkeyboard_dbus.h"
using KWin::VirtualKeyboardDBus;
@ -26,32 +27,6 @@ private Q_SLOTS:
void testRequestEnabled();
};
class DbusPropertyHelper : public QObject
{
Q_OBJECT
public:
DbusPropertyHelper()
: QObject(nullptr)
{
QDBusConnection::sessionBus().connect(
QStringLiteral("org.kde.kwin.testvirtualkeyboard"),
QStringLiteral("/VirtualKeyboard"),
QStringLiteral("org.kde.kwin.VirtualKeyboard"),
QStringLiteral("enabledChanged"),
this,
SLOT(slotEnabledChanged()));
}
~DbusPropertyHelper() override = default;
Q_SIGNALS:
void enabledChanged();
private Q_SLOTS:
void slotEnabledChanged() {
emit enabledChanged();
}
};
void VirtualKeyboardDBusTest::initTestCase()
{
QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.kwin.testvirtualkeyboard"));
@ -60,8 +35,8 @@ void VirtualKeyboardDBusTest::initTestCase()
void VirtualKeyboardDBusTest::testEnabled()
{
VirtualKeyboardDBus dbus;
DbusPropertyHelper helper;
QSignalSpy helperChangedSpy(&helper, &DbusPropertyHelper::enabledChanged);
OrgKdeKwinVirtualKeyboardInterface iface(QStringLiteral("org.kde.kwin.testvirtualkeyboard"), QStringLiteral("/VirtualKeyboard"), QDBusConnection::sessionBus());
QSignalSpy helperChangedSpy(&iface, &OrgKdeKwinVirtualKeyboardInterface::enabledChanged);
QVERIFY(helperChangedSpy.isValid());
QCOMPARE(dbus.isEnabled(), false);
@ -69,17 +44,8 @@ void VirtualKeyboardDBusTest::testEnabled()
QSignalSpy enabledChangedSpy(&dbus, &VirtualKeyboardDBus::enabledChanged);
QVERIFY(enabledChangedSpy.isValid());
auto readProperty = [] (bool enabled) {
const QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kwin.testvirtualkeyboard"),
QStringLiteral("/VirtualKeyboard"),
QStringLiteral("org.kde.kwin.VirtualKeyboard"),
QStringLiteral("isEnabled"));
const auto reply = QDBusConnection::sessionBus().call(message);
QCOMPARE(reply.type(), QDBusMessage::ReplyMessage);
QCOMPARE(reply.arguments().count(), 1);
QCOMPARE(reply.arguments().first().toBool(), enabled);
};
readProperty(false);
QVERIFY(iface.isValid());
QCOMPARE(iface.enabled(), false);
dbus.setEnabled(true);
QCOMPARE(enabledChangedSpy.count(), 1);
@ -87,7 +53,7 @@ void VirtualKeyboardDBusTest::testEnabled()
QCOMPARE(helperChangedSpy.count(), 1);
QCOMPARE(dbus.isEnabled(), true);
QCOMPARE(dbus.property("enabled").toBool(), true);
readProperty(true);
QCOMPARE(iface.enabled(), true);
// setting again to enabled should not change anything
dbus.setEnabled(true);
@ -100,7 +66,7 @@ void VirtualKeyboardDBusTest::testEnabled()
QCOMPARE(helperChangedSpy.count(), 2);
QCOMPARE(dbus.isEnabled(), false);
QCOMPARE(dbus.property("enabled").toBool(), false);
readProperty(false);
QCOMPARE(iface.enabled(), false);
}
void VirtualKeyboardDBusTest::testRequestEnabled_data()
@ -108,23 +74,28 @@ void VirtualKeyboardDBusTest::testRequestEnabled_data()
QTest::addColumn<QString>("method");
QTest::addColumn<bool>("expectedResult");
QTest::newRow("enable") << QStringLiteral("enable") << true;
QTest::newRow("disable") << QStringLiteral("disable") << false;
QTest::newRow("enable") << QStringLiteral("requestEnabled") << true;
QTest::newRow("disable") << QStringLiteral("requestEnabled") << false;
}
void VirtualKeyboardDBusTest::testRequestEnabled()
{
VirtualKeyboardDBus dbus;
QSignalSpy activateRequestedSpy(&dbus, &VirtualKeyboardDBus::activateRequested);
QVERIFY(activateRequestedSpy.isValid());
QFETCH(QString, method);
const QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kwin.testvirtualkeyboard"),
QStringLiteral("/VirtualKeyboard"),
QStringLiteral("org.kde.kwin.VirtualKeyboard"),
method);
QDBusConnection::sessionBus().asyncCall(message);
QTRY_COMPARE(activateRequestedSpy.count(), 1);
QTEST(activateRequestedSpy.first().first().toBool(), "expectedResult");
QFETCH(bool, expectedResult);
VirtualKeyboardDBus dbus;
dbus.setEnabled(!expectedResult);
connect(&dbus, &VirtualKeyboardDBus::enableRequested, &dbus, &VirtualKeyboardDBus::setEnabled);
QSignalSpy activateRequestedSpy(&dbus, &VirtualKeyboardDBus::enabledChanged);
QVERIFY(activateRequestedSpy.isValid());
OrgKdeKwinVirtualKeyboardInterface iface(QStringLiteral("org.kde.kwin.testvirtualkeyboard"), QStringLiteral("/VirtualKeyboard"), QDBusConnection::sessionBus());
auto pending = iface.requestEnabled(expectedResult);
QVERIFY(!pending.isError());
// activateRequestedSpy.wait();
QCOMPARE(activateRequestedSpy.count(), 1);
QCOMPARE(dbus.isEnabled(), expectedResult);
QCOMPARE(iface.enabled(), expectedResult);
}
QTEST_GUILESS_MAIN(VirtualKeyboardDBusTest)

View file

@ -264,6 +264,8 @@ if (KWIN_BUILD_TABBOX)
target_link_libraries(kwin Qt::GuiPrivate)
endif()
qt5_generate_dbus_interface(virtualkeyboard_dbus.h org.kde.kwin.VirtualKeyboard.xml OPTIONS -P -s -M)
generate_export_header(kwin EXPORT_FILE_NAME kwin_export.h)
if(CMAKE_SYSTEM MATCHES "FreeBSD")
@ -339,6 +341,12 @@ target_link_libraries(kwin_wayland
KF5IdleTimeKWinPlugin
)
add_custom_target(
KWinDBusInterfaces
ALL
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/org.kde.kwin.VirtualKeyboard.xml
)
if (PipeWire_FOUND)
target_link_libraries(kwin_wayland KWinScreencastPlugin)
endif()
@ -352,6 +360,7 @@ install(
org.kde.kwin.Compositing.xml
org.kde.kwin.Effects.xml
org.kde.KWin.Plugins.xml
${CMAKE_CURRENT_BINARY_DIR}/org.kde.kwin.VirtualKeyboard.xml
DESTINATION
${KDE_INSTALL_DBUSINTERFACEDIR}
)

View file

@ -82,7 +82,9 @@ void InputMethod::init()
auto dbus = new VirtualKeyboardDBus(this);
qCDebug(KWIN_VIRTUALKEYBOARD) << "Registering the DBus interface";
dbus->setEnabled(m_enabled);
connect(dbus, &VirtualKeyboardDBus::activateRequested, this, &InputMethod::setEnabled);
connect(dbus, &VirtualKeyboardDBus::enableRequested, this, &InputMethod::setEnabled);
connect(dbus, &VirtualKeyboardDBus::hideRequested, this, &InputMethod::hide);
connect(this, &InputMethod::visibleChanged, dbus, &VirtualKeyboardDBus::setActive);
connect(this, &InputMethod::enabledChanged, dbus, &VirtualKeyboardDBus::setEnabled);
connect(input(), &InputRedirection::keyStateChanged, this, &InputMethod::hide);
@ -114,25 +116,37 @@ void InputMethod::init()
void InputMethod::show()
{
if (m_shown) {
waylandServer()->inputMethod()->sendDeactivate();
}
if (!m_enabled) {
return;
}
waylandServer()->inputMethod()->sendActivate();
if (m_shown) {
adoptInputMethodContext();
}
m_shown = true;
setVisible(true);
}
void InputMethod::hide()
{
waylandServer()->inputMethod()->sendDeactivate();
updateInputPanelState();
m_shown = false;
setVisible(false);
}
void InputMethod::setVisible(bool visible)
{
if (m_visible) {
waylandServer()->inputMethod()->sendDeactivate();
}
if (visible) {
if (!m_enabled) {
return;
}
waylandServer()->inputMethod()->sendActivate();
if (m_visible) {
adoptInputMethodContext();
}
} else {
updateInputPanelState();
}
if (m_visible != visible) {
m_visible = visible;
Q_EMIT visibleChanged(visible);
}
}
void InputMethod::clientAdded(AbstractClient* client)
@ -172,10 +186,10 @@ void InputMethod::handleFocusedSurfaceChanged()
}
m_trackedClient = focusedClient;
}
updateInputPanelState();
} else {
waylandServer()->inputMethod()->sendDeactivate();
setVisible(false);
}
updateInputPanelState();
}
void InputMethod::surroundingTextChanged()
@ -248,7 +262,6 @@ void InputMethod::textInputInterfaceV2EnabledChanged()
waylandServer()->inputMethod()->sendActivate();
adoptInputMethodContext();
} else {
waylandServer()->inputMethod()->sendDeactivate();
hide();
}
}

View file

@ -37,6 +37,7 @@ public:
void show();
Q_SIGNALS:
void visibleChanged(bool shown);
void enabledChanged(bool enabled);
private Q_SLOTS:
@ -56,6 +57,7 @@ private Q_SLOTS:
void setPreeditCursor(qint32 index);
private:
void setVisible(bool shown);
void setEnabled(bool enable);
void updateSni();
void updateInputPanelState();
@ -68,7 +70,7 @@ private:
} preedit;
bool m_enabled = false;
bool m_shown = false;
bool m_visible = false;
KStatusNotifierItem *m_sni = nullptr;
QPointer<AbstractClient> m_inputClient;
QPointer<AbstractClient> m_trackedClient;

View file

@ -16,11 +16,48 @@ VirtualKeyboardDBus::VirtualKeyboardDBus(QObject *parent)
: QObject(parent)
{
QDBusConnection::sessionBus().registerObject(QStringLiteral("/VirtualKeyboard"), this,
QDBusConnection::ExportAllInvokables |
QDBusConnection::ExportScriptableSignals |
QDBusConnection::ExportAllProperties |
QDBusConnection::ExportScriptableSignals | //qdbuscpp2xml doesn't support yet properties with NOTIFY
QDBusConnection::ExportAllSlots);
}
VirtualKeyboardDBus::~VirtualKeyboardDBus() = default;
bool VirtualKeyboardDBus::isActive() const
{
return m_active;
}
void VirtualKeyboardDBus::requestEnabled(bool enabled)
{
emit enableRequested(enabled);
}
void VirtualKeyboardDBus::setActive(bool active)
{
if (m_active != active) {
m_active = active;
Q_EMIT activeChanged();
}
}
void VirtualKeyboardDBus::hide()
{
Q_EMIT hideRequested();
}
bool VirtualKeyboardDBus::isEnabled() const
{
return m_enabled;
}
void VirtualKeyboardDBus::setEnabled(bool enabled)
{
if (m_enabled == enabled) {
return;
}
m_enabled = enabled;
emit enabledChanged();
}
}

View file

@ -18,34 +18,29 @@ class VirtualKeyboardDBus : public QObject
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.kde.kwin.VirtualKeyboard")
Q_PROPERTY(bool enabled READ isEnabled NOTIFY enabledChanged)
Q_PROPERTY(bool active READ isActive NOTIFY activeChanged)
public:
explicit VirtualKeyboardDBus(QObject *parent = nullptr);
~VirtualKeyboardDBus() override;
Q_INVOKABLE bool isEnabled() const {
return m_enabled;
}
void setEnabled(bool enabled) {
if (m_enabled == enabled) {
return;
}
m_enabled = enabled;
emit enabledChanged();
}
bool isEnabled() const;
void setEnabled(bool enabled);
void setActive(bool active);
bool isActive() const;
public Q_SLOTS:
void enable() {
emit activateRequested(true);
}
void disable() {
emit activateRequested(false);
}
void requestEnabled(bool enabled);
void hide();
Q_SIGNALS:
Q_SCRIPTABLE void enabledChanged();
void activateRequested(bool requested);
Q_SCRIPTABLE void activeChanged();
void hideRequested();
void enableRequested(bool requested);
private:
bool m_enabled = false;
bool m_active = false;
};
}