diff --git a/src/lib/fcitx-utils/event_js.cpp b/src/lib/fcitx-utils/event_js.cpp new file mode 100644 index 000000000..522f6d99a --- /dev/null +++ b/src/lib/fcitx-utils/event_js.cpp @@ -0,0 +1,134 @@ +#include +#include "event.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) { + 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) { + 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) { + 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