From 4954ad6dbc9c37ac4f8b9cae8808c31f1d55c698 Mon Sep 17 00:00:00 2001 From: Takao Fujiwara Date: Wed, 16 Sep 2015 19:33:25 +0900 Subject: [PATCH] Qt IBus plugin connects to IBus Bus again if ibus-daemon does not run Qt5 applications do not enable IBus when the applications are saved in the session and launched automatically in the next login. This patch checks the IBus socket path and connect to the bus when it's available. Task-number QTBUG-47657 Change-Id: I0883eaa2438fd27455da93f78f392ea3c1abe6b8 Reviewed-by: Lars Knoll --- .../ibus/qibusplatforminputcontext.cpp | 106 +++++++++++++++--- .../ibus/qibusplatforminputcontext.h | 8 ++ 2 files changed, 97 insertions(+), 17 deletions(-) diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp index 27fca7c6ed..dca21245aa 100644 --- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp +++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp @@ -73,13 +73,18 @@ public: delete connection; } + static QString getSocketPath(); static QDBusConnection *createConnection(); + void initBus(); + void createBusProxy(); + QDBusConnection *connection; QIBusProxy *bus; QIBusInputContextProxy *context; bool valid; + bool busConnected; QString predit; bool needsSurroundingText; }; @@ -88,12 +93,21 @@ public: QIBusPlatformInputContext::QIBusPlatformInputContext () : d(new QIBusPlatformInputContextPrivate()) { - if (d->context) { - connect(d->context, SIGNAL(CommitText(QDBusVariant)), SLOT(commitText(QDBusVariant))); - connect(d->context, SIGNAL(UpdatePreeditText(QDBusVariant,uint,bool)), this, SLOT(updatePreeditText(QDBusVariant,uint,bool))); - connect(d->context, SIGNAL(DeleteSurroundingText(int,uint)), this, SLOT(deleteSurroundingText(int,uint))); - connect(d->context, SIGNAL(RequireSurroundingText()), this, SLOT(surroundingTextRequired())); + QString socketPath = QIBusPlatformInputContextPrivate::getSocketPath(); + QFile file(socketPath); + if (file.open(QFile::ReadOnly)) { + // 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))); } + + m_timer.setSingleShot(true); + connect(&m_timer, SIGNAL(timeout()), this, SLOT(connectToBus())); + + connectToContextSignals(); + QInputMethod *p = qApp->inputMethod(); connect(p, SIGNAL(cursorRectangleChanged()), this, SLOT(cursorRectChanged())); m_eventFilterUseSynchronousMode = false; @@ -117,7 +131,7 @@ bool QIBusPlatformInputContext::isValid() const void QIBusPlatformInputContext::invokeAction(QInputMethod::Action a, int) { - if (!d->valid) + if (!d->busConnected) return; if (a == QInputMethod::Click) @@ -128,7 +142,7 @@ void QIBusPlatformInputContext::reset() { QPlatformInputContext::reset(); - if (!d->valid) + if (!d->busConnected) return; d->context->Reset(); @@ -139,7 +153,7 @@ void QIBusPlatformInputContext::commit() { QPlatformInputContext::commit(); - if (!d->valid) + if (!d->busConnected) return; QObject *input = qApp->focusObject(); @@ -193,7 +207,7 @@ void QIBusPlatformInputContext::update(Qt::InputMethodQueries q) void QIBusPlatformInputContext::cursorRectChanged() { - if (!d->valid) + if (!d->busConnected) return; QRect r = qApp->inputMethod()->cursorRectangle().toRect(); @@ -211,7 +225,7 @@ void QIBusPlatformInputContext::cursorRectChanged() void QIBusPlatformInputContext::setFocusObject(QObject *object) { - if (!d->valid) + if (!d->busConnected) return; if (debug) @@ -291,7 +305,7 @@ void QIBusPlatformInputContext::deleteSurroundingText(int offset, uint n_chars) bool QIBusPlatformInputContext::filterEvent(const QEvent *event) { - if (!d->valid) + if (!d->busConnected) return false; if (!inputMethodAccepted()) @@ -398,12 +412,65 @@ void QIBusPlatformInputContext::filterEventFinished(QDBusPendingCallWatcher *cal call->deleteLater(); } +void QIBusPlatformInputContext::socketChanged(const QString &str) +{ + qCDebug(qtQpaInputMethods) << "socketChanged"; + Q_UNUSED (str); + + m_timer.stop(); + + if (d->context) + disconnect(d->context); + if (d->connection) + d->connection->disconnectFromBus(QLatin1String("QIBusProxy")); + + m_timer.start(100); +} + +// When getSocketPath() is modified, the bus is not established yet +// so use m_timer. +void QIBusPlatformInputContext::connectToBus() +{ + qCDebug(qtQpaInputMethods) << "QIBusPlatformInputContext::connectToBus"; + d->initBus(); + connectToContextSignals(); + + if (m_socketWatcher.files().size() == 0) + m_socketWatcher.addPath(QIBusPlatformInputContextPrivate::getSocketPath()); +} + +void QIBusPlatformInputContext::connectToContextSignals() +{ + if (d->context) { + connect(d->context, SIGNAL(CommitText(QDBusVariant)), SLOT(commitText(QDBusVariant))); + connect(d->context, SIGNAL(UpdatePreeditText(QDBusVariant,uint,bool)), this, SLOT(updatePreeditText(QDBusVariant,uint,bool))); + connect(d->context, SIGNAL(DeleteSurroundingText(int,uint)), this, SLOT(deleteSurroundingText(int,uint))); + connect(d->context, SIGNAL(RequireSurroundingText()), this, SLOT(surroundingTextRequired())); + } +} + QIBusPlatformInputContextPrivate::QIBusPlatformInputContextPrivate() - : connection(createConnection()), + : connection(0), bus(0), context(0), valid(false), + busConnected(false), needsSurroundingText(false) +{ + valid = !QStandardPaths::findExecutable(QString::fromLocal8Bit("ibus-daemon"), QStringList()).isEmpty(); + if (!valid) + return; + initBus(); +} + +void QIBusPlatformInputContextPrivate::initBus() +{ + connection = createConnection(); + busConnected = false; + createBusProxy(); +} + +void QIBusPlatformInputContextPrivate::createBusProxy() { if (!connection || !connection->isConnected()) return; @@ -440,11 +507,11 @@ QIBusPlatformInputContextPrivate::QIBusPlatformInputContextPrivate() context->SetCapabilities(IBUS_CAP_PREEDIT_TEXT|IBUS_CAP_FOCUS|IBUS_CAP_SURROUNDING_TEXT); if (debug) - qDebug(">>>> valid!"); - valid = true; + qDebug(">>>> bus connected!"); + busConnected = true; } -QDBusConnection *QIBusPlatformInputContextPrivate::createConnection() +QString QIBusPlatformInputContextPrivate::getSocketPath() { QByteArray display(qgetenv("DISPLAY")); QByteArray host = "unix"; @@ -462,9 +529,14 @@ QDBusConnection *QIBusPlatformInputContextPrivate::createConnection() if (debug) qDebug() << "host=" << host << "displayNumber" << displayNumber; - QFile file(QDir::homePath() + QLatin1String("/.config/ibus/bus/") + + return QDir::homePath() + QLatin1String("/.config/ibus/bus/") + QLatin1String(QDBusConnection::localMachineId()) + - QLatin1Char('-') + QString::fromLocal8Bit(host) + QLatin1Char('-') + QString::fromLocal8Bit(displayNumber)); + QLatin1Char('-') + QString::fromLocal8Bit(host) + QLatin1Char('-') + QString::fromLocal8Bit(displayNumber); +} + +QDBusConnection *QIBusPlatformInputContextPrivate::createConnection() +{ + QFile file(getSocketPath()); if (!file.open(QFile::ReadOnly)) return 0; diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h index 127db7df8b..a8efd9deb3 100644 --- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h +++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h @@ -37,7 +37,9 @@ #include #include +#include #include +#include #include QT_BEGIN_NAMESPACE @@ -96,10 +98,16 @@ public Q_SLOTS: void deleteSurroundingText(int offset, uint n_chars); void surroundingTextRequired(); void filterEventFinished(QDBusPendingCallWatcher *call); + void socketChanged(const QString &str); + void connectToBus(); private: QIBusPlatformInputContextPrivate *d; bool m_eventFilterUseSynchronousMode; + QFileSystemWatcher m_socketWatcher; + QTimer m_timer; + + void connectToContextSignals(); }; QT_END_NAMESPACE