TeaSpeak-Client/native/ppt/binding.cc

126 lines
3.1 KiB
C++
Raw Normal View History

2019-10-25 19:51:40 -04:00
#include <v8.h>
#include <nan.h>
#include <iostream>
#include <mutex>
2019-11-24 12:38:50 -05:00
#include <include/NanStrings.h>
2019-10-25 19:51:40 -04:00
using namespace std;
2019-11-24 12:38:50 -05:00
#include "include/NanException.h"
#include "include/NanEventCallback.h"
#ifdef WIN32
#include "src/Win32KeyboardHook.h"
#else
#include "src/KeyboardHook.h"
2020-08-23 05:35:52 -04:00
#include "src/X11KeyboardHook.h"
#endif
2019-10-25 19:51:40 -04:00
std::mutex callback_lock;
std::deque<std::shared_ptr<Nan::Callback>> callbacks;
std::deque<std::shared_ptr<KeyboardHook::KeyEvent>> queued_events;
std::unique_ptr<KeyboardHook> hook;
Nan::callback_t<> event_callback;
inline v8::Local<v8::Object> event_to_object(const std::shared_ptr<KeyboardHook::KeyEvent>& event) {
Nan::EscapableHandleScope scope;
auto object = Nan::New<v8::Object>();
2019-11-24 12:38:50 -05:00
Nan::Set(object, Nan::LocalString("type"), Nan::New<v8::Number>(event->type));
Nan::Set(object, Nan::LocalString("key_code"), Nan::New<v8::String>(event->code).ToLocalChecked());
2019-10-25 19:51:40 -04:00
2019-11-24 12:38:50 -05:00
Nan::Set(object, Nan::LocalString("key_shift"), Nan::New<v8::Boolean>(event->key_shift));
Nan::Set(object, Nan::LocalString("key_alt"), Nan::New<v8::Boolean>(event->key_alt));
Nan::Set(object, Nan::LocalString("key_windows"), Nan::New<v8::Boolean>(event->key_windows));
Nan::Set(object, Nan::LocalString("key_ctrl"), Nan::New<v8::Boolean>(event->key_ctrl));
2019-10-25 19:51:40 -04:00
return scope.Escape(object);
}
NAN_METHOD(RegisterCallback) {
2019-11-24 12:38:50 -05:00
if(info.Length() < 1 || !info[0]->IsFunction()) {
2019-10-25 19:51:40 -04:00
NAN_THROW_EXCEPTION(Error, "argument must be a function!");
return;
}
auto callback = make_shared<Nan::Callback>(info[0].As<v8::Function>());
{
lock_guard lock(callback_lock);
callbacks.push_back(callback);
}
}
NAN_METHOD(UnregisterCallback) {
2019-11-24 12:38:50 -05:00
if(info.Length() < 1 || !info[0]->IsFunction()) {
2019-10-25 19:51:40 -04:00
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<Nan::Callback>& callback){
return callback->GetFunction() == info[0];
}), callbacks.end());
}
}
NAN_MODULE_INIT(init) {
2020-06-13 11:21:29 -04:00
#ifdef WIN32
hook = make_unique<hooks::Win32RawHook>();
2020-06-13 11:21:29 -04:00
#else
hook = make_unique<hooks::X11KeyboardHook>();
#endif
2019-10-25 19:51:40 -04:00
if(!hook->attach()) {
NAN_THROW_EXCEPTION(Error, "Failed to attach hook!");
return;
}
hook->callback_event = [&](const shared_ptr<KeyboardHook::KeyEvent>& 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<v8::Value> args[] = {
object
};
2019-11-24 12:38:50 -05:00
Nan::Call(*callback, Nan::Undefined().As<v8::Object>(), 1, args);
2019-10-25 19:51:40 -04:00
}
}
});
NAN_EXPORT(target, RegisterCallback);
NAN_EXPORT(target, UnregisterCallback);
2020-08-23 15:52:57 -04:00
node::AtExit([](auto){
hook->detach();
std::unique_lock lock{callback_lock};
callbacks.clear();
queued_events.clear();
});
2019-10-25 19:51:40 -04:00
}
NODE_MODULE(MODULE_NAME, init)