diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b4e1ee..54e6bd8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,8 @@ set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS TRUE) set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-sSIDE_MODULE") set(CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS "-sSIDE_MODULE") add_compile_options(-fPIC -fexceptions) +# createDefaultEventLoop is called by libFcitx5Utils.so but implemented in event_js.cpp. +add_link_options(-sERROR_ON_UNDEFINED_SYMBOLS=0) set(PREBUILDER_LIB_DIR "${PROJECT_BINARY_DIR}/sysroot/usr/lib") set(PREBUILDER_SHARE_DIR "${PROJECT_BINARY_DIR}/sysroot/usr/share") diff --git a/fcitx5 b/fcitx5 index 717034c..e2dcfcb 160000 --- a/fcitx5 +++ b/fcitx5 @@ -1 +1 @@ -Subproject commit 717034ced24ff6df23c2b1e82704b2f853ddc3f0 +Subproject commit e2dcfcbf3590dc42427b4537a9c1eeeef8d82743 diff --git a/fcitx5-webview b/fcitx5-webview index 94aff6d..d994567 160000 --- a/fcitx5-webview +++ b/fcitx5-webview @@ -1 +1 @@ -Subproject commit 94aff6d4b759902e608f6bbdb3bcef1cb0f34e28 +Subproject commit d9945672a16dac4b003423ccb0818c246ab3fa42 diff --git a/patches/fcitx5.patch b/patches/fcitx5.patch index f8110db..42dff47 100644 --- a/patches/fcitx5.patch +++ b/patches/fcitx5.patch @@ -1,16 +1,3 @@ -diff --git a/CMakeLists.txt b/CMakeLists.txt -index aa90bad4..b4641520 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -70,7 +70,7 @@ if (NOT TARGET Systemd::Systemd) - pkg_get_variable(DBUS_SYSTEM_BUS_DEFAULT_ADDRESS "dbus-1" "system_bus_default_address") - endif() - -- if (NOT LIBUV_TARGET) -+ if (NOT LIBUV_TARGET AND NOT EMSCRIPTEN) - if (NOT (TARGET PkgConfig::LibUV)) - pkg_check_modules(LibUV REQUIRED IMPORTED_TARGET "libuv") - endif() diff --git a/src/lib/fcitx-config/CMakeLists.txt b/src/lib/fcitx-config/CMakeLists.txt index 85c9865b..3a995ca1 100644 --- a/src/lib/fcitx-config/CMakeLists.txt @@ -26,32 +13,10 @@ index 85c9865b..3a995ca1 100644 ) target_include_directories(Fcitx5Config PUBLIC diff --git a/src/lib/fcitx-utils/CMakeLists.txt b/src/lib/fcitx-utils/CMakeLists.txt -index dd67e07d..21680660 100644 +index a1f18886..6f9a5832 100644 --- a/src/lib/fcitx-utils/CMakeLists.txt +++ b/src/lib/fcitx-utils/CMakeLists.txt -@@ -27,14 +27,18 @@ if (ENABLE_DBUS) - endif() - endif() - --if (NOT TARGET Systemd::Systemd) -+if (TARGET Systemd::Systemd) - set(FCITX_UTILS_SOURCES - ${FCITX_UTILS_SOURCES} -- event_libuv.cpp) -+ event_sdevent.cpp) -+elseif (EMSCRIPTEN) -+ set(FCITX_UTILS_SOURCES -+ ${FCITX_UTILS_SOURCES} -+ event_js.cpp) - else() - set(FCITX_UTILS_SOURCES - ${FCITX_UTILS_SOURCES} -- event_sdevent.cpp) -+ event_libuv.cpp) - endif() - - set(FCITX_UTILS_SOURCES -@@ -121,8 +125,7 @@ ecm_setup_version(PROJECT +@@ -119,8 +119,7 @@ ecm_setup_version(PROJECT add_library(Fcitx5Utils SHARED ${FCITX_UTILS_SOURCES}) set_target_properties(Fcitx5Utils @@ -61,160 +26,6 @@ index dd67e07d..21680660 100644 EXPORT_NAME Utils ) target_include_directories(Fcitx5Utils PUBLIC -@@ -135,7 +138,7 @@ if(LIBKVM_FOUND) - endif() - - if (NOT TARGET Systemd::Systemd) -- target_link_libraries(Fcitx5Utils PRIVATE ${LIBUV_TARGET}) -+ # target_link_libraries(Fcitx5Utils PRIVATE ${LIBUV_TARGET}) - if (ENABLE_DBUS) - target_link_libraries(Fcitx5Utils PRIVATE PkgConfig::DBus) - endif() -diff --git a/src/lib/fcitx-utils/event_js.cpp b/src/lib/fcitx-utils/event_js.cpp -new file mode 100644 -index 00000000..68f7ee7f ---- /dev/null -+++ b/src/lib/fcitx-utils/event_js.cpp -@@ -0,0 +1,139 @@ -+#include -+#include -+#include "event.h" -+#include "log.h" -+ -+namespace fcitx { -+ -+template -+struct JSEventSourceBase : public Interface { -+public: -+ ~JSEventSourceBase() override {} -+ -+ bool isEnabled() const override { return enabled_; } -+ -+ void setEnabled(bool enabled) override { enabled_ = enabled; } -+ -+ bool isOneShot() const override { return oneShot_; } -+ -+ void setOneShot() override { oneShot_ = true; } -+ -+private: -+ bool enabled_ = false; -+ bool oneShot_ = false; -+}; -+ -+struct JSEventSource : public JSEventSourceBase { -+ JSEventSource(EventCallback _callback) -+ : callback_(std::make_shared(std::move(_callback))) {} -+ -+ std::shared_ptr callback_; -+}; -+ -+struct JSEventSourceIO : public JSEventSourceBase { -+ JSEventSourceIO(IOCallback _callback) {} -+ -+ int fd() const override { return 0; } -+ -+ void setFd(int fd) override {} -+ -+ IOEventFlags events() const override { return IOEventFlag::In; } -+ -+ void setEvents(IOEventFlags flags) override {} -+ -+ IOEventFlags revents() const override { return IOEventFlag::In; } -+}; -+ -+void TimeEventCallback(void *arg); -+ -+struct JSEventSourceTime : public JSEventSourceBase { -+ JSEventSourceTime(TimeCallback _callback, uint64_t time, clockid_t clockid) -+ : callback_(std::make_shared(std::move(_callback))), -+ time_(time), clockid_(clockid) { -+ assert(clockid == CLOCK_MONOTONIC); -+ setOneShot(); -+ } -+ -+ void setOneShot() override { -+ int t = std::max(0, time_ - now(CLOCK_MONOTONIC)) / 1000; -+ emscripten_async_call(TimeEventCallback, this, t); -+ } -+ -+ uint64_t time() const override { return time_; } -+ -+ void setTime(uint64_t time) override { time_ = time; } -+ -+ uint64_t accuracy() const override { return 0; } -+ -+ void setAccuracy(uint64_t time) override {} -+ -+ clockid_t clock() const override { return clockid_; } -+ -+ std::shared_ptr callback_; -+ -+private: -+ uint64_t time_; -+ clockid_t clockid_; -+}; -+ -+void TimeEventCallback(void *arg) { -+ auto source = static_cast(arg); -+ (*source->callback_)(source, source->time()); -+} -+ -+class EventLoopPrivate { -+public: -+ EventLoopPrivate() {} -+ -+ ~EventLoopPrivate() {} -+}; -+ -+EventLoop::EventLoop() : d_ptr(std::make_unique()) {} -+ -+EventLoop::~EventLoop() = default; -+ -+const char *EventLoop::impl() { return "js-event"; } -+ -+void *EventLoop::nativeHandle() { return nullptr; } -+ -+bool EventLoop::exec() { return true; } -+ -+void EventLoop::exit() {} -+ -+std::unique_ptr EventLoop::addIOEvent(int fd, IOEventFlags flags, -+ IOCallback callback) { -+ FCITX_D(); -+ auto source = std::make_unique(std::move(callback)); -+ return source; -+} -+ -+std::unique_ptr -+EventLoop::addTimeEvent(clockid_t clock, uint64_t usec, uint64_t accuracy, -+ TimeCallback callback) { -+ auto source = -+ std::make_unique(std::move(callback), usec, clock); -+ return source; -+} -+ -+std::unique_ptr EventLoop::addExitEvent(EventCallback callback) { -+ FCITX_D(); -+ auto source = std::make_unique(std::move(callback)); -+ return source; -+} -+ -+std::unique_ptr EventLoop::addDeferEvent(EventCallback callback) { -+ return addTimeEvent( -+ CLOCK_MONOTONIC, now(CLOCK_MONOTONIC), 0, -+ [callback = std::move(callback)](EventSourceTime *source, uint64_t) { -+ return callback(source); -+ }); -+} -+ -+std::unique_ptr EventLoop::addPostEvent(EventCallback callback) { -+ return addTimeEvent( -+ CLOCK_MONOTONIC, now(CLOCK_MONOTONIC), 0, -+ [callback = std::move(callback)](EventSourceTime *source, uint64_t) { -+ return callback(source); -+ }); -+} -+} // namespace fcitx diff --git a/src/lib/fcitx/CMakeLists.txt b/src/lib/fcitx/CMakeLists.txt index df15dd57..36312bab 100644 --- a/src/lib/fcitx/CMakeLists.txt diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 63ace5b..82da3e4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,6 +4,7 @@ add_executable(Fcitx5 input_method.cpp config.cpp action.cpp + event_js.cpp ) target_include_directories(Fcitx5 PRIVATE diff --git a/src/event_js.cpp b/src/event_js.cpp new file mode 100644 index 0000000..3ffe746 --- /dev/null +++ b/src/event_js.cpp @@ -0,0 +1,121 @@ +#include "event_js.h" +#include +#include +#include + +namespace fcitx { + +std::unique_ptr createDefaultEventLoop() { + return std::make_unique(); +} + +const char *defaultEventLoopImplementation() { return "js"; } + +template struct JSEventSourceBase : public Interface { + public: + ~JSEventSourceBase() override {} + + bool isEnabled() const override { return enabled_; } + + void setEnabled(bool enabled) override { enabled_ = enabled; } + + bool isOneShot() const override { return oneShot_; } + + void setOneShot() override { oneShot_ = true; } + + private: + bool enabled_ = false; + bool oneShot_ = false; +}; + +struct JSEventSource : public JSEventSourceBase { + JSEventSource(EventCallback _callback) + : callback_(std::make_shared(std::move(_callback))) {} + + std::shared_ptr callback_; +}; + +struct JSEventSourceIO : public JSEventSourceBase { + JSEventSourceIO(IOCallback _callback) {} + + int fd() const override { return 0; } + + void setFd(int fd) override {} + + IOEventFlags events() const override { return IOEventFlag::In; } + + void setEvents(IOEventFlags flags) override {} + + IOEventFlags revents() const override { return IOEventFlag::In; } +}; + +void TimeEventCallback(void *arg); + +struct JSEventSourceTime : public JSEventSourceBase { + JSEventSourceTime(TimeCallback _callback, uint64_t time, clockid_t clockid) + : callback_(std::make_shared(std::move(_callback))), + time_(time), clockid_(clockid) { + setOneShot(); + } + + void setOneShot() override { + int t = std::max(0, time_ - now(CLOCK_MONOTONIC)) / 1000; + emscripten_async_call(TimeEventCallback, this, t); + } + + uint64_t time() const override { return time_; } + + void setTime(uint64_t time) override { time_ = time; } + + uint64_t accuracy() const override { return 0; } + + void setAccuracy(uint64_t time) override {} + + clockid_t clock() const override { return clockid_; } + + std::shared_ptr callback_; + + private: + uint64_t time_; + clockid_t clockid_; +}; + +void TimeEventCallback(void *arg) { + auto source = static_cast(arg); + (*source->callback_)(source, source->time()); +} + +std::unique_ptr +JSEventLoop::addIOEvent(int fd, IOEventFlags flags, IOCallback callback) { + auto source = std::make_unique(std::move(callback)); + return source; +} + +std::unique_ptr +JSEventLoop::addTimeEvent(clockid_t clock, uint64_t usec, uint64_t accuracy, + TimeCallback callback) { + auto source = + std::make_unique(std::move(callback), usec, clock); + return source; +} + +std::unique_ptr JSEventLoop::addExitEvent(EventCallback callback) { + auto source = std::make_unique(std::move(callback)); + return source; +} + +std::unique_ptr +JSEventLoop::addDeferEvent(EventCallback callback) { + return addTimeEvent( + CLOCK_MONOTONIC, now(CLOCK_MONOTONIC), 0, + [callback = std::move(callback)](EventSourceTime *source, uint64_t) { + return callback(source); + }); +} + +std::unique_ptr JSEventLoop::addPostEvent(EventCallback callback) { + FCITX_ERROR() << "Not implemented"; + return nullptr; +} + +} // namespace fcitx diff --git a/src/event_js.h b/src/event_js.h new file mode 100644 index 0000000..11d0007 --- /dev/null +++ b/src/event_js.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +namespace fcitx { +class JSEventLoop : public EventLoopInterface { + public: + JSEventLoop() = default; + ~JSEventLoop() override = default; + bool exec() override { return true; } + void exit() override {} + const char *implementation() const override { return "js"; } + void *nativeHandle() override { return nullptr; } + + std::unique_ptr addIOEvent(int fd, IOEventFlags flags, + IOCallback callback) override; + std::unique_ptr + addTimeEvent(clockid_t clock, uint64_t usec, uint64_t accuracy, + TimeCallback callback) override; + std::unique_ptr addExitEvent(EventCallback callback) override; + std::unique_ptr addDeferEvent(EventCallback callback) override; + std::unique_ptr addPostEvent(EventCallback callback) override; +}; +} // namespace fcitx