use new fcitxwatcher based implementation for proxy.

This commit is contained in:
Weng Xuetian 2017-10-16 18:43:30 -07:00
parent 16972ee69c
commit a44e118ff3
33 changed files with 1663 additions and 1271 deletions

View File

@ -22,15 +22,16 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/fcitx5qt4dbusaddons_version.h
DESTINATION ${Fcitx5Qt4_INCLUDE_INSTALL_DIR} COMPONENT Devel )
set(dbusaddons_SOURCES
fcitxqtconnection.cpp
fcitxqtwatcher.cpp
fcitxqtdbustypes.cpp
fcitxqtinputcontextproxy.cpp
fcitxqtinputcontextproxyimpl.cpp
fcitxqtinputmethodproxy.cpp
fcitxqtcontrollerproxy.cpp
)
set(dbusaddons_HEADERS
fcitxqtconnection.h
fcitxqtwatcher.h
fcitxqtdbustypes.h
fcitxqtinputcontextproxy.h
fcitxqtinputmethodproxy.h

View File

@ -1,188 +0,0 @@
/*
* Copyright (C) 2012~2017 by CSSlayer
* wengxt@gmail.com
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; see the file COPYING. If not,
* see <http://www.gnu.org/licenses/>.
*/
#include "fcitxqtconnection_p.h"
#include <QDBusConnection>
#include <QDBusConnectionInterface>
#include <QDBusReply>
#include <QDBusServiceWatcher>
#include <QDebug>
#include <QDir>
#include <QFile>
#include <QTimer>
#include <errno.h>
#include <signal.h>
namespace fcitx {
FcitxQtConnection::FcitxQtConnection(QObject *parent)
: QObject(parent), d_ptr(new FcitxQtConnectionPrivate(this)) {}
void FcitxQtConnection::startConnection() {
Q_D(FcitxQtConnection);
if (!d->m_initialized) {
d->initialize();
d->createConnection();
}
}
void FcitxQtConnection::endConnection() {
Q_D(FcitxQtConnection);
d->cleanUp();
d->finalize();
d->m_connectedOnce = false;
}
bool FcitxQtConnection::autoReconnect() {
Q_D(FcitxQtConnection);
return d->m_autoReconnect;
}
void FcitxQtConnection::setAutoReconnect(bool a) {
Q_D(FcitxQtConnection);
d->m_autoReconnect = a;
}
QDBusConnection *FcitxQtConnection::connection() {
Q_D(FcitxQtConnection);
return d->m_connection;
}
const QString &FcitxQtConnection::serviceName() {
Q_D(FcitxQtConnection);
return d->m_serviceName;
}
bool FcitxQtConnection::isConnected() {
Q_D(FcitxQtConnection);
return d->isConnected();
}
FcitxQtConnection::~FcitxQtConnection() {}
FcitxQtConnectionPrivate::FcitxQtConnectionPrivate(FcitxQtConnection *conn)
: QObject(conn), q_ptr(conn), m_serviceName("org.fcitx.Fcitx5"),
m_connection(nullptr), m_serviceWatcher(new QDBusServiceWatcher(this)),
m_autoReconnect(true), m_connectedOnce(false), m_initialized(false) {}
FcitxQtConnectionPrivate::~FcitxQtConnectionPrivate() {
if (m_connection)
delete m_connection;
}
void FcitxQtConnectionPrivate::initialize() {
m_serviceWatcher->setConnection(QDBusConnection::sessionBus());
m_serviceWatcher->addWatchedService(m_serviceName);
m_initialized = true;
}
void FcitxQtConnectionPrivate::finalize() {
m_serviceWatcher->removeWatchedService(m_serviceName);
m_initialized = false;
}
void FcitxQtConnectionPrivate::createConnection() {
if (m_connectedOnce && !m_autoReconnect) {
return;
}
disconnect(m_serviceWatcher,
SIGNAL(serviceOwnerChanged(QString, QString, QString)), this,
SLOT(imChanged(QString, QString, QString)));
if (!m_connection) {
QDBusConnection *connection =
new QDBusConnection(QDBusConnection::sessionBus());
connect(m_serviceWatcher,
SIGNAL(serviceOwnerChanged(QString, QString, QString)), this,
SLOT(imChanged(QString, QString, QString)));
QDBusReply<bool> registered =
connection->interface()->isServiceRegistered(m_serviceName);
if (!registered.isValid() || !registered.value()) {
delete connection;
} else {
m_connection = connection;
}
}
Q_Q(FcitxQtConnection);
if (m_connection) {
m_connection->connect("org.freedesktop.DBus.Local",
"/org/freedesktop/DBus/Local",
"org.freedesktop.DBus.Local", "Disconnected",
this, SLOT(dbusDisconnected()));
m_connectedOnce = true;
emit q->connected();
}
}
void FcitxQtConnectionPrivate::dbusDisconnected() {
cleanUp();
createConnection();
}
void FcitxQtConnectionPrivate::imChanged(const QString &service,
const QString &oldowner,
const QString &newowner) {
if (service == m_serviceName) {
/* old die */
if (oldowner.length() > 0 || newowner.length() > 0)
cleanUp();
/* new rise */
if (newowner.length() > 0) {
QTimer::singleShot(100, this, SLOT(newServiceAppear()));
}
}
}
void FcitxQtConnectionPrivate::cleanUp() {
Q_Q(FcitxQtConnection);
bool doemit = false;
if (m_connection) {
delete m_connection;
m_connection = nullptr;
doemit = true;
}
if (!m_autoReconnect && m_connectedOnce)
finalize();
/* we want m_connection and finalize being called before the signal
* thus isConnected will return false in slot
* and startConnection can be called in slot
*/
if (doemit)
emit q->disconnected();
}
bool FcitxQtConnectionPrivate::isConnected() {
return m_connection && m_connection->isConnected();
}
void FcitxQtConnectionPrivate::newServiceAppear() {
if (!isConnected()) {
cleanUp();
createConnection();
}
}
}

View File

@ -1,112 +0,0 @@
/*
* Copyright (C) 2012~2017 by CSSlayer
* wengxt@gmail.com
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; see the file COPYING. If not,
* see <http://www.gnu.org/licenses/>.
*/
#ifndef _DBUSADDONS_FCITXQTCONNECTION_H_
#define _DBUSADDONS_FCITXQTCONNECTION_H_
#include "fcitx5qt4dbusaddons_export.h"
#include <QObject>
class QDBusConnection;
namespace fcitx {
class FcitxQtConnectionPrivate;
/**
* dbus connection to fcitx
**/
class FCITX5QT4DBUSADDONS_EXPORT FcitxQtConnection : public QObject {
Q_OBJECT
Q_PROPERTY(bool autoReconnect READ autoReconnect WRITE setAutoReconnect)
Q_PROPERTY(bool connected READ isConnected)
Q_PROPERTY(QDBusConnection *connection READ connection)
Q_PROPERTY(QString serviceName READ serviceName)
public:
/**
* create a new connection
*
* @param parent
**/
explicit FcitxQtConnection(QObject *parent = 0);
/**
* destroy the connection
**/
virtual ~FcitxQtConnection();
/**
* the connection will not start to work until you call this function
* you may want to connect to the signal before you call this function
**/
void startConnection();
void endConnection();
/**
* automatically reconnect if fcitx disappeared
*
* @param a ...
* @return void
**/
void setAutoReconnect(bool a);
/**
* check this connection is doing automatical reconnect or not
*
* default value is true
**/
bool autoReconnect();
/**
* return the current dbus connection to fcitx, notice, the object return
* by this function might be deteled if fcitx disappear, or might return 0
* if fcitx is not running
*
* @return QDBusConnection*
**/
QDBusConnection *connection();
/**
* current fcitx dbus service name, can be used for create DBus proxy
*
* @return service name
**/
const QString &serviceName();
/**
* check its connected or not
**/
bool isConnected();
Q_SIGNALS:
/**
* this signal will be emitted upon fcitx appears
**/
void connected();
/**
* this signal will be emitted upon fcitx disappears
*
* it will come with connected in pair
**/
void disconnected();
private:
FcitxQtConnectionPrivate *const d_ptr;
Q_DECLARE_PRIVATE(FcitxQtConnection);
};
}
#endif // _DBUSADDONS_FCITXQTCONNECTION_H_

View File

@ -1,60 +0,0 @@
/*
* Copyright (C) 2017~2017 by CSSlayer
* wengxt@gmail.com
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; see the file COPYING. If not,
* see <http://www.gnu.org/licenses/>.
*/
#ifndef _DBUSADDONS_FCITXQTCONNECTION_P_H_
#define _DBUSADDONS_FCITXQTCONNECTION_P_H_
#include "fcitxqtconnection.h"
class QDBusConnection;
class QDBusServiceWatcher;
namespace fcitx {
class FcitxQtConnectionPrivate : public QObject {
Q_OBJECT
public:
FcitxQtConnectionPrivate(FcitxQtConnection *conn);
virtual ~FcitxQtConnectionPrivate();
FcitxQtConnection *const q_ptr;
Q_DECLARE_PUBLIC(FcitxQtConnection);
private Q_SLOTS:
void imChanged(const QString &service, const QString &oldowner,
const QString &newowner);
void dbusDisconnected();
void cleanUp();
void newServiceAppear();
private:
bool isConnected();
void createConnection();
void initialize();
void finalize();
QString m_serviceName;
QDBusConnection *m_connection;
QDBusServiceWatcher *m_serviceWatcher;
QString m_socketFile;
bool m_autoReconnect;
bool m_connectedOnce;
bool m_initialized;
};
}
#endif // _DBUSADDONS_FCITXQTCONNECTION_P_H_

View File

@ -1,29 +1,112 @@
/*
* This file was generated by qdbusxml2cpp version 0.7
* Command line was: qdbusxml2cpp -N -p fcitxqtinputcontextproxy -c FcitxQtInputContextProxy interfaces/org.fcitx.Fcitx.InputContext1.xml -i fcitxqtdbustypes.h -i fcitx5qt4dbusaddons_export.h
*
* qdbusxml2cpp is Copyright (C) 2015 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.
*/
* Copyright (C) 2017~2017 by CSSlayer
* wengxt@gmail.com
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; see the file COPYING. If not,
* see <http://www.gnu.org/licenses/>.
*/
#include "fcitxqtinputcontextproxy.h"
#include "fcitxqtinputcontextproxy_p.h"
#include <QDBusInterface>
#include <QDBusMetaType>
#include <QDBusConnectionInterface>
#include <QFileInfo>
#include <QCoreApplication>
#include <QTimer>
namespace fcitx {
/*
* Implementation of interface class FcitxQtInputContextProxy
*/
FcitxQtInputContextProxy::FcitxQtInputContextProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
FcitxQtInputContextProxy::FcitxQtInputContextProxy(FcitxQtWatcher *watcher, QObject *parent) : QObject(parent),
d_ptr(new FcitxQtInputContextProxyPrivate(watcher, this))
{
}
FcitxQtInputContextProxy::~FcitxQtInputContextProxy()
{
Q_D(FcitxQtInputContextProxy);
if (isValid()) {
d->m_icproxy->DestroyIC();
}
delete d_ptr;
}
void FcitxQtInputContextProxy::setDisplay(const QString& display)
{
Q_D(FcitxQtInputContextProxy);
d->m_display = display;
}
const QString &FcitxQtInputContextProxy::display() const
{
Q_D(const FcitxQtInputContextProxy);
return d->m_display;
}
bool FcitxQtInputContextProxy::isValid() const
{
Q_D(const FcitxQtInputContextProxy);
return d->isValid();
}
QDBusPendingReply<> FcitxQtInputContextProxy::focusIn()
{
Q_D(FcitxQtInputContextProxy);
return d->m_icproxy->FocusIn();
}
QDBusPendingReply<> FcitxQtInputContextProxy::focusOut()
{
Q_D(FcitxQtInputContextProxy);
return d->m_icproxy->FocusOut();
}
QDBusPendingReply<bool> FcitxQtInputContextProxy::processKeyEvent(uint keyval, uint keycode, uint state, bool type, uint time)
{
Q_D(FcitxQtInputContextProxy);
return d->m_icproxy->ProcessKeyEvent(keyval, keycode, state, type, time);
}
QDBusPendingReply<> FcitxQtInputContextProxy::reset()
{
Q_D(FcitxQtInputContextProxy);
return d->m_icproxy->Reset();
}
QDBusPendingReply<> FcitxQtInputContextProxy::setCapability(qulonglong caps)
{
Q_D(FcitxQtInputContextProxy);
return d->m_icproxy->SetCapability(caps);
}
QDBusPendingReply<> FcitxQtInputContextProxy::setCursorRect(int x, int y, int w, int h)
{
Q_D(FcitxQtInputContextProxy);
return d->m_icproxy->SetCursorRect(x, y, w, h);
}
QDBusPendingReply<> FcitxQtInputContextProxy::setSurroundingText(const QString &text, uint cursor, uint anchor)
{
Q_D(FcitxQtInputContextProxy);
return d->m_icproxy->SetSurroundingText(text, cursor, anchor);
}
QDBusPendingReply<> FcitxQtInputContextProxy::setSurroundingTextPosition(uint cursor, uint anchor)
{
Q_D(FcitxQtInputContextProxy);
return d->m_icproxy->SetSurroundingTextPosition(cursor, anchor);
}
}
#include "moc_fcitxqtinputcontextproxy.cpp"

View File

@ -1,112 +1,77 @@
/*
* This file was generated by qdbusxml2cpp version 0.7
* Command line was: qdbusxml2cpp -N -p fcitxqtinputcontextproxy -c FcitxQtInputContextProxy interfaces/org.fcitx.Fcitx.InputContext1.xml -i fcitxqtdbustypes.h -i fcitx5qt4dbusaddons_export.h
*
* qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
* Copyright (C) 2017~2017 by CSSlayer
* wengxt@gmail.com
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; see the file COPYING. If not,
* see <http://www.gnu.org/licenses/>.
*/
#ifndef _DBUSADDONS_FCITXQTINPUTCONTEXTPROXY_H_
#define _DBUSADDONS_FCITXQTINPUTCONTEXTPROXY_H_
#ifndef FCITXQTINPUTCONTEXTPROXY_H_1495144859
#define FCITXQTINPUTCONTEXTPROXY_H_1495144859
#include <QtCore/QObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <QtDBus/QtDBus>
#include "fcitxqtdbustypes.h"
#include "fcitx5qt4dbusaddons_export.h"
#include <QObject>
#include <QDBusServiceWatcher>
#include <QDBusConnection>
#include <QDBusPendingReply>
#include "fcitxqtdbustypes.h"
class QDBusPendingCallWatcher;
namespace fcitx {
/*
* Proxy class for interface org.fcitx.Fcitx.InputContext1
*/
class FCITX5QT4DBUSADDONS_EXPORT FcitxQtInputContextProxy: public QDBusAbstractInterface
{
class FcitxQtWatcher;
class FcitxQtInputContextProxyPrivate;
class FCITX5QT4DBUSADDONS_EXPORT FcitxQtInputContextProxy : public QObject {
Q_OBJECT
public:
static inline const char *staticInterfaceName()
{ return "org.fcitx.Fcitx.InputContext1"; }
public:
FcitxQtInputContextProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
FcitxQtInputContextProxy(FcitxQtWatcher *watcher, QObject *parent);
~FcitxQtInputContextProxy();
public Q_SLOTS: // METHODS
inline QDBusPendingReply<> DestroyIC()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("DestroyIC"), argumentList);
}
bool isValid() const;
void setDisplay(const QString &display);
const QString &display() const;
inline QDBusPendingReply<> FocusIn()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("FocusIn"), argumentList);
}
public slots:
QDBusPendingReply<> focusIn();
QDBusPendingReply<> focusOut();
QDBusPendingReply<bool> processKeyEvent(uint keyval, uint keycode, uint state, bool type, uint time);
QDBusPendingReply<> reset();
QDBusPendingReply<> setCapability(qulonglong caps);
QDBusPendingReply<> setCursorRect(int x, int y, int w, int h);
QDBusPendingReply<> setSurroundingText(const QString &text, uint cursor, uint anchor);
QDBusPendingReply<> setSurroundingTextPosition(uint cursor, uint anchor);
inline QDBusPendingReply<> FocusOut()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("FocusOut"), argumentList);
}
signals:
void commitString(const QString &str);
void currentIM(const QString &name, const QString &uniqueName, const QString &langCode);
void deleteSurroundingText(int offset, uint nchar);
void forwardKey(uint keyval, uint state, bool isRelease);
void updateFormattedPreedit(const FcitxQtFormattedPreeditList &str, int cursorpos);
void inputContextCreated(const QByteArray &uuid);
inline QDBusPendingReply<bool> ProcessKeyEvent(uint keyval, uint keycode, uint state, bool type, uint time)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(keyval) << QVariant::fromValue(keycode) << QVariant::fromValue(state) << QVariant::fromValue(type) << QVariant::fromValue(time);
return asyncCallWithArgumentList(QLatin1String("ProcessKeyEvent"), argumentList);
}
private:
Q_PRIVATE_SLOT(d_func(), void availabilityChanged());
Q_PRIVATE_SLOT(d_func(), void recheck());
Q_PRIVATE_SLOT(d_func(), void cleanUp());
Q_PRIVATE_SLOT(d_func(), void createInputContextFinished());
inline QDBusPendingReply<> Reset()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("Reset"), argumentList);
}
inline QDBusPendingReply<> SetCapability(qulonglong caps)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(caps);
return asyncCallWithArgumentList(QLatin1String("SetCapability"), argumentList);
}
inline QDBusPendingReply<> SetCursorRect(int x, int y, int w, int h)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(x) << QVariant::fromValue(y) << QVariant::fromValue(w) << QVariant::fromValue(h);
return asyncCallWithArgumentList(QLatin1String("SetCursorRect"), argumentList);
}
inline QDBusPendingReply<> SetSurroundingText(const QString &text, uint cursor, uint anchor)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(text) << QVariant::fromValue(cursor) << QVariant::fromValue(anchor);
return asyncCallWithArgumentList(QLatin1String("SetSurroundingText"), argumentList);
}
inline QDBusPendingReply<> SetSurroundingTextPosition(uint cursor, uint anchor)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(cursor) << QVariant::fromValue(anchor);
return asyncCallWithArgumentList(QLatin1String("SetSurroundingTextPosition"), argumentList);
}
Q_SIGNALS: // SIGNALS
void CommitString(const QString &str);
void CurrentIM(const QString &name, const QString &uniqueName, const QString &langCode);
void DeleteSurroundingText(int offset, uint nchar);
void ForwardKey(uint keyval, uint state, bool type);
void UpdateFormattedPreedit(FcitxQtFormattedPreeditList str, int cursorpos);
FcitxQtInputContextProxyPrivate *const d_ptr;
Q_DECLARE_PRIVATE(FcitxQtInputContextProxy);
};
}
#endif
#endif // _DBUSADDONS_FCITXQTINPUTCONTEXTPROXY_H_

