Files
tdesktop/Telegram/ThirdParty/fcitx5-qt/qt5/dbusaddons/fcitxqtinputcontextproxy_p.h
allhaileris afb81b8278
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
init
2026-02-16 15:50:16 +03:00

272 lines
9.8 KiB
C++

/*
* SPDX-FileCopyrightText: 2012~2017 CSSlayer <wengxt@gmail.com>
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef _DBUSADDONS_FCITXQTINPUTCONTEXTPROXY_P_H_
#define _DBUSADDONS_FCITXQTINPUTCONTEXTPROXY_P_H_
#include "fcitxqtinputcontextproxy.h"
#include "fcitxqtinputcontextproxyimpl.h"
#include "fcitxqtinputmethodproxy.h"
#include "fcitxqtwatcher.h"
#include <QDBusServiceWatcher>
#include <cstddef>
namespace fcitx {
class FcitxQtInputContextProxyPrivate {
public:
FcitxQtInputContextProxyPrivate(FcitxQtWatcher *watcher,
FcitxQtInputContextProxy *q)
: q_ptr(q), fcitxWatcher_(watcher), watcher_(q) {
registerFcitxQtDBusTypes();
QObject::connect(fcitxWatcher_, &FcitxQtWatcher::availabilityChanged, q,
[this]() { availabilityChanged(); });
watcher_.setWatchMode(QDBusServiceWatcher::WatchForUnregistration);
QObject::connect(&watcher_, &QDBusServiceWatcher::serviceUnregistered,
q, [this]() {
cleanUp();
availabilityChanged();
});
availabilityChanged();
}
~FcitxQtInputContextProxyPrivate() {
Q_Q(FcitxQtInputContextProxy);
if (isValid()) {
icproxy_->DestroyIC();
}
QObject::disconnect(
q, &FcitxQtInputContextProxy::virtualKeyboardVisibilityChanged,
nullptr, nullptr);
cleanUp();
}
bool isValid() const { return (icproxy_ && icproxy_->isValid()); }
void availabilityChanged() {
QTimer::singleShot(100, q_ptr, [this]() { recheck(); });
}
void recheck() {
if (!isValid() && fcitxWatcher_->availability()) {
createInputContext();
}
if (!fcitxWatcher_->availability()) {
cleanUp();
}
}
void cleanUp() {
auto services = watcher_.watchedServices();
for (const auto &service : services) {
watcher_.removeWatchedService(service);
}
delete improxy_;
improxy_ = nullptr;
delete icproxy_;
icproxy_ = nullptr;
delete createInputContextWatcher_;
createInputContextWatcher_ = nullptr;
delete introspectWatcher_;
introspectWatcher_ = nullptr;
delete queryWatcher_;
queryWatcher_ = nullptr;
setVirtualKeyboardVisible(false);
supportInvokeAction_ = false;
}
void createInputContext() {
Q_Q(FcitxQtInputContextProxy);
if (!fcitxWatcher_->availability()) {
return;
}
cleanUp();
auto service = fcitxWatcher_->serviceName();
auto connection = fcitxWatcher_->connection();
auto owner = connection.interface()->serviceOwner(service);
if (!owner.isValid()) {
return;
}
watcher_.setConnection(connection);
watcher_.setWatchedServices(QStringList() << owner);
// Avoid race, query again.
if (!connection.interface()->isServiceRegistered(owner)) {
cleanUp();
return;
}
QFileInfo info(QCoreApplication::applicationFilePath());
improxy_ = new FcitxQtInputMethodProxy(
owner, "/org/freedesktop/portal/inputmethod", connection, q);
FcitxQtStringKeyValueList list;
FcitxQtStringKeyValue arg;
arg.setKey("program");
arg.setValue(info.fileName());
list << arg;
if (!display_.isEmpty()) {
FcitxQtStringKeyValue arg2;
arg2.setKey("display");
arg2.setValue(display_);
list << arg2;
}
// Qt has good support for showing virtual keyboard, so we should
// disable the default behavior supported by fcitx5
FcitxQtStringKeyValue clientControlVirtualkeyboardShow;
clientControlVirtualkeyboardShow.setKey(
"clientControlVirtualkeyboardShow");
clientControlVirtualkeyboardShow.setValue("true");
list << clientControlVirtualkeyboardShow;
// Qt has poor support for hiding virtual keyboard, so we should enable
// the default behavior supported by fcitx5
FcitxQtStringKeyValue clientControlVirtualkeyboardHide;
clientControlVirtualkeyboardHide.setKey(
"clientControlVirtualkeyboardHide");
clientControlVirtualkeyboardHide.setValue("false");
list << clientControlVirtualkeyboardHide;
auto result = improxy_->CreateInputContext(list);
createInputContextWatcher_ = new QDBusPendingCallWatcher(result);
QObject::connect(createInputContextWatcher_,
&QDBusPendingCallWatcher::finished, q,
[this]() { createInputContextFinished(); });
}
void createInputContextFinished() {
Q_Q(FcitxQtInputContextProxy);
if (createInputContextWatcher_->isError()) {
cleanUp();
Q_EMIT q->inputContextCreationFailed();
return;
}
QDBusPendingReply<QDBusObjectPath, QByteArray> reply(
*createInputContextWatcher_);
icproxy_ = new FcitxQtInputContextProxyImpl(improxy_->service(),
reply.value().path(),
improxy_->connection(), q);
QObject::connect(icproxy_, &FcitxQtInputContextProxyImpl::CommitString,
q, &FcitxQtInputContextProxy::commitString);
QObject::connect(icproxy_, &FcitxQtInputContextProxyImpl::CurrentIM, q,
&FcitxQtInputContextProxy::currentIM);
QObject::connect(icproxy_,
&FcitxQtInputContextProxyImpl::DeleteSurroundingText,
q, &FcitxQtInputContextProxy::deleteSurroundingText);
QObject::connect(icproxy_, &FcitxQtInputContextProxyImpl::ForwardKey, q,
&FcitxQtInputContextProxy::forwardKey);
QObject::connect(icproxy_,
&FcitxQtInputContextProxyImpl::UpdateFormattedPreedit,
q, &FcitxQtInputContextProxy::updateFormattedPreedit);
QObject::connect(icproxy_,
&FcitxQtInputContextProxyImpl::UpdateClientSideUI, q,
&FcitxQtInputContextProxy::updateClientSideUI);
QObject::connect(icproxy_,
&FcitxQtInputContextProxyImpl::NotifyFocusOut, q,
&FcitxQtInputContextProxy::notifyFocusOut);
QObject::connect(
icproxy_,
&FcitxQtInputContextProxyImpl::VirtualKeyboardVisibilityChanged, q,
[this](bool visible) {
if (queryWatcher_) {
queryWatcher_->deleteLater();
queryWatcher_ = nullptr;
}
setVirtualKeyboardVisible(visible);
});
delete createInputContextWatcher_;
createInputContextWatcher_ = nullptr;
Q_EMIT q->inputContextCreated(reply.argumentAt<1>());
introspect();
virtualKeyboardVisibilityQuery();
}
void introspect() {
Q_Q(FcitxQtInputContextProxy);
if (introspectWatcher_) {
delete introspectWatcher_;
introspectWatcher_ = nullptr;
}
QDBusMessage call = QDBusMessage::createMethodCall(
icproxy_->service(), icproxy_->path(),
"org.freedesktop.DBus.Introspectable", "Introspect");
introspectWatcher_ = new QDBusPendingCallWatcher(
fcitxWatcher_->connection().asyncCall(call));
QObject::connect(introspectWatcher_, &QDBusPendingCallWatcher::finished,
q, [this]() { introspectFinished(); });
}
void introspectFinished() {
if (introspectWatcher_->isFinished() &&
!introspectWatcher_->isError()) {
QDBusPendingReply<QString> reply = *introspectWatcher_;
if (reply.value().contains("InvokeAction")) {
supportInvokeAction_ = true;
}
}
delete introspectWatcher_;
introspectWatcher_ = nullptr;
}
void virtualKeyboardVisibilityQuery() {
Q_Q(FcitxQtInputContextProxy);
if (queryWatcher_) {
delete queryWatcher_;
queryWatcher_ = nullptr;
}
queryWatcher_ =
new QDBusPendingCallWatcher(icproxy_->IsVirtualKeyboardVisible());
QObject::connect(
queryWatcher_, &QDBusPendingCallWatcher::finished, q,
[this]() { virtualKeyboardVisibilityQueryFinished(); });
}
void virtualKeyboardVisibilityQueryFinished() {
if (queryWatcher_ && queryWatcher_->isFinished() &&
!queryWatcher_->isError()) {
QDBusPendingReply<bool> reply = *queryWatcher_;
setVirtualKeyboardVisible(reply.value());
}
delete queryWatcher_;
queryWatcher_ = nullptr;
}
void setVirtualKeyboardVisible(bool visible) {
Q_Q(FcitxQtInputContextProxy);
if (isVirtualKeyboardVisible_ != visible) {
isVirtualKeyboardVisible_ = visible;
Q_EMIT q->virtualKeyboardVisibilityChanged(
isVirtualKeyboardVisible_);
}
}
FcitxQtInputContextProxy *q_ptr;
Q_DECLARE_PUBLIC(FcitxQtInputContextProxy);
FcitxQtWatcher *fcitxWatcher_;
QDBusServiceWatcher watcher_;
FcitxQtInputMethodProxy *improxy_ = nullptr;
FcitxQtInputContextProxyImpl *icproxy_ = nullptr;
bool isVirtualKeyboardVisible_ = false;
bool supportInvokeAction_ = false;
QDBusPendingCallWatcher *createInputContextWatcher_ = nullptr;
QDBusPendingCallWatcher *introspectWatcher_ = nullptr;
QDBusPendingCallWatcher *queryWatcher_ = nullptr;
QString display_;
};
} // namespace fcitx
#endif // _DBUSADDONS_FCITXQTINPUTCONTEXTPROXY_P_H_