Skip to content

Commit

Permalink
allow client-only architecture (#71)
Browse files Browse the repository at this point in the history
Co-authored-by: Weng Xuetian <[email protected]>
  • Loading branch information
eagleoflqj and wengxt authored Dec 24, 2024
1 parent 2358d1e commit e191411
Show file tree
Hide file tree
Showing 18 changed files with 638 additions and 227 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/fcitx.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ jobs:
fail-fast: false
matrix:
compiler: [gcc, clang]
use_server: [true, false]
include:
- compiler: gcc
cxx_compiler: g++
Expand All @@ -50,8 +51,7 @@ jobs:
uses: actions/cache@v4
with:
path: 'fcitx5/**/*.tar.*'
key: ${{ runner.os }}-${{ hashFiles('fcitx5/src/modules/spell/CMakeLists.txt')
}}
key: ${{ runner.os }}-${{ hashFiles('fcitx5/src/modules/spell/CMakeLists.txt')}}
- name: Build and Install fcitx5
uses: fcitx/github-actions@cmake
with:
Expand All @@ -69,5 +69,5 @@ jobs:
run: |
cd mozc/src/
chown -R builduser:builduser .
_BUILD_TARGETS=unix/fcitx5:fcitx5-mozc.so sudo -u builduser ../scripts/build_fcitx5_bazel --cxxopt=-Wno-uninitialized --host_cxxopt=-Wno-uninitialized --linkopt=-L/opt/fcitx/lib
_BUILD_TARGETS=unix/fcitx5:fcitx5-mozc.so sudo -u builduser ../scripts/build_fcitx5_bazel --//unix/fcitx5:use_server=${{ matrix.use_server }} --cxxopt=-Wno-uninitialized --host_cxxopt=-Wno-uninitialized --linkopt=-L/opt/fcitx/lib
chown -R root:root .
2 changes: 1 addition & 1 deletion scripts/build_fcitx5_bazel
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

_BUILD_TARGETS="${_BUILD_TARGETS:-unix/fcitx5:fcitx5-mozc.so server:mozc_server gui/tool:mozc_tool}"

bazel build -c opt --copt=-fPIC --config oss_linux "$@" $_BUILD_TARGETS
bazel build -c opt --copt=-fPIC --config oss_linux --define server=1 "$@" $_BUILD_TARGETS
92 changes: 76 additions & 16 deletions src/unix/fcitx5/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
load(
"//:build_defs.bzl",
"mozc_cc_binary",
Expand All @@ -6,32 +7,86 @@ load(

package(default_visibility = ["//:__subpackages__"])

bool_flag(
name = "use_server",
build_setting_default = True,
)

config_setting(
name = "without_server",
flag_values = {
":use_server": "False",
},
)

mozc_cc_library(
name = "mozc_connection",
srcs = ["mozc_connection.cc"],
hdrs = ["mozc_connection.h"],
name = "mozc_client_interface",
hdrs = [
"mozc_client_interface.h",
],
deps = [
":fcitx_key_util",
":surrounding_text_util",
"//base:port",
"//base:util",
"//base:vlog",
"//client",
"//protocol:commands_cc_proto",
"//protocol:config_cc_proto",
],
)

mozc_cc_library(
name = "mozc_client_pool",
srcs = ["mozc_client_pool.cc"],
hdrs = ["mozc_client_pool.h"],
srcs = [
"mozc_client_pool.cc",
],
hdrs = [
"mozc_client_pool.h",
],
deps = [
":mozc_connection",
"//client:client_interface",
":mozc_client_interface",
"//protocol:commands_cc_proto",
"//protocol:config_cc_proto",
"@fcitx5",
],
)

mozc_cc_library(
name = "mozc_direct_client",
srcs = [
"mozc_direct_client.cc",
],
hdrs = [
"mozc_direct_client.h",
],
deps = [
":mozc_client_interface",
"//base:singleton",
"//base:vlog",
"//config:config_handler",
"//engine:engine_factory",
"//protocol:commands_cc_proto",
"//protocol:config_cc_proto",
"//session:key_info_util",
"//session:session_handler",
"//session:session_handler_interface",
"//session:session_usage_observer",
"@com_google_absl//absl/log",
],
)

mozc_cc_library(
name = "mozc_ipc_client",
srcs = [
"mozc_ipc_client.cc",
],
hdrs = [
"mozc_ipc_client.h",
],
deps = [
":mozc_client_interface",
"//client",
"//ipc",
"//protocol:commands_cc_proto",
"//protocol:config_cc_proto",
],
)

mozc_cc_library(
name = "i18nwrapper",
hdrs = [
Expand All @@ -58,19 +113,24 @@ mozc_cc_library(
":fcitx_key_util",
":i18nwrapper",
":mozc_client_pool",
":mozc_connection",
":surrounding_text_util",
"//base:init_mozc",
"//base:port",
"//base:process",
"//base:run_level",
"//base:util",
"//base:vlog",
"//client:client_interface",
"//protocol:candidate_window_cc_proto",
"//protocol:commands_cc_proto",
"@fcitx5",
],
] + select({
":without_server": [
":mozc_direct_client",
],
"//conditions:default": [
":mozc_ipc_client",
],
}),
)

mozc_cc_library(
Expand Down
1 change: 1 addition & 0 deletions src/unix/fcitx5/fcitx_key_event_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <cstdint>
#include <memory>
#include <set>
#include <string>

#include "protocol/commands.pb.h"
#include "protocol/config.pb.h"
Expand Down
44 changes: 44 additions & 0 deletions src/unix/fcitx5/mozc_client_interface.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#ifndef UNIX_FCITX5_MOZC_CLIENT_INTERFACE_H_
#define UNIX_FCITX5_MOZC_CLIENT_INTERFACE_H_

#include <memory>
#include <string>
#include <string_view>

#include "protocol/commands.pb.h"
#include "protocol/config.pb.h"

namespace fcitx {

// This is a simplified version of mozc::ClientInterface, with only functions
// Needed by Fcitx.
class MozcClientInterface {
public:
virtual ~MozcClientInterface() = default;
virtual bool EnsureConnection() = 0;
bool SendCommand(const mozc::commands::SessionCommand &command,
mozc::commands::Output *output) {
return SendCommandWithContext(
command, mozc::commands::Context::default_instance(), output);
}
virtual bool SendKeyWithContext(const mozc::commands::KeyEvent &key,
const mozc::commands::Context &context,
mozc::commands::Output *output) = 0;
virtual bool SendCommandWithContext(
const mozc::commands::SessionCommand &command,
const mozc::commands::Context &context,
mozc::commands::Output *output) = 0;
virtual bool IsDirectModeCommand(
const mozc::commands::KeyEvent &key) const = 0;
virtual bool GetConfig(mozc::config::Config *config) = 0;
virtual void set_client_capability(
const mozc::commands::Capability &capability) = 0;
virtual bool SyncData() = 0;
virtual bool LaunchTool(const std::string &mode, std::string_view arg) = 0;
virtual bool LaunchToolWithProtoBuf(const mozc::commands::Output &output) = 0;
};

std::unique_ptr<MozcClientInterface> createClient();

} // namespace fcitx
#endif
49 changes: 26 additions & 23 deletions src/unix/fcitx5/mozc_client_pool.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,15 @@
#include <cassert>
#include <memory>
#include <string>
#include <utility>

#include "unix/fcitx5/mozc_connection.h"
#include "protocol/commands.pb.h"
#include "unix/fcitx5/mozc_client_interface.h"

namespace fcitx {

MozcClientHolder::~MozcClientHolder() {
if (pool_) {
pool_->unregisterClient(key_);
}
}

MozcClientPool::MozcClientPool(MozcConnection *connection,
PropertyPropagatePolicy initialPolicy)
: connection_(connection), policy_(initialPolicy) {}
MozcClientPool::MozcClientPool(PropertyPropagatePolicy initialPolicy)
: policy_(initialPolicy) {}

void MozcClientPool::setPolicy(PropertyPropagatePolicy policy) {
if (policy_ == policy) {
Expand All @@ -73,7 +68,7 @@ std::string uuidKey(InputContext *ic) {
return key;
}

std::shared_ptr<MozcClientHolder> MozcClientPool::requestClient(
std::shared_ptr<MozcClientInterface> MozcClientPool::requestClient(
InputContext *ic) {
std::string key;
switch (policy_) {
Expand All @@ -95,26 +90,34 @@ std::shared_ptr<MozcClientHolder> MozcClientPool::requestClient(
if (iter != clients_.end()) {
return iter->second.lock();
}
auto newclient = std::make_shared<MozcClientHolder>();
registerClient(key, newclient);
return newclient;
std::unique_ptr<MozcClientInterface> newclient = createClient();
// Currently client capability is fixed.
mozc::commands::Capability capability;
capability.set_text_deletion(
mozc::commands::Capability::DELETE_PRECEDING_TEXT);
newclient->set_client_capability(capability);
return registerClient(key, std::move(newclient));
}

void MozcClientPool::registerClient(const std::string &key,
std::shared_ptr<MozcClientHolder> client) {
std::shared_ptr<MozcClientInterface> MozcClientPool::registerClient(
const std::string &key, std::unique_ptr<MozcClientInterface> client) {
assert(!key.empty());
client->pool_ = this;
client->client_ = connection_->CreateClient();
client->key_ = key;
auto [_, success] = clients_.emplace(key, client);
std::shared_ptr<MozcClientInterface> managedClient(
client.release(),
[key, ref = this->watch()](MozcClientInterface *client) {
if (auto *that = ref.get()) {
that->unregisterClient(key);
}
delete client;
});
const auto [iter, success] = clients_.emplace(key, managedClient);
FCITX_UNUSED(success);
assert(success);
return managedClient;
}

void MozcClientPool::unregisterClient(const std::string &key) {
auto count = clients_.erase(key);
FCITX_UNUSED(count);
assert(count > 0);
clients_.erase(key);
}

} // namespace fcitx
42 changes: 9 additions & 33 deletions src/unix/fcitx5/mozc_client_pool.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,59 +30,35 @@
#ifndef UNIX_FCITX5_MOZC_CLIENT_POOL_H_
#define UNIX_FCITX5_MOZC_CLIENT_POOL_H_

#include <fcitx-utils/trackableobject.h>
#include <fcitx/inputcontext.h>
#include <fcitx/inputcontextmanager.h>

#include <memory>
#include <string>
#include <unordered_map>

#include "client/client_interface.h"
#include "unix/fcitx5/mozc_connection.h"
#include "unix/fcitx5/mozc_client_interface.h"

namespace fcitx {

class MozcClientPool;

class MozcClientHolder {
friend class MozcClientPool;
class MozcClientPool : public TrackableObject<MozcClientPool> {
friend class MozcClientInterface;

public:
MozcClientHolder() = default;

MozcClientHolder(MozcClientHolder &&) = delete;

~MozcClientHolder();

mozc::client::ClientInterface *client() const { return client_.get(); }

private:
MozcClientPool *pool_;
std::unique_ptr<mozc::client::ClientInterface> client_;
std::string key_;
};

class MozcClientPool {
friend class MozcClientHolder;

public:
MozcClientPool(MozcConnection *connection,
PropertyPropagatePolicy initialPolicy);
MozcClientPool(PropertyPropagatePolicy initialPolicy);

void setPolicy(PropertyPropagatePolicy policy);
PropertyPropagatePolicy policy() const { return policy_; }

std::shared_ptr<MozcClientHolder> requestClient(InputContext *ic);

MozcConnection *connection() const { return connection_; }
std::shared_ptr<MozcClientInterface> requestClient(InputContext *ic);

private:
void registerClient(const std::string &key,
std::shared_ptr<MozcClientHolder> client);
std::shared_ptr<MozcClientInterface> registerClient(
const std::string &key, std::unique_ptr<MozcClientInterface> client);
void unregisterClient(const std::string &key);
MozcConnection *connection_;
PropertyPropagatePolicy policy_;
std::unordered_map<std::string, std::weak_ptr<MozcClientHolder>> clients_;
std::unordered_map<std::string, std::weak_ptr<MozcClientInterface>> clients_;
};

} // namespace fcitx
Expand Down
Loading

0 comments on commit e191411

Please sign in to comment.