View File

@ -0,0 +1,172 @@
/*
* Copyright (C) 2017~2017 by CSSlayer
* wengxt@gmail.com
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; see the file COPYING. If not,
* see <http://www.gnu.org/licenses/>.
*/
#ifndef _DBUSADDONS_FCITXQTINPUTCONTEXTPROXY_P_H_
#define _DBUSADDONS_FCITXQTINPUTCONTEXTPROXY_P_H_
#include "fcitxqtinputcontextproxy.h"
#include "fcitxqtinputcontextproxyimpl.h"
#include "fcitxqtinputmethodproxy.h"
#include "fcitxqtwatcher.h"
#include <QDBusServiceWatcher>
namespace fcitx {
class FcitxQtInputContextProxyPrivate {
public:
FcitxQtInputContextProxyPrivate(FcitxQtWatcher *watcher,
FcitxQtInputContextProxy *q)
: q_ptr(q), m_fcitxWatcher(watcher), m_watcher(q) {
FcitxQtFormattedPreedit::registerMetaType();
FcitxQtInputContextArgument::registerMetaType();
QObject::connect(m_fcitxWatcher, SIGNAL(availibilityChanged(bool)), q,
SLOT(availabilityChanged()));
m_watcher.setWatchMode(QDBusServiceWatcher::WatchForUnregistration);
QObject::connect(&m_watcher, SIGNAL(serviceUnregistered(QString)), q,
SLOT(availabilityChanged()));
availabilityChanged();
}
~FcitxQtInputContextProxyPrivate() {
if (isValid()) {
m_icproxy->DestroyIC();
}
}
bool isValid() const { return (m_icproxy && m_icproxy->isValid()); }
void availabilityChanged() {
QTimer::singleShot(100, q_ptr, SLOT(recheck()));
}
void recheck() {
if (!isValid() && m_fcitxWatcher->availability()) {
createInputContext();
}
if (!m_fcitxWatcher->availability()) {
cleanUp();
}
}
void cleanUp() {
auto services = m_watcher.watchedServices();
for (const auto &service : services) {
m_watcher.removeWatchedService(service);
}
delete m_improxy;
m_improxy = nullptr;
delete m_icproxy;
m_icproxy = nullptr;
delete m_createInputContextWatcher;
m_createInputContextWatcher = nullptr;
}
void createInputContext() {
Q_Q(FcitxQtInputContextProxy);
if (!m_fcitxWatcher->availability()) {
return;
}
cleanUp();
auto service = m_fcitxWatcher->serviceName();
auto connection = m_fcitxWatcher->connection();
auto owner = connection.interface()->serviceOwner(service);
if (!owner.isValid()) {
return;
}
m_watcher.setConnection(connection);
m_watcher.setWatchedServices(QStringList() << owner);
// Avoid race, query again.
if (!connection.interface()->isServiceRegistered(owner)) {
cleanUp();
return;
}
QFileInfo info(QCoreApplication::applicationFilePath());
m_portal = true;
m_improxy =
new FcitxQtInputMethodProxy(owner, "/inputmethod", connection, q);
FcitxQtInputContextArgumentList list;
FcitxQtInputContextArgument arg;
arg.setName("program");
arg.setValue(info.fileName());
list << arg;
if (!m_display.isEmpty()) {
FcitxQtInputContextArgument arg2;
arg2.setName("display");
arg2.setValue(m_display);
list << arg2;
}
auto result = m_improxy->CreateInputContext(list);
m_createInputContextWatcher = new QDBusPendingCallWatcher(result);
QObject::connect(m_createInputContextWatcher,
SIGNAL(finished(QDBusPendingCallWatcher *)), q,
SLOT(createInputContextFinished()));
}
void createInputContextFinished() {
Q_Q(FcitxQtInputContextProxy);
if (m_createInputContextWatcher->isError()) {
cleanUp();
return;
}
QDBusPendingReply<QDBusObjectPath, QByteArray> reply(
*m_createInputContextWatcher);
m_icproxy = new FcitxQtInputContextProxyImpl(
m_improxy->service(), reply.value().path(), m_improxy->connection(),
q);
QObject::connect(m_icproxy, SIGNAL(CommitString(QString)), q,
SIGNAL(commitString(QString)));
QObject::connect(m_icproxy,
SIGNAL(CurrentIM(QString, QString, QString)), q,
SIGNAL(currentIM(QString, QString, QString)));
QObject::connect(m_icproxy, SIGNAL(ForwardKey(uint, uint, bool)), q,
SIGNAL(forwardKey(uint, uint, bool)));
QObject::connect(
m_icproxy,
SIGNAL(UpdateFormattedPreedit(FcitxFormattedPreeditList, int)), q,
SIGNAL(updateFormattedPreedit(FcitxFormattedPreeditList, int)));
QObject::connect(m_icproxy, SIGNAL(DeleteSurroundingText(int, uint)), q,
SLOT(deleteSurroundingText(int, uint)));
delete m_createInputContextWatcher;
m_createInputContextWatcher = nullptr;
emit q->inputContextCreated(reply.argumentAt<1>());
}
FcitxQtInputContextProxy *q_ptr;
Q_DECLARE_PUBLIC(FcitxQtInputContextProxy);
FcitxQtWatcher *m_fcitxWatcher;
QDBusServiceWatcher m_watcher;
FcitxQtInputMethodProxy *m_improxy = nullptr;
FcitxQtInputContextProxyImpl *m_icproxy = nullptr;
QDBusPendingCallWatcher *m_createInputContextWatcher = nullptr;
QString m_display;
bool m_portal;
qulonglong m_capability;
};
}
#endif // _DBUSADDONS_FCITXQTINPUTCONTEXTPROXY_P_H_

View File

@ -0,0 +1,29 @@
/*
* This file was generated by qdbusxml2cpp version 0.7
* Command line was: qdbusxml2cpp -N -p fcitxqtinputcontextproxyimpl -c
* FcitxQtInputContextProxyImpl interfaces/org.fcitx.Fcitx.InputContext1.xml -i
* fcitxqtdbustypes.h -i fcitx5qt4dbusaddons_export.h
*
* qdbusxml2cpp is Copyright (C) 2015 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 "fcitxqtinputcontextproxyimpl.h"
namespace fcitx {
/*
* Implementation of interface class FcitxQtInputContextProxyImpl
*/
FcitxQtInputContextProxyImpl::FcitxQtInputContextProxyImpl(
const QString &service, const QString &path,
const QDBusConnection &connection, QObject *parent)
: QDBusAbstractInterface(service, path, staticInterfaceName(), connection,
parent) {}
FcitxQtInputContextProxyImpl::~FcitxQtInputContextProxyImpl() {}
}

View File

