diff options
Diffstat (limited to 'src/plugins/platforminputcontexts')
6 files changed, 179 insertions, 21 deletions
diff --git a/src/plugins/platforminputcontexts/ibus/ibus.pro b/src/plugins/platforminputcontexts/ibus/ibus.pro index 9f6c848e6a..52836bb8b6 100644 --- a/src/plugins/platforminputcontexts/ibus/ibus.pro +++ b/src/plugins/platforminputcontexts/ibus/ibus.pro @@ -3,12 +3,14 @@ TARGET = ibusplatforminputcontextplugin QT += dbus gui-private SOURCES += $$PWD/qibusplatforminputcontext.cpp \ $$PWD/qibusproxy.cpp \ + $$PWD/qibusproxyportal.cpp \ $$PWD/qibusinputcontextproxy.cpp \ $$PWD/qibustypes.cpp \ $$PWD/main.cpp HEADERS += $$PWD/qibusplatforminputcontext.h \ $$PWD/qibusproxy.h \ + $$PWD/qibusproxyportal.h \ $$PWD/qibusinputcontextproxy.h \ $$PWD/qibustypes.h diff --git a/src/plugins/platforminputcontexts/ibus/interfaces/org.freedesktop.IBus.Portal.xml b/src/plugins/platforminputcontexts/ibus/interfaces/org.freedesktop.IBus.Portal.xml new file mode 100644 index 0000000000..1a5414d0ae --- /dev/null +++ b/src/plugins/platforminputcontexts/ibus/interfaces/org.freedesktop.IBus.Portal.xml @@ -0,0 +1,10 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" +"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node> + <interface name="org.freedesktop.IBus.Portal"> + <method name="CreateInputContext"> + <arg name="name" direction="in" type="s"/> + <arg name="context" direction="out" type="o"/> + </method> + </interface> +</node> diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp index f339938f86..0e587965ca 100644 --- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp +++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp @@ -50,6 +50,7 @@ #include <qpa/qwindowsysteminterface.h> #include "qibusproxy.h" +#include "qibusproxyportal.h" #include "qibusinputcontextproxy.h" #include "qibustypes.h" @@ -78,19 +79,23 @@ public: { delete context; delete bus; + delete portalBus; delete connection; } static QString getSocketPath(); - static QDBusConnection *createConnection(); + QDBusConnection *createConnection(); void initBus(); void createBusProxy(); QDBusConnection *connection; QIBusProxy *bus; + QIBusProxyPortal *portalBus; // bus and portalBus are alternative. QIBusInputContextProxy *context; + QDBusServiceWatcher serviceWatcher; + bool usePortal; // return value of shouldConnectIbusPortal bool valid; bool busConnected; QString predit; @@ -103,20 +108,25 @@ public: QIBusPlatformInputContext::QIBusPlatformInputContext () : d(new QIBusPlatformInputContextPrivate()) { - QString socketPath = QIBusPlatformInputContextPrivate::getSocketPath(); - QFile file(socketPath); - if (file.open(QFile::ReadOnly)) { + if (!d->usePortal) { + QString socketPath = QIBusPlatformInputContextPrivate::getSocketPath(); + QFile file(socketPath); + if (file.open(QFile::ReadOnly)) { #ifndef QT_NO_FILESYSTEMWATCHER - // If KDE session save is used or restart ibus-daemon, - // the applications could run before ibus-daemon runs. - // We watch the getSocketPath() to get the launching ibus-daemon. - m_socketWatcher.addPath(socketPath); - connect(&m_socketWatcher, SIGNAL(fileChanged(QString)), this, SLOT(socketChanged(QString))); + qCDebug(qtQpaInputMethods) << "socketWatcher.addPath" << socketPath; + // If KDE session save is used or restart ibus-daemon, + // the applications could run before ibus-daemon runs. + // We watch the getSocketPath() to get the launching ibus-daemon. + m_socketWatcher.addPath(socketPath); + connect(&m_socketWatcher, SIGNAL(fileChanged(QString)), this, SLOT(socketChanged(QString))); #endif + } + m_timer.setSingleShot(true); + connect(&m_timer, SIGNAL(timeout()), this, SLOT(connectToBus())); } - m_timer.setSingleShot(true); - connect(&m_timer, SIGNAL(timeout()), this, SLOT(connectToBus())); + QObject::connect(&d->serviceWatcher, SIGNAL(serviceRegistered(QString)), this, SLOT(busRegistered(QString))); + QObject::connect(&d->serviceWatcher, SIGNAL(serviceUnregistered(QString)), this, SLOT(busUnregistered(QString))); connectToContextSignals(); @@ -507,6 +517,9 @@ void QIBusPlatformInputContext::filterEventFinished(QDBusPendingCallWatcher *cal QLocale QIBusPlatformInputContext::locale() const { + // d->locale is not updated when IBus portal is used + if (d->usePortal) + return QPlatformInputContext::locale(); return d->locale; } @@ -527,6 +540,22 @@ void QIBusPlatformInputContext::socketChanged(const QString &str) m_timer.start(100); } +void QIBusPlatformInputContext::busRegistered(const QString &str) +{ + qCDebug(qtQpaInputMethods) << "busRegistered"; + Q_UNUSED (str); + if (d->usePortal) { + connectToBus(); + } +} + +void QIBusPlatformInputContext::busUnregistered(const QString &str) +{ + qCDebug(qtQpaInputMethods) << "busUnregistered"; + Q_UNUSED (str); + d->busConnected = false; +} + // When getSocketPath() is modified, the bus is not established yet // so use m_timer. void QIBusPlatformInputContext::connectToBus() @@ -536,7 +565,7 @@ void QIBusPlatformInputContext::connectToBus() connectToContextSignals(); #ifndef QT_NO_FILESYSTEMWATCHER - if (m_socketWatcher.files().size() == 0) + if (!d->usePortal && m_socketWatcher.files().size() == 0) m_socketWatcher.addPath(QIBusPlatformInputContextPrivate::getSocketPath()); #endif } @@ -572,15 +601,34 @@ void QIBusPlatformInputContext::connectToContextSignals() } } +static inline bool checkRunningUnderFlatpak() +{ + return !QStandardPaths::locate(QStandardPaths::RuntimeLocation, QLatin1String("flatpak-info")).isEmpty(); +} + +static bool shouldConnectIbusPortal() +{ + // honor the same env as ibus-gtk + return (checkRunningUnderFlatpak() || !qgetenv("IBUS_USE_PORTAL").isNull()); +} + QIBusPlatformInputContextPrivate::QIBusPlatformInputContextPrivate() : connection(0), bus(0), + portalBus(0), context(0), + usePortal(shouldConnectIbusPortal()), valid(false), busConnected(false), needsSurroundingText(false) { - valid = !QStandardPaths::findExecutable(QString::fromLocal8Bit("ibus-daemon"), QStringList()).isEmpty(); + if (usePortal) { + valid = true; + if (debug) + qDebug() << "use IBus portal"; + } else { + valid = !QStandardPaths::findExecutable(QString::fromLocal8Bit("ibus-daemon"), QStringList()).isEmpty(); + } if (!valid) return; initBus(); @@ -603,21 +651,40 @@ void QIBusPlatformInputContextPrivate::createBusProxy() if (!connection || !connection->isConnected()) return; - bus = new QIBusProxy(QLatin1String("org.freedesktop.IBus"), - QLatin1String("/org/freedesktop/IBus"), - *connection); - if (!bus->isValid()) { - qWarning("QIBusPlatformInputContext: invalid bus."); - return; + const char* ibusService = usePortal ? "org.freedesktop.portal.IBus" : "org.freedesktop.IBus"; + QDBusReply<QDBusObjectPath> ic; + if (usePortal) { + portalBus = new QIBusProxyPortal(QLatin1String(ibusService), + QLatin1String("/org/freedesktop/IBus"), + *connection); + if (!portalBus->isValid()) { + qWarning("QIBusPlatformInputContext: invalid portal bus."); + return; + } + + ic = portalBus->CreateInputContext(QLatin1String("QIBusInputContext")); + } else { + bus = new QIBusProxy(QLatin1String(ibusService), + QLatin1String("/org/freedesktop/IBus"), + *connection); + if (!bus->isValid()) { + qWarning("QIBusPlatformInputContext: invalid bus."); + return; + } + + ic = bus->CreateInputContext(QLatin1String("QIBusInputContext")); } - QDBusReply<QDBusObjectPath> ic = bus->CreateInputContext(QLatin1String("QIBusInputContext")); + serviceWatcher.removeWatchedService(ibusService); + serviceWatcher.setConnection(*connection); + serviceWatcher.addWatchedService(ibusService); + if (!ic.isValid()) { qWarning("QIBusPlatformInputContext: CreateInputContext failed."); return; } - context = new QIBusInputContextProxy(QLatin1String("org.freedesktop.IBus"), ic.value().path(), *connection); + context = new QIBusInputContextProxy(QLatin1String(ibusService), ic.value().path(), *connection); if (!context->isValid()) { qWarning("QIBusPlatformInputContext: invalid input context."); @@ -665,6 +732,8 @@ QString QIBusPlatformInputContextPrivate::getSocketPath() QDBusConnection *QIBusPlatformInputContextPrivate::createConnection() { + if (usePortal) + return new QDBusConnection(QDBusConnection::connectToBus(QDBusConnection::SessionBus, QLatin1String("QIBusProxy"))); QFile file(getSocketPath()); if (!file.open(QFile::ReadOnly)) diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h index 9b92b2e1f9..f37552b937 100644 --- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h +++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h @@ -108,6 +108,8 @@ public Q_SLOTS: void showPreeditText(); void filterEventFinished(QDBusPendingCallWatcher *call); void socketChanged(const QString &str); + void busRegistered(const QString &str); + void busUnregistered(const QString &str); void connectToBus(); void globalEngineChanged(const QString &engine_name); diff --git a/src/plugins/platforminputcontexts/ibus/qibusproxyportal.cpp b/src/plugins/platforminputcontexts/ibus/qibusproxyportal.cpp new file mode 100644 index 0000000000..50482e2d9a --- /dev/null +++ b/src/plugins/platforminputcontexts/ibus/qibusproxyportal.cpp @@ -0,0 +1,26 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -N -p qibusproxyportal -c QIBusProxyPortal interfaces/org.freedesktop.IBus.Portal.xml + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "qibusproxyportal.h" + +/* + * Implementation of interface class QIBusProxyPortal + */ + +QIBusProxyPortal::QIBusProxyPortal(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +QIBusProxyPortal::~QIBusProxyPortal() +{ +} + diff --git a/src/plugins/platforminputcontexts/ibus/qibusproxyportal.h b/src/plugins/platforminputcontexts/ibus/qibusproxyportal.h new file mode 100644 index 0000000000..bdd1d9c395 --- /dev/null +++ b/src/plugins/platforminputcontexts/ibus/qibusproxyportal.h @@ -0,0 +1,49 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -N -p qibusproxyportal -c QIBusProxyPortal interfaces/org.freedesktop.IBus.Portal.xml + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef QIBUSPROXYPORTAL_H +#define QIBUSPROXYPORTAL_H + +#include <QtCore/QObject> +#include <QtCore/QByteArray> +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QVariant> +#include <QtDBus/QtDBus> + +/* + * Proxy class for interface org.freedesktop.IBus.Portal + */ +class QIBusProxyPortal: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.freedesktop.IBus.Portal"; } + +public: + QIBusProxyPortal(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); + + ~QIBusProxyPortal(); + +public Q_SLOTS: // METHODS + inline QDBusPendingReply<QDBusObjectPath> CreateInputContext(const QString &name) + { + QList<QVariant> argumentList; + argumentList << QVariant::fromValue(name); + return asyncCallWithArgumentList(QStringLiteral("CreateInputContext"), argumentList); + } + +Q_SIGNALS: // SIGNALS +}; + +#endif |