IBus: Support the portal, needed for Flatpak environment

Following commit 35ce6247 in IBus, IBus input plugin now connects to
session bus and use IBus portal to create input context when running
in Flatpak environment or IBUS_USE_PORTAL is set.

[ChangeLog][plugins][ibus] Support IBus portal. Qt programs in Flatpak
environment can now trigger IBus input method.

Change-Id: I561f5f873d709b8abeae554d804daa058f9f6e16
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Reviewed-by: Takao Fujiwara <takao.fujiwara1@gmail.com>
This commit is contained in:
Robin Lee 2018-06-27 11:54:20 +08:00 committed by Takao Fujiwara
parent 7dc930d400
commit 2adc06f940
5 changed files with 140 additions and 11 deletions

View File

@ -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

View File

@ -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>

View File

@ -50,6 +50,7 @@
#include <qpa/qwindowsysteminterface.h>
#include "qibusproxy.h"
#include "qibusproxyportal.h"
#include "qibusinputcontextproxy.h"
#include "qibustypes.h"
@ -78,19 +79,22 @@ 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;
bool usePortal; // return value of shouldConnectIbusPortal
bool valid;
bool busConnected;
QString predit;
@ -507,6 +511,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;
}
@ -572,15 +579,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 +629,35 @@ 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;
}
QDBusReply<QDBusObjectPath> ic = bus->CreateInputContext(QLatin1String("QIBusInputContext"));
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"));
}
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 +705,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))

View File

@ -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()
{
}

View File

@ -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