@ -0,0 +1,125 @@
/*
* This file was generated by qdbusxml2cpp version 0.7
* Command line was: qdbusxml2cpp -N -p fcitxqtinputcontextproxyimpl -c
* FcitxQtInputContextProxyImpl interfaces/org.fcitx.Fcitx.InputContext1.xml -i
* fcitxqtdbustypes.h -i fcitx5qt4dbusaddons_export.h
*
* qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
#ifndef FCITXQTINPUTCONTEXTPROXYIMPL_H_1508138556
#define FCITXQTINPUTCONTEXTPROXYIMPL_H_1508138556
#include "fcitx5qt4dbusaddons_export.h"
#include "fcitxqtdbustypes.h"
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QObject>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <QtDBus/QtDBus>
namespace fcitx {
/*
* Proxy class for interface org.fcitx.Fcitx.InputContext1
*/
class FcitxQtInputContextProxyImpl : public QDBusAbstractInterface {
Q_OBJECT
public:
static inline const char *staticInterfaceName() {
return "org.fcitx.Fcitx.InputContext1";
}
public:
FcitxQtInputContextProxyImpl(const QString &service, const QString &path,
const QDBusConnection &connection,
QObject *parent = 0);
~FcitxQtInputContextProxyImpl();
public Q_SLOTS: // METHODS
inline QDBusPendingReply<> DestroyIC() {
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("DestroyIC"),
argumentList);
}
inline QDBusPendingReply<> FocusIn() {
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("FocusIn"),
argumentList);
}
inline QDBusPendingReply<> FocusOut() {
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("FocusOut"),
argumentList);
}
inline QDBusPendingReply<bool> ProcessKeyEvent(uint keyval, uint keycode,
uint state, bool type,
uint time) {
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(keyval)
<< QVariant::fromValue(keycode)
<< QVariant::fromValue(state) << QVariant::fromValue(type)
<< QVariant::fromValue(time);
return asyncCallWithArgumentList(QLatin1String("ProcessKeyEvent"),
argumentList);
}
inline QDBusPendingReply<> Reset() {
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QLatin1String("Reset"), argumentList);
}
inline QDBusPendingReply<> SetCapability(qulonglong caps) {
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(caps);
return asyncCallWithArgumentList(QLatin1String("SetCapability"),
argumentList);
}
inline QDBusPendingReply<> SetCursorRect(int x, int y, int w, int h) {
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(x) << QVariant::fromValue(y)
<< QVariant::fromValue(w) << QVariant::fromValue(h);
return asyncCallWithArgumentList(QLatin1String("SetCursorRect"),
argumentList);
}
inline QDBusPendingReply<> SetSurroundingText(const QString &text,
uint cursor, uint anchor) {
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(text) << QVariant::fromValue(cursor)
<< QVariant::fromValue(anchor);
return asyncCallWithArgumentList(QLatin1String("SetSurroundingText"),
argumentList);
}
inline QDBusPendingReply<> SetSurroundingTextPosition(uint cursor,
uint anchor) {
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(cursor)
<< QVariant::fromValue(anchor);
return asyncCallWithArgumentList(
QLatin1String("SetSurroundingTextPosition"), argumentList);
}
Q_SIGNALS: // SIGNALS
void CommitString(const QString &str);
void CurrentIM(const QString &name, const QString &uniqueName,
const QString &langCode);
void DeleteSurroundingText(int offset, uint nchar);
void ForwardKey(uint keyval, uint state, bool type);
void UpdateFormattedPreedit(FcitxQtFormattedPreeditList str, int cursorpos);
};
}
#endif

View File

@ -0,0 +1,151 @@
/***************************************************************************
* Copyright (C) 2011~2012 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include "fcitxqtwatcher_p.h"
#include <QDBusConnection>
#include <QDBusConnectionInterface>
#include <QDBusServiceWatcher>
#include <QDir>
namespace fcitx {
FcitxQtWatcher::FcitxQtWatcher(QObject *parent)
: QObject(parent), d_ptr(new FcitxQtWatcherPrivate(this)) {}
FcitxQtWatcher::FcitxQtWatcher(const QDBusConnection &connection,
QObject *parent)
: FcitxQtWatcher(parent) {
setConnection(connection);
}
FcitxQtWatcher::~FcitxQtWatcher() { delete d_ptr; }
bool FcitxQtWatcher::availability() const {
Q_D(const FcitxQtWatcher);
return d->m_availability;
}
void FcitxQtWatcher::setConnection(const QDBusConnection &connection) {
Q_D(FcitxQtWatcher);
return d->m_serviceWatcher.setConnection(connection);
}
QDBusConnection FcitxQtWatcher::connection() const {
Q_D(const FcitxQtWatcher);
return d->m_serviceWatcher.connection();
}
void FcitxQtWatcher::setWatchPortal(bool portal) {
Q_D(FcitxQtWatcher);
d->m_watchPortal = portal;
}
bool FcitxQtWatcher::watchPortal() const {
Q_D(const FcitxQtWatcher);
return d->m_watchPortal;
}
QString FcitxQtWatcher::serviceName() const {
Q_D(const FcitxQtWatcher);
if (d->m_mainPresent) {
return FCITX_MAIN_SERVICE_NAME;
}
if (d->m_portalPresent) {
return FCITX_PORTAL_SERVICE_NAME;
}
return QString();
}
void FcitxQtWatcher::setAvailability(bool availability) {
Q_D(FcitxQtWatcher);
if (d->m_availability != availability) {
d->m_availability = availability;
emit availibilityChanged(d->m_availability);
}
}
void FcitxQtWatcher::watch() {
Q_D(FcitxQtWatcher);
if (d->m_watched) {
return;
}
connect(&d->m_serviceWatcher,
SIGNAL(serviceOwnerChanged(QString, QString, QString)), this,
SLOT(imChanged(QString, QString, QString)));
d->m_serviceWatcher.addWatchedService(FCITX_MAIN_SERVICE_NAME);
if (d->m_watchPortal) {
d->m_serviceWatcher.addWatchedService(FCITX_PORTAL_SERVICE_NAME);
}
if (QDBusConnection::sessionBus().interface()->isServiceRegistered(
FCITX_MAIN_SERVICE_NAME)) {
d->m_mainPresent = true;
}
if (d->m_watchPortal &&
QDBusConnection::sessionBus().interface()->isServiceRegistered(
FCITX_PORTAL_SERVICE_NAME)) {
d->m_portalPresent = true;
}
updateAvailbility();
d->m_watched = true;
}
void FcitxQtWatcher::unwatch() {
Q_D(FcitxQtWatcher);
if (!d->m_watched) {
return;
}
disconnect(&d->m_serviceWatcher,
SIGNAL(serviceOwnerChanged(QString, QString, QString)), this,
SLOT(imChanged(QString, QString, QString)));
}
bool FcitxQtWatcher::isWatching() const {
Q_D(const FcitxQtWatcher);
return d->m_watched;
}
void FcitxQtWatcher::imChanged(const QString &service, const QString &,
const QString &newOwner) {
Q_D(FcitxQtWatcher);
if (service == FCITX_MAIN_SERVICE_NAME) {
if (!newOwner.isEmpty()) {
d->m_mainPresent = true;
} else {
d->m_mainPresent = false;
}
} else if (service == FCITX_PORTAL_SERVICE_NAME) {
if (!newOwner.isEmpty()) {
d->m_portalPresent = true;
} else {
d->m_portalPresent = false;
}
}
updateAvailbility();
}
void FcitxQtWatcher::updateAvailbility() {
Q_D(FcitxQtWatcher);
setAvailability(d->m_mainPresent || d->m_portalPresent);
}
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2017~2017 by CSSlayer
* wengxt@gmail.com
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; see the file COPYING. If not,
* see <http://www.gnu.org/licenses/>.
*/
#ifndef _DBUSADDONS_FCITXQTWATCHER_H_
#define _DBUSADDONS_FCITXQTWATCHER_H_
#include "fcitx5qt4dbusaddons_export.h"
#include <QDBusConnection>
#include <QObject>
namespace fcitx {
class FcitxQtWatcherPrivate;
class FCITX5QT4DBUSADDONS_EXPORT FcitxQtWatcher : public QObject {
Q_OBJECT
public:
explicit FcitxQtWatcher(QObject *parent = nullptr);
explicit FcitxQtWatcher(const QDBusConnection &connection,
QObject *parent = nullptr);
~FcitxQtWatcher();
void watch();
void unwatch();
void setConnection(const QDBusConnection &connection);
QDBusConnection connection() const;
void setWatchPortal(bool portal);
bool watchPortal() const;
bool isWatching() const;
bool availability() const;
QString serviceName() const;
signals:
void availibilityChanged(bool);
private slots:
void imChanged(const QString &service, const QString &oldOwner,
const QString &newOwner);
private:
void setAvailability(bool availability);
void updateAvailbility();
FcitxQtWatcherPrivate *const d_ptr;
Q_DECLARE_PRIVATE(FcitxQtWatcher);
};
}
#endif // _DBUSADDONS_FCITXQTWATCHER_H_

View File

@ -0,0 +1,43 @@
/*
* Copyright (C) 2017~2017 by CSSlayer
* wengxt@gmail.com
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; see the file COPYING. If not,
* see <http://www.gnu.org/licenses/>.
*/
#ifndef _DBUSADDONS_FCITXQTWATCHER_P_H_
#define _DBUSADDONS_FCITXQTWATCHER_P_H_
#include "fcitxqtwatcher.h"
#include <QDBusServiceWatcher>
#define FCITX_MAIN_SERVICE_NAME "org.fcitx.Fcitx5"
#define FCITX_PORTAL_SERVICE_NAME "org.freedesktop.portal.Fcitx"
namespace fcitx {
class FcitxQtWatcherPrivate {
public:
FcitxQtWatcherPrivate(FcitxQtWatcher *q) : m_serviceWatcher(q) {}
QDBusServiceWatcher m_serviceWatcher;
bool m_watchPortal = false;
bool m_availability = false;
bool m_mainPresent = false;
bool m_portalPresent = false;
bool m_watched = false;
};
}
#endif // _DBUSADDONS_FCITXQTWATCHER_P_H_

View File

@ -1,5 +1,5 @@
#!/bin/sh
qdbusxml2cpp -N -p fcitxqtinputcontextproxy -c FcitxQtInputContextProxy interfaces/org.fcitx.Fcitx.InputContext1.xml -i fcitxqtdbustypes.h -i fcitx5qt4dbusaddons_export.h
qdbusxml2cpp -N -p fcitxqtinputcontextproxyimpl -c FcitxQtInputContextProxyImpl interfaces/org.fcitx.Fcitx.InputContext1.xml -i fcitxqtdbustypes.h -i fcitx5qt4dbusaddons_export.h
qdbusxml2cpp -N -p fcitxqtinputmethodproxy -c FcitxQtInputMethodProxy interfaces/org.fcitx.Fcitx.InputMethod1.xml -i fcitxqtdbustypes.h -i fcitx5qt4dbusaddons_export.h
qdbusxml2cpp -N -p fcitxqtcontrollerproxy -c FcitxQtControllerProxy interfaces/org.fcitx.Fcitx.Controller1.xml -i fcitxqtdbustypes.h -i fcitx5qt4dbusaddons_export.h

View File

