#include #include #include #include #include using namespace std; #include "include/NanException.h" #include "include/NanEventCallback.h" #ifdef WIN32 #include "src/Win32KeyboardHook.h" #else #include "src/KeyboardHook.h" #endif 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(); Nan::Set(object, Nan::LocalString("type"), Nan::New(event->type)); Nan::Set(object, Nan::LocalString("key_code"), Nan::New(event->code).ToLocalChecked()); Nan::Set(object, Nan::LocalString("key_shift"), Nan::New(event->key_shift)); Nan::Set(object, Nan::LocalString("key_alt"), Nan::New(event->key_alt)); Nan::Set(object, Nan::LocalString("key_windows"), Nan::New(event->key_windows)); Nan::Set(object, Nan::LocalString("key_ctrl"), Nan::New(event->key_ctrl)); return scope.Escape(object); } NAN_METHOD(RegisterCallback) { if(info.Length() < 1 || !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.Length() < 1 || !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 }; Nan::Call(*callback, Nan::Undefined().As(), 1, args); } } }); NAN_EXPORT(target, RegisterCallback); NAN_EXPORT(target, UnregisterCallback); } NODE_MODULE(MODULE_NAME, init)