Skip to content

Commit

Permalink
bundle conf and load addons (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
eagleoflqj authored Jan 6, 2025
1 parent e1ac800 commit 3d4bbda
Show file tree
Hide file tree
Showing 14 changed files with 201 additions and 34 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ jobs:
hvigorw -v
hvigorw clean --no-daemon
hvigorw assembleHap --mode module -p product=default --parallel --no-daemon
hvigorw assembleHap --mode module -p product=default --parallel --no-daemon # bundle generated resfile
mv entry/build/default/outputs/default/entry-default-unsigned.hap fcitx5-harmony-${{ matrix.arch }}.hap
- name: Upload artifact
Expand Down
15 changes: 10 additions & 5 deletions entry/src/main/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
cmake_minimum_required(VERSION 3.24)
project(fcitx5-harmony)
project(fcitx5-harmony VERSION 0.1.0)

set(CMAKE_CXX_STANDARD 17)

set(PREBUILT_DIR "${PROJECT_SOURCE_DIR}/prebuilt/${OHOS_ARCH}")
set(CMAKE_INSTALL_PREFIX "/usr")

# fcitx5-harmony/entry/.cxx/default/default/debug/hvigor/x86_64
# fcitx5-harmony/entry/.cxx/default/default/debug/hvigor/x86_64 this is also PROJECT_BINARY_DIR
# C:/Program Files/Huawei/DevEco Studio/sdk/default/openharmony/native
# C:/Program Files/Huawei/DevEco Studio/sdk/default/hms/native/sysroot/usr
list(APPEND CMAKE_FIND_ROOT_PATH "${PREBUILT_DIR}")
Expand Down Expand Up @@ -34,12 +35,16 @@ option(ENABLE_LIBUUID "" OFF)
option(BUILD_SPELL_DICT "" OFF)
add_subdirectory(fcitx5)

add_subdirectory(harmonyfrontend)
add_subdirectory(src)

add_library(entry SHARED napi_init.cpp)
target_include_directories(entry PRIVATE src)
target_link_libraries(entry PRIVATE fcitx)
target_link_libraries(entry PUBLIC
libace_napi.z.so
libhilog_ndk.z.so
target_link_libraries(entry PUBLIC libace_napi.z.so)

# XXX: This won't be bundled into HAP for the first run of hvigorw assembleHap.
add_custom_command(TARGET entry
POST_BUILD COMMAND
node "${PROJECT_SOURCE_DIR}/../../../../scripts/postbuild.mjs" "${PROJECT_SOURCE_DIR}/../resources/resfile" "${PROJECT_BINARY_DIR}"
)
6 changes: 6 additions & 0 deletions entry/src/main/cpp/harmonyfrontend/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
add_library(harmonyfrontend STATIC harmonyfrontend.cpp)
target_link_libraries(harmonyfrontend Fcitx5::Core)

configure_file(harmonyfrontend.conf.in.in harmonyfrontend.conf.in @ONLY)
fcitx5_translate_desktop_file(${CMAKE_CURRENT_BINARY_DIR}/harmonyfrontend.conf.in harmonyfrontend.conf)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/harmonyfrontend.conf DESTINATION "${CMAKE_INSTALL_PREFIX}/share/fcitx5/addon" COMPONENT config)
7 changes: 7 additions & 0 deletions entry/src/main/cpp/harmonyfrontend/harmonyfrontend.conf.in.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[Addon]
Name=Harmony Frontend
Type=StaticLibrary
Library=libharmonyfrontend
Category=Frontend
Version=@PROJECT_VERSION@
Configurable=False
41 changes: 41 additions & 0 deletions entry/src/main/cpp/harmonyfrontend/harmonyfrontend.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include "harmonyfrontend.h"

namespace fcitx {
HarmonyFrontend::HarmonyFrontend(Instance *instance)
: instance_(instance), focusGroup_("harmony", instance->inputContextManager()) {
createInputContext();
}

void HarmonyFrontend::createInputContext() {
ic_ = new HarmonyInputContext(this, instance_->inputContextManager());
ic_->setFocusGroup(&focusGroup_);
}

bool HarmonyFrontend::keyEvent(const Key &key, bool isRelease) {
KeyEvent event(ic_, key, isRelease);
ic_->keyEvent(event);
return event.accepted();
}

void HarmonyFrontend::focusIn() { ic_->focusIn(); }

void HarmonyFrontend::focusOut() { ic_->focusOut(); }

HarmonyInputContext::HarmonyInputContext(HarmonyFrontend *frontend, InputContextManager &inputContextManager)
: InputContext(inputContextManager, ""), frontend_(frontend) {
CapabilityFlags flags = CapabilityFlag::Preedit;
setCapabilityFlags(flags);
created();
}

HarmonyInputContext::~HarmonyInputContext() { destroy(); }

void HarmonyInputContext::commitStringImpl(const std::string &text) { FCITX_ERROR() << "commit " << text; }

void HarmonyInputContext::updatePreeditImpl() {
auto preedit = frontend_->instance()->outputFilter(this, inputPanel().clientPreedit());
FCITX_ERROR() << "setPreedit " << preedit.toString() << preedit.cursor();
}
} // namespace fcitx

FCITX_ADDON_FACTORY_V2(harmonyfrontend, fcitx::HarmonyFrontendFactory);
53 changes: 53 additions & 0 deletions entry/src/main/cpp/harmonyfrontend/harmonyfrontend.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#pragma once

#include <fcitx-config/configuration.h>
#include <fcitx/addonfactory.h>
#include <fcitx/addoninstance.h>
#include <fcitx/addonmanager.h>
#include <fcitx/focusgroup.h>
#include <fcitx/instance.h>

namespace fcitx {
class HarmonyInputContext;

class HarmonyFrontend : public AddonInstance {
public:
HarmonyFrontend(Instance *instance);
Instance *instance() { return instance_; }

void reloadConfig() override {}
void save() override {}
const Configuration *getConfig() const override { return nullptr; }
void setConfig(const RawConfig &config) override {}

void createInputContext();
bool keyEvent(const Key &key, bool isRelease);
void focusIn();
void focusOut();

private:
Instance *instance_;
FocusGroup focusGroup_;
HarmonyInputContext *ic_;
};

class HarmonyFrontendFactory : public AddonFactory {
public:
AddonInstance *create(AddonManager *manager) override { return new HarmonyFrontend(manager->instance()); }
};

class HarmonyInputContext : public InputContext {
public:
HarmonyInputContext(HarmonyFrontend *frontend, InputContextManager &inputContextManager);
~HarmonyInputContext();

const char *frontend() const override { return "harmony"; }
void commitStringImpl(const std::string &text) override;
void deleteSurroundingTextImpl(int offset, unsigned int size) override {}
void forwardKeyImpl(const ForwardKeyEvent &key) override {}
void updatePreeditImpl() override;

private:
HarmonyFrontend *frontend_;
};
} // namespace fcitx
39 changes: 17 additions & 22 deletions entry/src/main/cpp/napi_init.cpp
Original file line number Diff line number Diff line change
@@ -1,35 +1,30 @@
#include "napi/native_api.h"
#include "fcitx.h"
#include <string>

static napi_value Add(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value args[2] = {nullptr};

#define GET_ARGS(n) \
size_t argc = n; \
napi_value args[n] = {nullptr}; \
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

napi_valuetype valuetype0;
napi_typeof(env, args[0], &valuetype0);

napi_valuetype valuetype1;
napi_typeof(env, args[1], &valuetype1);

double value0;
napi_get_value_double(env, args[0], &value0);

double value1;
napi_get_value_double(env, args[1], &value1);

napi_value sum;
napi_create_double(env, value0 + value1, &sum);

return sum;
#define GET_STRING(name, i) \
size_t len##i; \
napi_get_value_string_utf8(env, args[i], nullptr, 0, &len##i); \
std::string name(len##i, '\0'); \
napi_get_value_string_utf8(env, args[i], name.data(), len##i + 1, &len##i);

static napi_value init(napi_env env, napi_callback_info info) {
GET_ARGS(2)
GET_STRING(bundle, 0)
GET_STRING(resfile, 1)
fcitx::init(bundle, resfile);
return {};
}

EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
napi_property_descriptor desc[] = {{"add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr}};
napi_property_descriptor desc[] = {{"init", nullptr, init, nullptr, nullptr, nullptr, napi_default, nullptr}};
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
fcitx::init();
return exports;
}
EXTERN_C_END
Expand Down
9 changes: 7 additions & 2 deletions entry/src/main/cpp/src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
add_library(fcitx STATIC
add_library(fcitx SHARED
fcitx.cpp
)
target_link_libraries(fcitx Fcitx5::Core)
target_link_libraries(fcitx Fcitx5::Core libhilog_ndk.z.so)

fcitx5_import_addons(fcitx
REGISTRY_VARNAME getStaticAddon
ADDONS harmonyfrontend
)
38 changes: 35 additions & 3 deletions entry/src/main/cpp/src/fcitx.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
#include <fcitx-utils/event.h>
#include <fcitx-utils/eventdispatcher.h>
#include <fcitx-utils/standardpath.h>
#include <fcitx/addonmanager.h>
#include <fcitx/instance.h>
#include <thread>
#include <sys/stat.h>
#include <filesystem>
#include "nativestreambuf.h"
#include "../harmonyfrontend/harmonyfrontend.h"

#ifdef __x86_64__
#define ARCH "x86_64"
#elif defined(__aarch64__)
#define ARCH "arm64-v8a"
#endif

namespace fs = std::filesystem;

FCITX_DEFINE_STATIC_ADDON_REGISTRY(getStaticAddon)

namespace fcitx {
std::unique_ptr<Instance> instance;
std::unique_ptr<fcitx::EventDispatcher> dispatcher;
HarmonyFrontend *frontend;

static native_streambuf log_streambuf;
static std::ostream stream(&log_streambuf);
Expand All @@ -20,14 +34,32 @@ void setupLog() {
fcitx::Log::setLogRule("*=5,notimedate");
}

void init() {
umask(007);
StandardPath::global().syncUmask();
void setupEnv(const std::string &bundle, const std::string &resfile) {
// resfile is /data/storage/el1/bundle/entry/resources/resfile
::fs::path bundlePath = bundle;
::fs::path resfilePath = resfile;
std::string fcitx_addon_dirs = bundlePath / "libs" / ARCH;
setenv("FCITX_ADDON_DIRS", fcitx_addon_dirs.c_str(), 1);
::fs::path xdg_data_dirs = resfilePath / "usr" / "share";
std::string fcitx_data_dirs = xdg_data_dirs / "fcitx5";
setenv("XDG_DATA_DIRS", xdg_data_dirs.c_str(), 1);
setenv("FCITX_DATA_DIRS", fcitx_data_dirs.c_str(), 1);
}

void init(const std::string &bundle, const std::string &resfile) {
setupLog();
setupEnv(bundle, resfile);
// f5a and f5j need it. Not sure if f5h needs it but just do it.
umask(007);
StandardPath::global().syncUmask(); // Must happen after setupEnv.

instance = std::make_unique<Instance>(0, nullptr);
auto &addonMgr = instance->addonManager();
addonMgr.registerDefaultLoader(&getStaticAddon());
instance->initialize();
dispatcher = std::make_unique<fcitx::EventDispatcher>();
dispatcher->attach(&instance->eventLoop());
fcitx_thread = std::thread([] { instance->eventLoop().exec(); });
frontend = dynamic_cast<HarmonyFrontend *>(addonMgr.addon("harmonyfrontend"));
}
} // namespace fcitx
4 changes: 3 additions & 1 deletion entry/src/main/cpp/src/fcitx.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include <string>

namespace fcitx {
void init();
void init(const std::string &bundle, const std::string &resfile);
}
2 changes: 1 addition & 1 deletion entry/src/main/cpp/types/libentry/Index.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const add: (a: number, b: number) => number;
export const init: (bundle: string, resfile: string) => void;
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { InputMethodExtensionAbility } from "@kit.IMEKit";
import type Want from "@ohos.app.ability.Want";
import keyboardController from "./model/KeyboardController";
import fcitx from 'libentry.so';

export default class FcitxInputMethodService extends InputMethodExtensionAbility {
onCreate(want: Want): void {
keyboardController.onCreate(this.context)
const bundle = this.context.bundleCodeDir
const resfile = this.context.resourceDir
fcitx.init(bundle, resfile)
}

onDestroy(): void {
Expand Down
1 change: 1 addition & 0 deletions entry/src/main/resources/resfile/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
usr
15 changes: 15 additions & 0 deletions scripts/postbuild.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { spawnSync } from 'child_process'
import path from 'path'

const [destDir, buildDir] = process.argv.slice(2)

const env = { ...process.env, DESTDIR: path.resolve(destDir) }
const result = spawnSync('cmake', ['--install', buildDir, '--component', 'config'], {
env,
stdio: 'inherit',
shell: true
})

if (result.error || result.status !== 0) {
exit(1)
}

0 comments on commit 3d4bbda

Please sign in to comment.