@ -19,9 +19,11 @@
#include <QApplication>
#include <QDBusConnection>
#include <QDateTime>
#include <QKeyEvent>
#include <QPalette>
#include <QTextCharFormat>
#include <QTextCodec>
#include <QWidget>
#include <QX11Info>
@ -31,9 +33,8 @@
#include "qtkey.h"
#include "fcitxqtconnection.h"
#include "fcitxqtinputcontextproxy.h"
#include "fcitxqtinputmethodproxy.h"
#include "fcitxqtwatcher.h"
#include "qfcitxinputcontext.h"
#include <fcitx-utils/key.h>
@ -118,7 +119,7 @@ struct xkb_context *_xkb_context_new_helper() {
}
QFcitxInputContext::QFcitxInputContext()
: m_connection(new FcitxQtConnection(this)), m_improxy(nullptr),
: m_watcher(new FcitxQtWatcher(QDBusConnection::sessionBus(), this)),
m_cursorPos(0), m_useSurroundingText(false),
m_syncMode(get_boolean_env("FCITX_QT_USE_SYNC", false)), m_destroy(false),
m_xkbContext(_xkb_context_new_helper()),
@ -132,44 +133,20 @@ QFcitxInputContext::QFcitxInputContext()
: 0) {
FcitxQtFormattedPreedit::registerMetaType();
FcitxQtInputContextArgument::registerMetaType();
connect(m_connection, SIGNAL(connected()), this, SLOT(connected()));
connect(m_connection, SIGNAL(disconnected()), this, SLOT(cleanUp()));
m_connection->startConnection();
m_watcher->setWatchPortal(true);
m_watcher->watch();
}
QFcitxInputContext::~QFcitxInputContext() {
m_destroy = true;
m_watcher->unwatch();
cleanUp();
}
void QFcitxInputContext::connected() {
if (!m_connection->isConnected())
return;
// qDebug() << "create Input Context" << m_connection->name();
if (m_improxy) {
delete m_improxy;
m_improxy = nullptr;
}
m_improxy = new FcitxQtInputMethodProxy(m_connection->serviceName(),
QLatin1String("/inputmethod"),
*m_connection->connection(), this);
QWidget *w = qApp->focusWidget();
if (w)
createICData(w);
delete m_watcher;
}
void QFcitxInputContext::cleanUp() {
m_icMap.clear();
if (m_improxy) {
delete m_improxy;
m_improxy = nullptr;
}
if (!m_destroy) {
commitPreedit();
}
@ -183,8 +160,7 @@ void QFcitxInputContext::mouseHandler(int cursorPosition, QMouseEvent *event) {
}
}
void QFcitxInputContext::commitPreedit() {
QWidget *input = qApp->focusWidget();
void QFcitxInputContext::commitPreedit(QPointer<QWidget> input) {
if (!input)
return;
if (m_commitPreedit.length() <= 0)
@ -207,9 +183,9 @@ bool checkUtf8(const QByteArray &byteArray) {
void QFcitxInputContext::reset() {
commitPreedit();
FcitxQtInputContextProxy *proxy = validIC();
if (proxy)
proxy->Reset();
if (FcitxQtInputContextProxy *proxy = validIC()) {
proxy->reset();
}
if (m_xkbComposeState) {
xkb_compose_state_reset(m_xkbComposeState.data());
}
@ -221,7 +197,8 @@ void QFcitxInputContext::update() {
if (!proxy)
return;
auto &data = m_icMap[window];
FcitxQtICData &data = *static_cast<FcitxQtICData *>(
proxy->property("icData").value<void *>());
QWidget *input = qApp->focusWidget();
if (!input)
@ -283,11 +260,11 @@ void QFcitxInputContext::update() {
anchor = tempUCS4.size();
if (data.surroundingText != text) {
data.surroundingText = text;
proxy->SetSurroundingText(text, cursor, anchor);
proxy->setSurroundingText(text, cursor, anchor);
} else {
if (data.surroundingAnchor != anchor ||
data.surroundingCursor != cursor)
proxy->SetSurroundingTextPosition(cursor, anchor);
proxy->setSurroundingTextPosition(cursor, anchor);
}
data.surroundingCursor = cursor;
data.surroundingAnchor = anchor;
@ -307,7 +284,7 @@ void QFcitxInputContext::setFocusWidget(QWidget *object) {
Q_UNUSED(object);
FcitxQtInputContextProxy *proxy = validICByWindow(m_lastWindow);
if (proxy) {
proxy->FocusOut();
proxy->focusOut();
}
QWidget *window = qApp->focusWidget();
@ -317,7 +294,7 @@ void QFcitxInputContext::setFocusWidget(QWidget *object) {
}
proxy = validICByWindow(window);
if (proxy)
proxy->FocusIn();
proxy->focusIn();
else {
createICData(window);
}
@ -344,7 +321,8 @@ void QFcitxInputContext::cursorRectChanged() {
if (!proxy)
return;
auto &data = m_icMap[inputWindow];
FcitxQtICData &data = *static_cast<FcitxQtICData *>(
proxy->property("icData").value<void *>());
QRect r = inputWindow->inputMethodQuery(Qt::ImMicroFocus).toRect();
@ -353,107 +331,49 @@ void QFcitxInputContext::cursorRectChanged() {
if (data.rect != newRect) {
data.rect = newRect;
proxy->SetCursorRect(newRect.x(), newRect.y(), newRect.width(),
proxy->setCursorRect(newRect.x(), newRect.y(), newRect.width(),
newRect.height());
}
}
void QFcitxInputContext::createInputContext(QWidget *w) {
if (!m_connection->isConnected())
void QFcitxInputContext::createInputContextFinished(const QByteArray &uuid) {
auto proxy = qobject_cast<FcitxQtInputContextProxy *>(sender());
if (!proxy) {
return;
// qDebug() << "create Input Context" << m_connection->connection()->name();
if (!m_improxy) {
m_improxy = new FcitxQtInputMethodProxy(
m_connection->serviceName(), QLatin1String("/inputmethod"),
*m_connection->connection(), this);
}
if (!m_improxy->isValid())
return;
QFileInfo info(QCoreApplication::applicationFilePath());
FcitxQtInputContextArgumentList args;
args << FcitxQtInputContextArgument("program", info.fileName());
args << FcitxQtInputContextArgument("display", "x11:");
auto result = m_improxy->CreateInputContext(args);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(result);
watcher->setProperty("wid", qVariantFromValue(static_cast<void *>(w)));
connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher *)), this,
SLOT(createInputContextFinished(QDBusPendingCallWatcher *)));
}
void QFcitxInputContext::createInputContextFinished(
QDBusPendingCallWatcher *watcher) {
auto w =
reinterpret_cast<QWidget *>(watcher->property("wid").value<void *>());
auto iter = m_icMap.find(w);
if (iter == m_icMap.end()) {
return;
reinterpret_cast<QWidget *>(proxy->property("wid").value<void *>());
FcitxQtICData *data =
static_cast<FcitxQtICData *>(proxy->property("icData").value<void *>());
data->rect = QRect();
if (proxy->isValid()) {
QWidget *window = qApp->focusWidget();
if (window && window == w) {
proxy->focusIn();
cursorRectChanged();
}
setFocusGroupForX11(uuid);
}
auto &data = iter->second;
fcitx::CapabilityFlags flag;
flag |= fcitx::CapabilityFlag::Preedit;
flag |= fcitx::CapabilityFlag::FormattedPreedit;
flag |= fcitx::CapabilityFlag::ClientUnfocusCommit;
flag |= fcitx::CapabilityFlag::GetIMInfoOnFocus;
m_useSurroundingText =
get_boolean_env("FCITX_QT_ENABLE_SURROUNDING_TEXT", true);
if (m_useSurroundingText)
flag |= fcitx::CapabilityFlag::SurroundingText;
QDBusPendingReply<QDBusObjectPath, QByteArray> result = *watcher;
do {
if (result.isError()) {
break;
}
if (!m_connection->isConnected())
break;
auto objectPath = result.argumentAt<0>();
if (data.proxy) {
delete data.proxy;
}
data.proxy = new FcitxQtInputContextProxy(
m_connection->serviceName(), objectPath.path(),
*m_connection->connection(), this);
data.proxy->setProperty("icData",
qVariantFromValue(static_cast<void *>(&data)));
connect(data.proxy, SIGNAL(CommitString(QString)), this,
SLOT(commitString(QString)));
connect(data.proxy, SIGNAL(ForwardKey(uint, uint, bool)), this,
SLOT(forwardKey(uint, uint, bool)));
connect(data.proxy, SIGNAL(UpdateFormattedPreedit(
FcitxQtFormattedPreeditList, int)),
this,
SLOT(updateFormattedPreedit(FcitxQtFormattedPreeditList, int)));
connect(data.proxy, SIGNAL(DeleteSurroundingText(int, uint)), this,
SLOT(deleteSurroundingText(int, uint)));
if (data.proxy->isValid()) {
QWidget *window = qApp->focusWidget();
if (window && window == w)
data.proxy->FocusIn();
}
setFocusGroupForX11(result.argumentAt<1>());
fcitx::CapabilityFlags flag;
flag |= fcitx::CapabilityFlag::Preedit;
flag |= fcitx::CapabilityFlag::FormattedPreedit;
flag |= fcitx::CapabilityFlag::ClientUnfocusCommit;
flag |= fcitx::CapabilityFlag::GetIMInfoOnFocus;
m_useSurroundingText =
get_boolean_env("FCITX_QT_ENABLE_SURROUNDING_TEXT", true);
if (m_useSurroundingText)
flag |= fcitx::CapabilityFlag::SurroundingText;
addCapability(data, flag, true);
} while (0);
delete watcher;
addCapability(*data, flag, true);
}
void QFcitxInputContext::updateCapability(const FcitxQtICData &data) {
if (!data.proxy || !data.proxy->isValid())
return;
QDBusPendingReply<void> result =
data.proxy->SetCapability((uint)data.capability);
QDBusPendingReply<void> result = data.proxy->setCapability(data.capability);
}
void QFcitxInputContext::commitString(const QString &str) {
@ -604,12 +524,30 @@ void QFcitxInputContext::forwardKey(uint keyval, uint state, bool type) {
void QFcitxInputContext::createICData(QWidget *w) {
auto iter = m_icMap.find(w);
if (iter == m_icMap.end()) {
m_icMap.emplace(std::piecewise_construct, std::forward_as_tuple(w),
std::forward_as_tuple());
connect(w, SIGNAL(destroyed(QObject *)), this,
SLOT(windowDestroyed(QObject *)));
auto result =
m_icMap.emplace(std::piecewise_construct, std::forward_as_tuple(w),
std::forward_as_tuple(m_watcher));
iter = result.first;
auto &data = iter->second;
data.proxy->setDisplay("x11:");
data.proxy->setProperty("wid",
qVariantFromValue(static_cast<void *>(w)));
data.proxy->setProperty("icData",
qVariantFromValue(static_cast<void *>(&data)));
connect(data.proxy, SIGNAL(inputContextCreated(QByteArray)), this,
SLOT(createInputContextFinished(QByteArray)));
connect(data.proxy, SIGNAL(commitString(QString)), this,
SLOT(commitString(QString)));
connect(data.proxy, SIGNAL(forwardKey(uint, uint, bool)), this,
SLOT(forwardKey(uint, uint, bool)));
connect(data.proxy, SIGNAL(updateFormattedPreedit(
FcitxQtFormattedPreeditList, int)),
this,
SLOT(updateFormattedPreedit(FcitxQtFormattedPreeditList, int)));
connect(data.proxy, SIGNAL(deleteSurroundingText(int, uint)), this,
SLOT(deleteSurroundingText(int, uint)));
}
createInputContext(w);
}
QKeyEvent *QFcitxInputContext::createKeyEvent(uint keyval, uint _state,
@ -644,7 +582,7 @@ QKeyEvent *QFcitxInputContext::createKeyEvent(uint keyval, uint _state,
QKeyEvent *keyevent =
new QKeyEvent(isRelease ? (QEvent::KeyRelease) : (QEvent::KeyPress),
key, qstate, QString(), false, count);
key, qstate, text, false, count);
return keyevent;
}
@ -682,17 +620,16 @@ bool QFcitxInputContext::filterEvent(const QEvent *event) {
}
}
proxy->FocusIn();
proxy->focusIn();
auto reply =
proxy->ProcessKeyEvent(keyval, keycode, state, isRelease,
proxy->processKeyEvent(keyval, keycode, state, isRelease,
QDateTime::currentDateTime().toTime_t());
if (Q_UNLIKELY(m_syncMode)) {
reply.waitForFinished();
if (!m_connection->isConnected() || !reply.isFinished() ||
reply.isError() || !reply.value()) {
if (reply.isError() || !reply.value()) {
if (filterEventFallback(keyval, keycode, state, isRelease)) {
return true;
} else {
@ -704,7 +641,7 @@ bool QFcitxInputContext::filterEvent(const QEvent *event) {
}
} else {
ProcessKeyWatcher *watcher = new ProcessKeyWatcher(
*keyEvent, qApp->focusWidget(), reply, this);
*keyEvent, qApp->focusWidget(), reply, proxy);
connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher *)), this,
SLOT(processKeyEventFinished(QDBusPendingCallWatcher *)));
return true;
@ -721,6 +658,7 @@ void QFcitxInputContext::processKeyEventFinished(QDBusPendingCallWatcher *w) {
QWidget *window = watcher->window();
// if window is already destroyed, we can only throw this event away.
if (!window) {
delete watcher;
return;
}
@ -740,7 +678,7 @@ void QFcitxInputContext::processKeyEventFinished(QDBusPendingCallWatcher *w) {
filtered = true;
}
if (!result.isError()) {
if (!watcher->isError()) {
update();
}

View File

@ -21,6 +21,8 @@
#define QFCITXINPUTCONTEXT_H
#include "fcitxqtinputcontextproxy.h"
#include "fcitxqtwatcher.h"
#include <QApplication>
#include <QDBusConnection>
#include <QDBusServiceWatcher>
#include <QInputContext>
@ -37,17 +39,11 @@ namespace fcitx {
class FcitxQtConnection;
struct FcitxQtICData {
FcitxQtICData()
: proxy(nullptr), surroundingAnchor(-1), surroundingCursor(-1) {}
FcitxQtICData(FcitxQtWatcher *watcher)
: proxy(new FcitxQtInputContextProxy(watcher, watcher)),
surroundingAnchor(-1), surroundingCursor(-1) {}
FcitxQtICData(const FcitxQtICData &that) = delete;
~FcitxQtICData() {
if (proxy) {
if (proxy->isValid()) {
proxy->DestroyIC();
}
delete proxy;
}
}
~FcitxQtICData() { delete proxy; }
fcitx::CapabilityFlags capability;
FcitxQtInputContextProxy *proxy;
QRect rect;
@ -128,13 +124,11 @@ public Q_SLOTS:
int cursorPos);
void deleteSurroundingText(int offset, uint nchar);
void forwardKey(uint keyval, uint state, bool type);
void createInputContextFinished(QDBusPendingCallWatcher *watcher);
void connected();
void createInputContextFinished(const QByteArray &uuid);
void cleanUp();
void windowDestroyed(QObject *object);
private:
void createInputContext(QWidget *w);
bool processCompose(uint keyval, uint state, bool isRelaese);
QKeyEvent *createKeyEvent(uint keyval, uint state, bool isRelaese);
@ -158,15 +152,14 @@ private:
}
void updateCapability(const FcitxQtICData &data);
void commitPreedit();
void commitPreedit(QPointer<QWidget> input = qApp->focusWidget());
void createICData(QWidget *w);
FcitxQtInputContextProxy *validIC();
FcitxQtInputContextProxy *validICByWindow(QWidget *window);
bool filterEventFallback(uint keyval, uint keycode, uint state,
bool isRelaese);
FcitxQtConnection *m_connection;
FcitxQtInputMethodProxy *m_improxy;
FcitxQtWatcher *m_watcher;
QString m_preedit;
QString m_commitPreedit;
FcitxQtFormattedPreeditList m_preeditList;
@ -184,7 +177,6 @@ private:
m_xkbComposeTable;
QScopedPointer<struct xkb_compose_state, XkbComposeStateDeleter>
m_xkbComposeState;
QLocale m_locale;
private slots:
void processKeyEventFinished(QDBusPendingCallWatcher *);
};

View File

@ -22,15 +22,16 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/fcitx5qt5dbusaddons_version.h
DESTINATION ${Fcitx5Qt5_INCLUDE_INSTALL_DIR} COMPONENT Devel )
set(dbusaddons_SOURCES
fcitxqtconnection.cpp
fcitxqtwatcher.cpp
fcitxqtdbustypes.cpp
fcitxqtinputcontextproxyimpl.cpp
fcitxqtinputcontextproxy.cpp
fcitxqtinputmethodproxy.cpp
fcitxqtcontrollerproxy.cpp
)
set(dbusaddons_HEADERS
fcitxqtconnection.h
fcitxqtwatcher.h
fcitxqtdbustypes.h
fcitxqtinputcontextproxy.h
fcitxqtinputmethodproxy.h

View File

@ -1,187 +0,0 @@
/*
* Copyright (C) 2012~2017 by CSSlayer
* wengxt@gmail.com
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; see the file COPYING. If not,
* see <http://www.gnu.org/licenses/>.
*/
#include "fcitxqtconnection_p.h"
#include <QDBusConnection>
#include <QDBusConnectionInterface>
#include <QDBusReply>
#include <QDBusServiceWatcher>
#include <QDebug>
#include <QDir>
#include <QFile>
#include <QTimer>
#include <errno.h>
#include <signal.h>
namespace fcitx {
FcitxQtConnection::FcitxQtConnection(QObject *parent)
: QObject(parent), d_ptr(new FcitxQtConnectionPrivate(this)) {}
void FcitxQtConnection::startConnection() {
Q_D(FcitxQtConnection);
if (!d->m_initialized) {
d->initialize();
d->createConnection();
}
}
void FcitxQtConnection::endConnection() {
Q_D(FcitxQtConnection);
d->cleanUp();
d->finalize();
d->m_connectedOnce = false;
}
bool FcitxQtConnection::autoReconnect() {
Q_D(FcitxQtConnection);
return d->m_autoReconnect;
}
void FcitxQtConnection::setAutoReconnect(bool a) {
Q_D(FcitxQtConnection);
d->m_autoReconnect = a;
}
QDBusConnection *FcitxQtConnection::connection() {
Q_D(FcitxQtConnection);
return d->m_connection;
}
const QString &FcitxQtConnection::serviceName() {
Q_D(FcitxQtConnection);
return d->m_serviceName;
}
bool FcitxQtConnection::isConnected() {
Q_D(FcitxQtConnection);
return d->isConnected();
}
FcitxQtConnection::~FcitxQtConnection() {}
FcitxQtConnectionPrivate::FcitxQtConnectionPrivate(FcitxQtConnection *conn)
: QObject(conn), q_ptr(conn), m_serviceName("org.fcitx.Fcitx5"),
m_connection(nullptr), m_serviceWatcher(new QDBusServiceWatcher(this)),
m_autoReconnect(true), m_connectedOnce(false), m_initialized(false) {}
FcitxQtConnectionPrivate::~FcitxQtConnectionPrivate() {
if (m_connection)
delete m_connection;
}
void FcitxQtConnectionPrivate::initialize() {
m_serviceWatcher->setConnection(QDBusConnection::sessionBus());
m_serviceWatcher->addWatchedService(m_serviceName);
m_initialized = true;
}
void FcitxQtConnectionPrivate::finalize() {
m_serviceWatcher->removeWatchedService(m_serviceName);
m_initialized = false;
}
void FcitxQtConnectionPrivate::createConnection() {
if (m_connectedOnce && !m_autoReconnect) {
return;
}
disconnect(m_serviceWatcher, &QDBusServiceWatcher::serviceOwnerChanged,
this, &FcitxQtConnectionPrivate::imChanged);
if (!m_connection) {
QDBusConnection *connection =
new QDBusConnection(QDBusConnection::sessionBus());
connect(m_serviceWatcher, &QDBusServiceWatcher::serviceOwnerChanged,
this, &FcitxQtConnectionPrivate::imChanged);
QDBusReply<bool> registered =
connection->interface()->isServiceRegistered(m_serviceName);
if (!registered.isValid() || !registered.value()) {
delete connection;
} else {
m_connection = connection;
}
}
Q_Q(FcitxQtConnection);
if (m_connection) {
m_connection->connect("org.freedesktop.DBus.Local",
"/org/freedesktop/DBus/Local",
"org.freedesktop.DBus.Local", "Disconnected",
this, SLOT(dbusDisconnected()));
m_connectedOnce = true;
emit q->connected();
}
}
void FcitxQtConnectionPrivate::dbusDisconnected() {
cleanUp();
createConnection();
}
void FcitxQtConnectionPrivate::imChanged(const QString &service,
const QString &oldowner,
const QString &newowner) {
if (service == m_serviceName) {
/* old die */
if (oldowner.length() > 0 || newowner.length() > 0)
cleanUp();
/* new rise */
if (newowner.length() > 0) {
QTimer::singleShot(100, this,
&FcitxQtConnectionPrivate::newServiceAppear);
}
}
}
void FcitxQtConnectionPrivate::cleanUp() {
Q_Q(FcitxQtConnection);
bool doemit = false;
if (m_connection) {
delete m_connection;
m_connection = nullptr;
doemit = true;
}
if (!m_autoReconnect && m_connectedOnce)
finalize();
/* we want m_connection and finalize being called before the signal
* thus isConnected will return false in slot
* and startConnection can be called in slot
*/
if (doemit)
emit q->disconnected();
}
bool FcitxQtConnectionPrivate::isConnected() {
return m_connection && m_connection->isConnected();
}
void FcitxQtConnectionPrivate::newServiceAppear() {
if (!isConnected()) {
cleanUp();
createConnection();
}
}
}

View File

@ -1,112 +0,0 @@
/*
* Copyright (C) 2012~2017 by CSSlayer
* wengxt@gmail.com
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; see the file COPYING. If not,
* see <http://www.gnu.org/licenses/>.
*/
#ifndef _DBUSADDONS_FCITXQTCONNECTION_H_
#define _DBUSADDONS_FCITXQTCONNECTION_H_
#include "fcitx5qt5dbusaddons_export.h"
#include <QObject>
class QDBusConnection;
namespace fcitx {
class FcitxQtConnectionPrivate;
/**
* dbus connection to fcitx
**/
class FCITX5QT5DBUSADDONS_EXPORT FcitxQtConnection : public QObject {
Q_OBJECT
Q_PROPERTY(bool autoReconnect READ autoReconnect WRITE setAutoReconnect)
Q_PROPERTY(bool connected READ isConnected)
Q_PROPERTY(QDBusConnection *connection READ connection)
Q_PROPERTY(QString serviceName READ serviceName)
public:
/**
* create a new connection
*
* @param parent
**/
explicit FcitxQtConnection(QObject *parent = 0);
/**
* destroy the connection
**/
virtual ~FcitxQtConnection();
/**
* the connection will not start to work until you call this function
* you may want to connect to the signal before you call this function
**/
void startConnection();
void endConnection();
/**
* automatically reconnect if fcitx disappeared
*
* @param a ...
* @return void
**/
void setAutoReconnect(bool a);
/**
* check this connection is doing automatical reconnect or not
*
* default value is true
**/
bool autoReconnect();
/**
* return the current dbus connection to fcitx, notice, the object return
* by this function might be deteled if fcitx disappear, or might return 0
* if fcitx is not running
*
* @return QDBusConnection*
**/
QDBusConnection *connection();
/**
* current fcitx dbus service name, can be used for create DBus proxy
*
* @return service name
**/
const QString &serviceName();
/**
* check its connected or not
**/
bool isConnected();
Q_SIGNALS:
/**
* this signal will be emitted upon fcitx appears
**/
void connected();
/**
* this signal will be emitted upon fcitx disappears
*
* it will come with connected in pair
**/
void disconnected();
private:
FcitxQtConnectionPrivate *const d_ptr;
Q_DECLARE_PRIVATE(FcitxQtConnection);
};
}
#endif // _DBUSADDONS_FCITXQTCONNECTION_H_

View File

@ -1,60 +0,0 @@
/*
* Copyright (C) 2017~2017 by CSSlayer
* wengxt@gmail.com
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; see the file COPYING. If not,
* see <http://www.gnu.org/licenses/>.
*/
#ifndef _DBUSADDONS_FCITXQTCONNECTION_P_H_
#define _DBUSADDONS_FCITXQTCONNECTION_P_H_
#include "fcitxqtconnection.h"
class QDBusConnection;
class QDBusServiceWatcher;
namespace fcitx {
class FcitxQtConnectionPrivate : public QObject {
Q_OBJECT
public:
FcitxQtConnectionPrivate(FcitxQtConnection *conn);
virtual ~FcitxQtConnectionPrivate();
FcitxQtConnection *const q_ptr;
Q_DECLARE_PUBLIC(FcitxQtConnection);
private Q_SLOTS:
void imChanged(const QString &service, const QString &oldowner,
const QString &newowner);
void dbusDisconnected();
void cleanUp();
void newServiceAppear();
private:
bool isConnected();
void createConnection();
void initialize();
void finalize();
QString m_serviceName;
QDBusConnection *m_connection;
QDBusServiceWatcher *m_serviceWatcher;
QString m_socketFile;
bool m_autoReconnect;
bool m_connectedOnce;
bool m_initialized;
};
}
#endif // _DBUSADDONS_FCITXQTCONNECTION_P_H_

View File

@ -1,29 +1,106 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was:
*
* qdbusxml2cpp is Copyright (C) 2016 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.
*/
* Copyright (C) 2017~2017 by CSSlayer
* wengxt@gmail.com
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; see the file COPYING. If not,
* see <http://www.gnu.org/licenses/>.
*/
#include "fcitxqtinputcontextproxy.h"
#include "fcitxqtinputcontextproxy_p.h"
#include <QDBusInterface>
#include <QDBusMetaType>
#include <QDBusConnectionInterface>
#include <QFileInfo>
#include <QCoreApplication>
#include <QTimer>
namespace fcitx {
/*
* Implementation of interface class FcitxQtInputContextProxy
*/
FcitxQtInputContextProxy::FcitxQtInputContextProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
FcitxQtInputContextProxy::FcitxQtInputContextProxy(FcitxQtWatcher *watcher, QObject *parent) : QObject(parent),
d_ptr(new FcitxQtInputContextProxyPrivate(watcher, this))
{
}
FcitxQtInputContextProxy::~FcitxQtInputContextProxy()
{
delete d_ptr;
}
void FcitxQtInputContextProxy::setDisplay(const QString& display)
{
Q_D(FcitxQtInputContextProxy);
d->m_display = display;
}
const QString &FcitxQtInputContextProxy::display() const
{
Q_D(const FcitxQtInputContextProxy);
return d->m_display;
}
bool FcitxQtInputContextProxy::isValid() const
{
Q_D(const FcitxQtInputContextProxy);
return d->isValid();
}
QDBusPendingReply<> FcitxQtInputContextProxy::focusIn()
{
Q_D(FcitxQtInputContextProxy);
return d->m_icproxy->FocusIn();
}
QDBusPendingReply<> FcitxQtInputContextProxy::focusOut()
{
Q_D(FcitxQtInputContextProxy);
return d->m_icproxy->FocusOut();
}
QDBusPendingReply<bool> FcitxQtInputContextProxy::processKeyEvent(uint keyval, uint keycode, uint state, bool type, uint time)
{
Q_D(FcitxQtInputContextProxy);
return d->m_icproxy->ProcessKeyEvent(keyval, keycode, state, type, time);
}
QDBusPendingReply<> FcitxQtInputContextProxy::reset()
{
Q_D(FcitxQtInputContextProxy);
return d->m_icproxy->Reset();
}
QDBusPendingReply<> FcitxQtInputContextProxy::setCapability(qulonglong caps)
{
Q_D(FcitxQtInputContextProxy);
return d->m_icproxy->SetCapability(caps);
}
QDBusPendingReply<> FcitxQtInputContextProxy::setCursorRect(int x, int y, int w, int h)
{
Q_D(FcitxQtInputContextProxy);
return d->m_icproxy->SetCursorRect(x, y, w, h);
}
QDBusPendingReply<> FcitxQtInputContextProxy::setSurroundingText(const QString &text, uint cursor, uint anchor)
{
Q_D(FcitxQtInputContextProxy);
return d->m_icproxy->SetSurroundingText(text, cursor, anchor);
}
QDBusPendingReply<> FcitxQtInputContextProxy::setSurroundingTextPosition(uint cursor, uint anchor)
{
Q_D(FcitxQtInputContextProxy);
return d->m_icproxy->SetSurroundingTextPosition(cursor, anchor);
}
}

View File

@ -1,112 +1,73 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was:
*
* qdbusxml2cpp is Copyright (C) 2016 The Qt Company Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
* Copyright (C) 2017~2017 by CSSlayer
* wengxt@gmail.com
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; see the file COPYING. If not,
* see <http://www.gnu.org/licenses/>.
*/
#ifndef _DBUSADDONS_FCITXQTINPUTCONTEXTPROXY_H_
#define _DBUSADDONS_FCITXQTINPUTCONTEXTPROXY_H_
#ifndef FCITXQTINPUTCONTEXTPROXY_H
#define FCITXQTINPUTCONTEXTPROXY_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>
#include "fcitxqtdbustypes.h"
#include "fcitx5qt5dbusaddons_export.h"
#include <QObject>
#include <QDBusServiceWatcher>
#include <QDBusConnection>
#include <QDBusPendingReply>
#include "fcitxqtdbustypes.h"
class QDBusPendingCallWatcher;
namespace fcitx {
/*
* Proxy class for interface org.fcitx.Fcitx.InputContext1
*/
class FCITX5QT5DBUSADDONS_EXPORT FcitxQtInputContextProxy: public QDBusAbstractInterface
{
class FcitxQtWatcher;
class FcitxQtInputContextProxyPrivate;
class FCITX5QT5DBUSADDONS_EXPORT FcitxQtInputContextProxy : public QObject {
Q_OBJECT
public:
static inline const char *staticInterfaceName()
{ return "org.fcitx.Fcitx.InputContext1"; }
public:
FcitxQtInputContextProxy(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);
FcitxQtInputContextProxy(FcitxQtWatcher *watcher, QObject *parent);
~FcitxQtInputContextProxy();
public Q_SLOTS: // METHODS
inline QDBusPendingReply<> DestroyIC()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("DestroyIC"), argumentList);
}
bool isValid() const;
void setDisplay(const QString &display);
const QString &display() const;
inline QDBusPendingReply<> FocusIn()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("FocusIn"), argumentList);
}
public slots:
QDBusPendingReply<> focusIn();
QDBusPendingReply<> focusOut();
QDBusPendingReply<bool> processKeyEvent(uint keyval, uint keycode, uint state, bool type, uint time);
QDBusPendingReply<> reset();
QDBusPendingReply<> setCapability(qulonglong caps);
QDBusPendingReply<> setCursorRect(int x, int y, int w, int h);
QDBusPendingReply<> setSurroundingText(const QString &text, uint cursor, uint anchor);
QDBusPendingReply<> setSurroundingTextPosition(uint cursor, uint anchor);
inline QDBusPendingReply<> FocusOut()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("FocusOut"), argumentList);
}
signals:
void commitString(const QString &str);
void currentIM(const QString &name, const QString &uniqueName, const QString &langCode);
void deleteSurroundingText(int offset, uint nchar);
void forwardKey(uint keyval, uint state, bool isRelease);
void updateFormattedPreedit(const FcitxQtFormattedPreeditList &str, int cursorpos);
void inputContextCreated(const QByteArray &uuid);
inline QDBusPendingReply<bool> ProcessKeyEvent(uint keyval, uint keycode, uint state, bool type, uint time)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(keyval) << QVariant::fromValue(keycode) << QVariant::fromValue(state) << QVariant::fromValue(type) << QVariant::fromValue(time);
return asyncCallWithArgumentList(QStringLiteral("ProcessKeyEvent"), argumentList);
}
private:
inline QDBusPendingReply<> Reset()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("Reset"), argumentList);
}
inline QDBusPendingReply<> SetCapability(qulonglong caps)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(caps);
return asyncCallWithArgumentList(QStringLiteral("SetCapability"), argumentList);
}
inline QDBusPendingReply<> SetCursorRect(int x, int y, int w, int h)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(x) << QVariant::fromValue(y) << QVariant::fromValue(w) << QVariant::fromValue(h);
return asyncCallWithArgumentList(QStringLiteral("SetCursorRect"), argumentList);
}
inline QDBusPendingReply<> SetSurroundingText(const QString &text, uint cursor, uint anchor)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(text) << QVariant::fromValue(cursor) << QVariant::fromValue(anchor);
return asyncCallWithArgumentList(QStringLiteral("SetSurroundingText"), argumentList);
}
inline QDBusPendingReply<> SetSurroundingTextPosition(uint cursor, uint anchor)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(cursor) << QVariant::fromValue(anchor);
return asyncCallWithArgumentList(QStringLiteral("SetSurroundingTextPosition"), argumentList);
}
Q_SIGNALS: // SIGNALS
void CommitString(const QString &str);
void CurrentIM(const QString &name, const QString &uniqueName, const QString &langCode);
void DeleteSurroundingText(int offset, uint nchar);
void ForwardKey(uint keyval, uint state, bool type);
void UpdateFormattedPreedit(FcitxQtFormattedPreeditList str, int cursorpos);
FcitxQtInputContextProxyPrivate *const d_ptr;
Q_DECLARE_PRIVATE(FcitxQtInputContextProxy);
};
}
#endif
#endif // _DBUSADDONS_FCITXQTINPUTCONTEXTPROXY_H_

