#include #include #include #include #include using namespace std; #include "NanException.h" #include "NanEventCallback.h" #include "src/KeyboardHook.h" std::mutex callback_lock; std::deque> callbacks; std::deque> queued_events; std::unique_ptr hook; Nan::callback_t<> event_callback; inline v8::Local event_to_object(const std::shared_ptr& event) { Nan::EscapableHandleScope scope; auto object = Nan::New(); object->Set(Nan::New("type").ToLocalChecked(), Nan::New(event->type)); object->Set(Nan::New("key_code").ToLocalChecked(), Nan::New(event->code).ToLocalChecked()); object->Set(Nan::New("key_shift").ToLocalChecked(), Nan::New(event->key_shift)); object->Set(Nan::New("key_alt").ToLocalChecked(), Nan::New(event->key_alt)); object->Set(Nan::New("key_windows").ToLocalChecked(), Nan::New(event->key_windows)); object->Set(Nan::New("key_ctrl").ToLocalChecked(), Nan::New(event->key_ctrl)); return scope.Escape(object); } NAN_METHOD(RegisterCallback) { if(!info[0]->IsFunction()) { NAN_THROW_EXCEPTION(Error, "argument must be a function!"); return; } auto callback = make_shared(info[0].As()); { lock_guard lock(callback_lock); callbacks.push_back(callback); } } NAN_METHOD(UnregisterCallback) { if(!info[0]->IsFunction()) { NAN_THROW_EXCEPTION(Error, "argument must be a function!"); return; } { lock_guard lock(callback_lock); callbacks.erase(std::remove_if(callbacks.begin(), callbacks.end(), [&](const std::shared_ptr& callback){ return callback->GetFunction() == info[0]; }), callbacks.end()); } } NAN_MODULE_INIT(init) { hook = make_unique(); if(!hook->attach()) { NAN_THROW_EXCEPTION(Error, "Failed to attach hook!"); return; } hook->callback_event = [&](const shared_ptr& event) { { lock_guard lock(callback_lock); queued_events.push_back(event); } event_callback(); }; event_callback = Nan::async_callback([](){ Nan::HandleScope scope; unique_lock lock(callback_lock); auto events = queued_events; auto calls = callbacks; queued_events.clear(); lock.unlock(); for(const auto& event : events) { auto object = event_to_object(event); for(const auto& callback : calls) { v8::Local args[] = { object }; callback->Call(1, args); } } }); NAN_EXPORT(target, RegisterCallback); NAN_EXPORT(target, UnregisterCallback); } NODE_MODULE(MODULE_NAME, init)