View File

@ -0,0 +1,171 @@
/*
* Copyright (C) 2017~2017 by CSSlayer
* wengxt@gmail.com
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; see the file COPYING. If not,
* see <http://www.gnu.org/licenses/>.
*/
#ifndef _DBUSADDONS_FCITXQTINPUTCONTEXTPROXY_P_H_
#define _DBUSADDONS_FCITXQTINPUTCONTEXTPROXY_P_H_
#include "fcitxqtinputcontextproxy.h"
#include "fcitxqtinputcontextproxyimpl.h"
#include "fcitxqtinputmethodproxy.h"
#include "fcitxqtwatcher.h"
#include <QDBusServiceWatcher>
namespace fcitx {
class FcitxQtInputContextProxyPrivate {
public:
FcitxQtInputContextProxyPrivate(FcitxQtWatcher *watcher,
FcitxQtInputContextProxy *q)
: q_ptr(q), m_fcitxWatcher(watcher), m_watcher(q) {
FcitxQtFormattedPreedit::registerMetaType();
FcitxQtInputContextArgument::registerMetaType();
QObject::connect(m_fcitxWatcher, &FcitxQtWatcher::availibilityChanged,
q, [this]() { availibilityChanged(); });
m_watcher.setWatchMode(QDBusServiceWatcher::WatchForUnregistration);
QObject::connect(&m_watcher, &QDBusServiceWatcher::serviceUnregistered,
q, [this]() { availibilityChanged(); });
availibilityChanged();
}
~FcitxQtInputContextProxyPrivate() {
if (isValid()) {
m_icproxy->DestroyIC();
}
}
bool isValid() const { return (m_icproxy && m_icproxy->isValid()); }
void availibilityChanged() {
QTimer::singleShot(100, q_ptr, [this]() { recheck(); });
}
void recheck() {
if (!isValid() && m_fcitxWatcher->availability()) {
createInputContext();
}
if (!m_fcitxWatcher->availability()) {
cleanUp();
}
}
void cleanUp() {
auto services = m_watcher.watchedServices();
for (const auto &service : services) {
m_watcher.removeWatchedService(service);
}
delete m_improxy;
m_improxy = nullptr;
delete m_icproxy;
m_icproxy = nullptr;
delete m_createInputContextWatcher;
m_createInputContextWatcher = nullptr;
}
void createInputContext() {
Q_Q(FcitxQtInputContextProxy);
if (!m_fcitxWatcher->availability()) {
return;
}
cleanUp();
auto service = m_fcitxWatcher->serviceName();
auto connection = m_fcitxWatcher->connection();
auto owner = connection.interface()->serviceOwner(service);
if (!owner.isValid()) {
return;
}
m_watcher.setConnection(connection);
m_watcher.setWatchedServices(QStringList() << owner);
// Avoid race, query again.
if (!connection.interface()->isServiceRegistered(owner)) {
cleanUp();
return;
}
QFileInfo info(QCoreApplication::applicationFilePath());
m_portal = true;
m_improxy =
new FcitxQtInputMethodProxy(owner, "/inputmethod", connection, q);
FcitxQtInputContextArgumentList list;
FcitxQtInputContextArgument arg;
arg.setName("program");
arg.setValue(info.fileName());
list << arg;
if (!m_display.isEmpty()) {
FcitxQtInputContextArgument arg2;
arg2.setName("display");
arg2.setValue(m_display);
list << arg2;
}
auto result = m_improxy->CreateInputContext(list);
m_createInputContextWatcher = new QDBusPendingCallWatcher(result);
QObject::connect(m_createInputContextWatcher,
&QDBusPendingCallWatcher::finished, q,
[this]() { createInputContextFinished(); });
}
void createInputContextFinished() {
Q_Q(FcitxQtInputContextProxy);
if (m_createInputContextWatcher->isError()) {
cleanUp();
return;
}
QDBusPendingReply<QDBusObjectPath, QByteArray> reply(
*m_createInputContextWatcher);
m_icproxy = new FcitxQtInputContextProxyImpl(
m_improxy->service(), reply.value().path(), m_improxy->connection(),
q);
QObject::connect(m_icproxy, &FcitxQtInputContextProxyImpl::CommitString,
q, &FcitxQtInputContextProxy::commitString);
QObject::connect(m_icproxy, &FcitxQtInputContextProxyImpl::CurrentIM, q,
&FcitxQtInputContextProxy::currentIM);
QObject::connect(m_icproxy,
&FcitxQtInputContextProxyImpl::DeleteSurroundingText,
q, &FcitxQtInputContextProxy::deleteSurroundingText);
QObject::connect(m_icproxy, &FcitxQtInputContextProxyImpl::ForwardKey,
q, &FcitxQtInputContextProxy::forwardKey);
QObject::connect(m_icproxy,
&FcitxQtInputContextProxyImpl::UpdateFormattedPreedit,
q, &FcitxQtInputContextProxy::updateFormattedPreedit);
delete m_createInputContextWatcher;
m_createInputContextWatcher = nullptr;
emit q->inputContextCreated(reply.argumentAt<1>());
}
FcitxQtInputContextProxy *q_ptr;
Q_DECLARE_PUBLIC(FcitxQtInputContextProxy);
FcitxQtWatcher *m_fcitxWatcher;
QDBusServiceWatcher m_watcher;
FcitxQtInputMethodProxy *m_improxy = nullptr;
FcitxQtInputContextProxyImpl *m_icproxy = nullptr;
QDBusPendingCallWatcher *m_createInputContextWatcher = nullptr;
QString m_display;
bool m_portal;
qulonglong m_capability;
};
}
#endif // _DBUSADDONS_FCITXQTINPUTCONTEXTPROXY_P_H_

View File

@ -0,0 +1,27 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was:
*
* qdbusxml2cpp is Copyright (C) 2016 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 "fcitxqtinputcontextproxyimpl.h"
namespace fcitx {
/*
* Implementation of interface class FcitxQtInputContextProxyImpl
*/
FcitxQtInputContextProxyImpl::FcitxQtInputContextProxyImpl(
const QString &service, const QString &path,
const QDBusConnection &connection, QObject *parent)
: QDBusAbstractInterface(service, path, staticInterfaceName(), connection,
parent) {}
FcitxQtInputContextProxyImpl::~FcitxQtInputContextProxyImpl() {}
}

View File

@ -0,0 +1,123 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was:
*
* qdbusxml2cpp is Copyright (C) 2016 The Qt Company Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
#ifndef FCITXQTINPUTCONTEXTPROXYIMPL_H
#define FCITXQTINPUTCONTEXTPROXYIMPL_H
#include "fcitx5qt5dbusaddons_export.h"
#include "fcitxqtdbustypes.h"
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QObject>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <QtDBus/QtDBus>
namespace fcitx {
/*
* Proxy class for interface org.fcitx.Fcitx.InputContext1
*/
class FcitxQtInputContextProxyImpl : public QDBusAbstractInterface {
Q_OBJECT
public:
static inline const char *staticInterfaceName() {
return "org.fcitx.Fcitx.InputContext1";
}
public:
FcitxQtInputContextProxyImpl(const QString &service, const QString &path,
const QDBusConnection &connection,
QObject *parent = nullptr);
~FcitxQtInputContextProxyImpl();
public Q_SLOTS: // METHODS
inline QDBusPendingReply<> DestroyIC() {
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("DestroyIC"),
argumentList);
}
inline QDBusPendingReply<> FocusIn() {
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("FocusIn"),
argumentList);
}
inline QDBusPendingReply<> FocusOut() {
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("FocusOut"),
argumentList);
}
inline QDBusPendingReply<bool> ProcessKeyEvent(uint keyval, uint keycode,
uint state, bool type,
uint time) {
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(keyval)
<< QVariant::fromValue(keycode)
<< QVariant::fromValue(state) << QVariant::fromValue(type)
<< QVariant::fromValue(time);
return asyncCallWithArgumentList(QStringLiteral("ProcessKeyEvent"),
argumentList);
}
inline QDBusPendingReply<> Reset() {
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("Reset"), argumentList);
}
inline QDBusPendingReply<> SetCapability(qulonglong caps) {
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(caps);
return asyncCallWithArgumentList(QStringLiteral("SetCapability"),
argumentList);
}
inline QDBusPendingReply<> SetCursorRect(int x, int y, int w, int h) {
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(x) << QVariant::fromValue(y)
<< QVariant::fromValue(w) << QVariant::fromValue(h);
return asyncCallWithArgumentList(QStringLiteral("SetCursorRect"),
argumentList);
}
inline QDBusPendingReply<> SetSurroundingText(const QString &text,
uint cursor, uint anchor) {
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(text) << QVariant::fromValue(cursor)
<< QVariant::fromValue(anchor);
return asyncCallWithArgumentList(QStringLiteral("SetSurroundingText"),
argumentList);
}
inline QDBusPendingReply<> SetSurroundingTextPosition(uint cursor,
uint anchor) {
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(cursor)
<< QVariant::fromValue(anchor);
return asyncCallWithArgumentList(
QStringLiteral("SetSurroundingTextPosition"), argumentList);
}
Q_SIGNALS: // SIGNALS
void CommitString(const QString &str);
void CurrentIM(const QString &name, const QString &uniqueName,
const QString &langCode);
void DeleteSurroundingText(int offset, uint nchar);
void ForwardKey(uint keyval, uint state, bool type);
void UpdateFormattedPreedit(FcitxQtFormattedPreeditList str, int cursorpos);
};
}
#endif

View File

@ -0,0 +1,149 @@
/***************************************************************************
* Copyright (C) 2011~2012 by CSSlayer *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include "fcitxqtwatcher_p.h"
#include <QDBusConnection>
#include <QDBusConnectionInterface>
#include <QDBusServiceWatcher>
#include <QDir>
namespace fcitx {
FcitxQtWatcher::FcitxQtWatcher(QObject *parent)
: QObject(parent), d_ptr(new FcitxQtWatcherPrivate(this)) {}
FcitxQtWatcher::FcitxQtWatcher(const QDBusConnection &connection,
QObject *parent)
: FcitxQtWatcher(parent) {
setConnection(connection);
}
FcitxQtWatcher::~FcitxQtWatcher() { delete d_ptr; }
bool FcitxQtWatcher::availability() const {
Q_D(const FcitxQtWatcher);
return d->m_availability;
}
void FcitxQtWatcher::setConnection(const QDBusConnection &connection) {
Q_D(FcitxQtWatcher);
return d->m_serviceWatcher.setConnection(connection);
}
QDBusConnection FcitxQtWatcher::connection() const {
Q_D(const FcitxQtWatcher);
return d->m_serviceWatcher.connection();
}
void FcitxQtWatcher::setWatchPortal(bool portal) {
Q_D(FcitxQtWatcher);
d->m_watchPortal = portal;
}
bool FcitxQtWatcher::watchPortal() const {
Q_D(const FcitxQtWatcher);
return d->m_watchPortal;
}
QString FcitxQtWatcher::serviceName() const {
Q_D(const FcitxQtWatcher);
if (d->m_mainPresent) {
return FCITX_MAIN_SERVICE_NAME;
}
if (d->m_portalPresent) {
return FCITX_PORTAL_SERVICE_NAME;
}
return QString();
}
void FcitxQtWatcher::setAvailability(bool availability) {
Q_D(FcitxQtWatcher);
if (d->m_availability != availability) {
d->m_availability = availability;
emit availibilityChanged(d->m_availability);
}
}
void FcitxQtWatcher::watch() {
Q_D(FcitxQtWatcher);
if (d->m_watched) {
return;
}
connect(&d->m_serviceWatcher, &QDBusServiceWatcher::serviceOwnerChanged,
this, &FcitxQtWatcher::imChanged);
d->m_serviceWatcher.addWatchedService(FCITX_MAIN_SERVICE_NAME);
if (d->m_watchPortal) {
d->m_serviceWatcher.addWatchedService(FCITX_PORTAL_SERVICE_NAME);
}
if (QDBusConnection::sessionBus().interface()->isServiceRegistered(
FCITX_MAIN_SERVICE_NAME)) {
d->m_mainPresent = true;
}
if (d->m_watchPortal &&
QDBusConnection::sessionBus().interface()->isServiceRegistered(
FCITX_PORTAL_SERVICE_NAME)) {
d->m_portalPresent = true;
}
updateAvailbility();
d->m_watched = true;
}
void FcitxQtWatcher::unwatch() {
Q_D(FcitxQtWatcher);
if (!d->m_watched) {
return;
}
disconnect(&d->m_serviceWatcher, &QDBusServiceWatcher::serviceOwnerChanged,
this, &FcitxQtWatcher::imChanged);
}
bool FcitxQtWatcher::isWatching() const {
Q_D(const FcitxQtWatcher);
return d->m_watched;
}
void FcitxQtWatcher::imChanged(const QString &service, const QString &,
const QString &newOwner) {
Q_D(FcitxQtWatcher);
if (service == FCITX_MAIN_SERVICE_NAME) {
if (!newOwner.isEmpty()) {
d->m_mainPresent = true;
} else {
d->m_mainPresent = false;
}
} else if (service == FCITX_PORTAL_SERVICE_NAME) {
if (!newOwner.isEmpty()) {
d->m_portalPresent = true;
} else {
d->m_portalPresent = false;
}
}
updateAvailbility();
}
void FcitxQtWatcher::updateAvailbility() {
Q_D(FcitxQtWatcher);
setAvailability(d->m_mainPresent || d->m_portalPresent);
}
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2017~2017 by CSSlayer
* wengxt@gmail.com
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; see the file COPYING. If not,
* see <http://www.gnu.org/licenses/>.
*/
#ifndef _DBUSADDONS_FCITXQTWATCHER_H_
#define _DBUSADDONS_FCITXQTWATCHER_H_
#include "fcitx5qt5dbusaddons_export.h"
#include <QDBusConnection>
#include <QObject>
namespace fcitx {
class FcitxQtWatcherPrivate;
class FCITX5QT5DBUSADDONS_EXPORT FcitxQtWatcher : public QObject {
Q_OBJECT
public:
explicit FcitxQtWatcher(QObject *parent = nullptr);
explicit FcitxQtWatcher(const QDBusConnection &connection,
QObject *parent = nullptr);
~FcitxQtWatcher();
void watch();
void unwatch();
void setConnection(const QDBusConnection &connection);
QDBusConnection connection() const;
void setWatchPortal(bool portal);
bool watchPortal() const;
bool isWatching() const;
bool availability() const;
QString serviceName() const;
signals:
void availibilityChanged(bool);
private slots:
void imChanged(const QString &service, const QString &oldOwner,
const QString &newOwner);
private:
void setAvailability(bool availability);
void updateAvailbility();
FcitxQtWatcherPrivate *const d_ptr;
Q_DECLARE_PRIVATE(FcitxQtWatcher);
};
}
#endif // _DBUSADDONS_FCITXQTWATCHER_H_

View File

@ -0,0 +1,43 @@
/*
* Copyright (C) 2017~2017 by CSSlayer
* wengxt@gmail.com
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; see the file COPYING. If not,
* see <http://www.gnu.org/licenses/>.
*/
#ifndef _DBUSADDONS_FCITXQTWATCHER_P_H_
#define _DBUSADDONS_FCITXQTWATCHER_P_H_
#include "fcitxqtwatcher.h"
#include <QDBusServiceWatcher>
#define FCITX_MAIN_SERVICE_NAME "org.fcitx.Fcitx5"
#define FCITX_PORTAL_SERVICE_NAME "org.freedesktop.portal.Fcitx"
namespace fcitx {
class FcitxQtWatcherPrivate {
public:
FcitxQtWatcherPrivate(FcitxQtWatcher *q) : m_serviceWatcher(q) {}
QDBusServiceWatcher m_serviceWatcher;
bool m_watchPortal = false;
bool m_availability = false;
bool m_mainPresent = false;
bool m_portalPresent = false;
bool m_watched = false;
};
}
#endif // _DBUSADDONS_FCITXQTWATCHER_P_H_

View File

@ -1,5 +1,5 @@
#!/bin/sh
qdbusxml2cpp-qt5 -N -p fcitxqtinputcontextproxy -c FcitxQtInputContextProxy interfaces/org.fcitx.Fcitx.InputContext1.xml -i fcitxqtdbustypes.h -i fcitx5qt5dbusaddons_export.h
qdbusxml2cpp-qt5 -N -p fcitxqtinputcontextproxyimpl -c FcitxQtInputContextProxyImpl interfaces/org.fcitx.Fcitx.InputContext1.xml -i fcitxqtdbustypes.h -i fcitx5qt5dbusaddons_export.h
qdbusxml2cpp-qt5 -N -p fcitxqtinputmethodproxy -c FcitxQtInputMethodProxy interfaces/org.fcitx.Fcitx.InputMethod1.xml -i fcitxqtdbustypes.h -i fcitx5qt5dbusaddons_export.h
qdbusxml2cpp-qt5 -N -p fcitxqtcontrollerproxy -c FcitxQtControllerProxy interfaces/org.fcitx.Fcitx.Controller1.xml -i fcitxqtdbustypes.h -i fcitx5qt5dbusaddons_export.h

View File

@ -26,16 +26,17 @@
#include "common.h"
#include "fcitxqtconfiguifactory.h"
#include "fcitxqtconnection.h"
#include "fcitxqtcontrollerproxy.h"
#include "fcitxqtwatcher.h"
#include "mainwindow.h"
namespace fcitx {
MainWindow::MainWindow(FcitxQtConfigUIWidget *pluginWidget, QWidget *parent)
: QMainWindow(parent), m_ui(new Ui::MainWindow),
m_connection(new FcitxQtConnection(this)), m_pluginWidget(pluginWidget),
m_watcher(new FcitxQtWatcher(this)), m_pluginWidget(pluginWidget),
m_proxy(0) {
m_watcher->setConnection(QDBusConnection::sessionBus());
m_ui->setupUi(this);
m_ui->verticalLayout->insertWidget(0, m_pluginWidget);
m_ui->buttonBox->button(QDialogButtonBox::Save)->setText(_("&Save"));
@ -52,18 +53,22 @@ MainWindow::MainWindow(FcitxQtConfigUIWidget *pluginWidget, QWidget *parent)
SLOT(saveFinished()));
connect(m_ui->buttonBox, SIGNAL(clicked(QAbstractButton *)), this,
SLOT(clicked(QAbstractButton *)));
connect(m_connection, SIGNAL(connected()), this, SLOT(connected()));
connect(m_watcher, &FcitxQtWatcher::availibilityChanged, this,
&MainWindow::availibilityChanged);
m_connection->startConnection();
m_watcher->watch();
}
void MainWindow::connected() {
void MainWindow::availibilityChanged(bool avail) {
if (!avail) {
return;
}
if (m_proxy) {
delete m_proxy;
}
m_proxy = new FcitxQtControllerProxy(m_connection->serviceName(),
m_proxy = new FcitxQtControllerProxy(m_watcher->serviceName(),
QLatin1String("/controller"),
*m_connection->connection(), this);
m_watcher->connection(), this);
}
void MainWindow::clicked(QAbstractButton *button) {

View File

@ -30,7 +30,7 @@
namespace fcitx {
class FcitxQtControllerProxy;
class FcitxQtConnection;
class FcitxQtWatcher;
class MainWindow : public QMainWindow {
Q_OBJECT
public:
@ -40,12 +40,12 @@ public:
public slots:
void changed(bool changed);
void clicked(QAbstractButton *button);
void connected();
void availibilityChanged(bool avail);
void saveFinished();
private:
Ui::MainWindow *m_ui;
FcitxQtConnection *m_connection;
FcitxQtWatcher *m_watcher;
FcitxQtConfigUIWidget *m_pluginWidget;
FcitxQtControllerProxy *m_proxy;
};

View File

@ -25,7 +25,6 @@
#include <QDebug>
#include "fcitxqtconfiguifactory.h"
#include "fcitxqtconnection.h"
#include "mainwindow.h"
#include "wrapperapp.h"
#include <fcitx-utils/standardpath.h>

View File

@ -36,9 +36,7 @@
#include "qtkey.h"
#include "fcitxqtconnection.h"
#include "fcitxqtinputcontextproxy.h"
#include "fcitxqtinputmethodproxy.h"
#include "qfcitxplatforminputcontext.h"
#include <fcitx-utils/key.h>
@ -147,7 +145,7 @@ struct xkb_context *_xkb_context_new_helper() {
}
QFcitxPlatformInputContext::QFcitxPlatformInputContext()
: m_connection(new FcitxQtConnection(this)), m_improxy(nullptr),
: m_watcher(new FcitxQtWatcher(QDBusConnection::sessionBus(), this)),
m_cursorPos(0), m_useSurroundingText(false),
m_syncMode(get_boolean_env("FCITX_QT_USE_SYNC", false)), m_destroy(false),
m_xkbContext(_xkb_context_new_helper()),
@ -161,46 +159,20 @@ QFcitxPlatformInputContext::QFcitxPlatformInputContext()
: 0) {
FcitxQtFormattedPreedit::registerMetaType();
FcitxQtInputContextArgument::registerMetaType();
connect(m_connection, &FcitxQtConnection::connected, this,
&QFcitxPlatformInputContext::connected);
connect(m_connection, &FcitxQtConnection::disconnected, this,
&QFcitxPlatformInputContext::cleanUp);
m_connection->startConnection();
m_watcher->setWatchPortal(true);
m_watcher->watch();
}
QFcitxPlatformInputContext::~QFcitxPlatformInputContext() {
m_destroy = true;
m_watcher->unwatch();
cleanUp();
}
void QFcitxPlatformInputContext::connected() {
if (!m_connection->isConnected())
return;
// qDebug() << "create Input Context" << m_connection->name();
if (m_improxy) {
delete m_improxy;
m_improxy = nullptr;
}
m_improxy = new FcitxQtInputMethodProxy(m_connection->serviceName(),
QLatin1String("/inputmethod"),
*m_connection->connection(), this);
QWindow *w = qApp->focusWindow();
if (w)
createICData(w);
delete m_watcher;
}
void QFcitxPlatformInputContext::cleanUp() {
m_icMap.clear();
if (m_improxy) {
delete m_improxy;
m_improxy = nullptr;
}
if (!m_destroy) {
commitPreedit();
}
@ -226,7 +198,6 @@ void QFcitxPlatformInputContext::commitPreedit(QPointer<QObject> input) {
e.setCommitString(m_commitPreedit);
QCoreApplication::sendEvent(input, &e);
m_commitPreedit.clear();
m_preeditList.clear();
}
@ -240,9 +211,9 @@ bool checkUtf8(const QByteArray &byteArray) {
void QFcitxPlatformInputContext::reset() {
commitPreedit();
FcitxQtInputContextProxy *proxy = validIC();
if (proxy)
proxy->Reset();
if (FcitxQtInputContextProxy *proxy = validIC()) {
proxy->reset();
}
if (m_xkbComposeState) {
xkb_compose_state_reset(m_xkbComposeState.data());
}
@ -255,7 +226,8 @@ void QFcitxPlatformInputContext::update(Qt::InputMethodQueries queries) {
if (!proxy)
return;
auto &data = m_icMap[window];
FcitxQtICData &data = *static_cast<FcitxQtICData *>(
proxy->property("icData").value<void *>());
QObject *input = qApp->focusObject();
if (!input)
@ -326,11 +298,11 @@ void QFcitxPlatformInputContext::update(Qt::InputMethodQueries queries) {
anchor = tempUCS4.size();
if (data.surroundingText != text) {
data.surroundingText = text;
proxy->SetSurroundingText(text, cursor, anchor);
proxy->setSurroundingText(text, cursor, anchor);
} else {
if (data.surroundingAnchor != anchor ||
data.surroundingCursor != cursor)
proxy->SetSurroundingTextPosition(cursor, anchor);
proxy->setSurroundingTextPosition(cursor, anchor);
}
data.surroundingCursor = cursor;
data.surroundingAnchor = anchor;
@ -353,7 +325,7 @@ void QFcitxPlatformInputContext::setFocusObject(QObject *object) {
FcitxQtInputContextProxy *proxy = validICByWindow(m_lastWindow);
commitPreedit(m_lastObject);
if (proxy) {
proxy->FocusOut();
proxy->focusOut();
}
QWindow *window = qApp->focusWindow();
@ -364,7 +336,7 @@ void QFcitxPlatformInputContext::setFocusObject(QObject *object) {
}
proxy = validICByWindow(window);
if (proxy)
proxy->FocusIn();
proxy->focusIn();
else {
createICData(window);
}
@ -384,7 +356,8 @@ void QFcitxPlatformInputContext::cursorRectChanged() {
if (!proxy)
return;
auto &data = m_icMap[inputWindow];
FcitxQtICData &data = *static_cast<FcitxQtICData *>(
proxy->property("icData").value<void *>());
QRect r = qApp->inputMethod()->cursorRectangle().toRect();
if (!r.isValid())
@ -404,111 +377,50 @@ void QFcitxPlatformInputContext::cursorRectChanged() {
if (data.rect != newRect) {
data.rect = newRect;
proxy->SetCursorRect(newRect.x(), newRect.y(), newRect.width(),
proxy->setCursorRect(newRect.x(), newRect.y(), newRect.width(),
newRect.height());
}
}
void QFcitxPlatformInputContext::createInputContext(QWindow *w) {
if (!m_connection->isConnected())
return;
// qDebug() << "create Input Context" << m_connection->connection()->name();
if (!m_improxy) {
m_improxy = new FcitxQtInputMethodProxy(
m_connection->serviceName(), QLatin1String("/inputmethod"),
*m_connection->connection(), this);
}
if (!m_improxy->isValid())
return;
QFileInfo info(QCoreApplication::applicationFilePath());
FcitxQtInputContextArgumentList args;
args << FcitxQtInputContextArgument("program", info.fileName());
if (QGuiApplication::platformName() == QLatin1String("xcb")) {
args << FcitxQtInputContextArgument("display", "x11:");
} else if (QGuiApplication::platformName() == QLatin1String("wayland")) {
args << FcitxQtInputContextArgument("display", "wayland:");
}
auto result = m_improxy->CreateInputContext(args);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(result);
watcher->setProperty("wid", qVariantFromValue(static_cast<void *>(w)));
connect(watcher, &QDBusPendingCallWatcher::finished, this,
&QFcitxPlatformInputContext::createInputContextFinished);
}
void QFcitxPlatformInputContext::createInputContextFinished(
QDBusPendingCallWatcher *watcher) {
auto w =
reinterpret_cast<QWindow *>(watcher->property("wid").value<void *>());
auto iter = m_icMap.find(w);
if (iter == m_icMap.end()) {
const QByteArray &uuid) {
auto proxy = qobject_cast<FcitxQtInputContextProxy *>(sender());
if (!proxy) {
return;
}
auto w =
reinterpret_cast<QWindow *>(proxy->property("wid").value<void *>());
FcitxQtICData *data =
static_cast<FcitxQtICData *>(proxy->property("icData").value<void *>());
data->rect = QRect();
auto &data = iter->second;
QDBusPendingReply<QDBusObjectPath, QByteArray> result = *watcher;
do {
if (result.isError()) {
break;
if (proxy->isValid()) {
QWindow *window = qApp->focusWindow();
if (window && window == w) {
proxy->focusIn();
cursorRectChanged();
}
setFocusGroupForX11(uuid);
}
if (!m_connection->isConnected())
break;
fcitx::CapabilityFlags flag;
flag |= fcitx::CapabilityFlag::Preedit;
flag |= fcitx::CapabilityFlag::FormattedPreedit;
flag |= fcitx::CapabilityFlag::ClientUnfocusCommit;
flag |= fcitx::CapabilityFlag::GetIMInfoOnFocus;
m_useSurroundingText =
get_boolean_env("FCITX_QT_ENABLE_SURROUNDING_TEXT", true);
if (m_useSurroundingText)
flag |= fcitx::CapabilityFlag::SurroundingText;
auto objectPath = result.argumentAt<0>();
if (data.proxy) {
delete data.proxy;
}
data.proxy = new FcitxQtInputContextProxy(
m_connection->serviceName(), objectPath.path(),
*m_connection->connection(), this);
data.proxy->setProperty("icData",
qVariantFromValue(static_cast<void *>(&data)));
connect(data.proxy, &FcitxQtInputContextProxy::CommitString, this,
&QFcitxPlatformInputContext::commitString);
connect(data.proxy, &FcitxQtInputContextProxy::ForwardKey, this,
&QFcitxPlatformInputContext::forwardKey);
connect(data.proxy, &FcitxQtInputContextProxy::UpdateFormattedPreedit,
this, &QFcitxPlatformInputContext::updateFormattedPreedit);
connect(data.proxy, &FcitxQtInputContextProxy::DeleteSurroundingText,
this, &QFcitxPlatformInputContext::deleteSurroundingText);
connect(data.proxy, &FcitxQtInputContextProxy::CurrentIM, this,
&QFcitxPlatformInputContext::updateCurrentIM);
if (data.proxy->isValid()) {
QWindow *window = qApp->focusWindow();
if (window && window == w)
data.proxy->FocusIn();
}
setFocusGroupForX11(result.argumentAt<1>());
fcitx::CapabilityFlags flag;
flag |= fcitx::CapabilityFlag::Preedit;
flag |= fcitx::CapabilityFlag::FormattedPreedit;
flag |= fcitx::CapabilityFlag::ClientUnfocusCommit;
flag |= fcitx::CapabilityFlag::GetIMInfoOnFocus;
m_useSurroundingText =
get_boolean_env("FCITX_QT_ENABLE_SURROUNDING_TEXT", true);
if (m_useSurroundingText)
flag |= fcitx::CapabilityFlag::SurroundingText;
addCapability(data, flag, true);
} while (0);
delete watcher;
addCapability(*data, flag, true);
}
void QFcitxPlatformInputContext::updateCapability(const FcitxQtICData &data) {
if (!data.proxy || !data.proxy->isValid())
return;
QDBusPendingReply<void> result =
data.proxy->SetCapability((uint)data.capability);
QDBusPendingReply<void> result = data.proxy->setCapability(data.capability);
}
void QFcitxPlatformInputContext::commitString(const QString &str) {
@ -676,12 +588,37 @@ QLocale QFcitxPlatformInputContext::locale() const { return m_locale; }
void QFcitxPlatformInputContext::createICData(QWindow *w) {
auto iter = m_icMap.find(w);
if (iter == m_icMap.end()) {
m_icMap.emplace(std::piecewise_construct, std::forward_as_tuple(w),
std::forward_as_tuple());
auto result =
m_icMap.emplace(std::piecewise_construct, std::forward_as_tuple(w),
std::forward_as_tuple(m_watcher));
connect(w, &QObject::destroyed, this,
&QFcitxPlatformInputContext::windowDestroyed);
iter = result.first;
auto &data = iter->second;
if (QGuiApplication::platformName() == QLatin1String("xcb")) {
data.proxy->setDisplay("x11:");
} else if (QGuiApplication::platformName() ==
QLatin1String("wayland")) {
data.proxy->setDisplay("wayland:");
}
data.proxy->setProperty("wid",
qVariantFromValue(static_cast<void *>(w)));
data.proxy->setProperty("icData",
qVariantFromValue(static_cast<void *>(&data)));
connect(data.proxy, &FcitxQtInputContextProxy::inputContextCreated,
this, &QFcitxPlatformInputContext::createInputContextFinished);
connect(data.proxy, &FcitxQtInputContextProxy::commitString, this,
&QFcitxPlatformInputContext::commitString);
connect(data.proxy, &FcitxQtInputContextProxy::forwardKey, this,
&QFcitxPlatformInputContext::forwardKey);
connect(data.proxy, &FcitxQtInputContextProxy::updateFormattedPreedit,
this, &QFcitxPlatformInputContext::updateFormattedPreedit);
connect(data.proxy, &FcitxQtInputContextProxy::deleteSurroundingText,
this, &QFcitxPlatformInputContext::deleteSurroundingText);
connect(data.proxy, &FcitxQtInputContextProxy::currentIM, this,
&QFcitxPlatformInputContext::updateCurrentIM);
}
createInputContext(w);
}
QKeyEvent *QFcitxPlatformInputContext::createKeyEvent(uint keyval, uint _state,
@ -714,9 +651,9 @@ QKeyEvent *QFcitxPlatformInputContext::createKeyEvent(uint keyval, uint _state,
int key = keysymToQtKey(keyval, text);
QKeyEvent *keyevent = new QKeyEvent(
isRelease ? (QEvent::KeyRelease) : (QEvent::KeyPress), key, qstate, 0,
keyval, _state, text, false, count);
QKeyEvent *keyevent =
new QKeyEvent(isRelease ? (QEvent::KeyRelease) : (QEvent::KeyPress),
key, qstate, 0, keyval, _state, text, false, count);
return keyevent;
}
@ -757,17 +694,16 @@ bool QFcitxPlatformInputContext::filterEvent(const QEvent *event) {
}
}
proxy->FocusIn();
proxy->focusIn();
auto reply =
proxy->ProcessKeyEvent(keyval, keycode, state, isRelease,
proxy->processKeyEvent(keyval, keycode, state, isRelease,
QDateTime::currentDateTime().toTime_t());
if (Q_UNLIKELY(m_syncMode)) {
reply.waitForFinished();
if (!m_connection->isConnected() || !reply.isFinished() ||
reply.isError() || !reply.value()) {
if (reply.isError() || !reply.value()) {
if (filterEventFallback(keyval, keycode, state, isRelease)) {
return true;
} else {
@ -779,7 +715,7 @@ bool QFcitxPlatformInputContext::filterEvent(const QEvent *event) {
}
} else {
ProcessKeyWatcher *watcher = new ProcessKeyWatcher(
*keyEvent, qApp->focusWindow(), reply, this);
*keyEvent, qApp->focusWindow(), reply, proxy);
connect(watcher, &QDBusPendingCallWatcher::finished, this,
&QFcitxPlatformInputContext::processKeyEventFinished);
return true;

View File

@ -21,6 +21,7 @@
#define QFCITXPLATFORMINPUTCONTEXT_H
#include "fcitxqtinputcontextproxy.h"
#include "fcitxqtwatcher.h"
#include <QDBusConnection>
#include <QDBusServiceWatcher>
#include <QGuiApplication>
@ -38,17 +39,11 @@ namespace fcitx {
class FcitxQtConnection;
struct FcitxQtICData {
FcitxQtICData()
: proxy(nullptr), surroundingAnchor(-1), surroundingCursor(-1) {}
FcitxQtICData(FcitxQtWatcher *watcher)
: proxy(new FcitxQtInputContextProxy(watcher, watcher)),
surroundingAnchor(-1), surroundingCursor(-1) {}
FcitxQtICData(const FcitxQtICData &that) = delete;
~FcitxQtICData() {
if (proxy) {
if (proxy->isValid()) {
proxy->DestroyIC();
}
delete proxy;
}
}
~FcitxQtICData() { delete proxy; }
fcitx::CapabilityFlags capability;
FcitxQtInputContextProxy *proxy;
QRect rect;
@ -101,8 +96,6 @@ struct XkbComposeStateDeleter {
}
};
class FcitxQtInputMethodProxy;
class QFcitxPlatformInputContext : public QPlatformInputContext {
Q_OBJECT
public:
@ -126,15 +119,13 @@ public Q_SLOTS:
int cursorPos);
void deleteSurroundingText(int offset, uint nchar);
void forwardKey(uint keyval, uint state, bool type);
void createInputContextFinished(QDBusPendingCallWatcher *watcher);
void connected();
void createInputContextFinished(const QByteArray &uuid);
void cleanUp();
void windowDestroyed(QObject *object);
void updateCurrentIM(const QString &name, const QString &uniqueName,
const QString &langCode);
private:
void createInputContext(QWindow *w);
bool processCompose(uint keyval, uint state, bool isRelaese);
QKeyEvent *createKeyEvent(uint keyval, uint state, bool isRelaese);
@ -165,8 +156,7 @@ private:
bool filterEventFallback(uint keyval, uint keycode, uint state,
bool isRelaese);
FcitxQtConnection *m_connection;
FcitxQtInputMethodProxy *m_improxy;
FcitxQtWatcher *m_watcher;
QString m_preedit;
QString m_commitPreedit;
FcitxQtFormattedPreeditList m_preeditList;