Some more fixes for the 1.4.10 client
This commit is contained in:
parent
02d683954b
commit
3611718bc7
@ -12,6 +12,7 @@ export async function close() {
|
|||||||
break;
|
break;
|
||||||
} catch(error) {} /* error will be already logged */
|
} catch(error) {} /* error will be already logged */
|
||||||
}
|
}
|
||||||
|
|
||||||
if(global_window) {
|
if(global_window) {
|
||||||
global_window.close();
|
global_window.close();
|
||||||
global_window = undefined;
|
global_window = undefined;
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
/* --------------- bootstrap --------------- */
|
/* --------------- bootstrap --------------- */
|
||||||
import * as RequireProxy from "../renderer/RequireProxy";
|
import * as RequireProxy from "../renderer/RequireProxy";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
|
|
||||||
RequireProxy.initialize(path.join(__dirname, "backend-impl"));
|
|
||||||
|
|
||||||
/* --------------- entry point --------------- */
|
/* --------------- entry point --------------- */
|
||||||
import * as loader from "tc-loader";
|
import * as loader from "tc-loader";
|
||||||
import {Stage} from "tc-loader";
|
import {Stage} from "tc-loader";
|
||||||
import {Arguments, process_args} from "../shared/process-arguments";
|
import {Arguments, process_args} from "../shared/process-arguments";
|
||||||
import {remote} from "electron";
|
import {remote} from "electron";
|
||||||
|
|
||||||
|
RequireProxy.initialize(path.join(__dirname, "backend-impl"));
|
||||||
|
|
||||||
export function initialize(manifestTarget: string) {
|
export function initialize(manifestTarget: string) {
|
||||||
console.log("Initializing native client for manifest target %s", manifestTarget);
|
console.log("Initializing native client for manifest target %s", manifestTarget);
|
||||||
|
|
||||||
@ -42,12 +41,10 @@ export function initialize(manifestTarget: string) {
|
|||||||
loader.register_task(loader.Stage.JAVASCRIPT, {
|
loader.register_task(loader.Stage.JAVASCRIPT, {
|
||||||
name: "teaclient jquery",
|
name: "teaclient jquery",
|
||||||
function: async () => {
|
function: async () => {
|
||||||
//const jquery = require("jquery");
|
window.$ = require("jquery");
|
||||||
//console.error(jquery);
|
|
||||||
//window.$ = jquery;
|
|
||||||
|
|
||||||
//window.jQuery = window.$;
|
window.jQuery = window.$;
|
||||||
//Object.assign(window.$, window.jsrender = require('jsrender'));
|
Object.assign(window.$, window.jsrender = require('jsrender'));
|
||||||
},
|
},
|
||||||
priority: 80
|
priority: 80
|
||||||
});
|
});
|
||||||
|
@ -2,7 +2,7 @@ set(MODULE_NAME "teaclient_ppt")
|
|||||||
|
|
||||||
set(SOURCE_FILES src/KeyboardHook.cpp)
|
set(SOURCE_FILES src/KeyboardHook.cpp)
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
set(SOURCE_FILES ${SOURCE_FILES} src/Win32KeyboardHook.cpp src/Win32KeyboardHookLL.cpp src/Win32KeyboardRawInput.cpp)
|
set(SOURCE_FILES ${SOURCE_FILES} src/Win32KeyboardHook.cpp src/Win32KeyboardRawInput.cpp)
|
||||||
else()
|
else()
|
||||||
set(SOURCE_FILES ${SOURCE_FILES} src/X11KeyboardHook.cpp)
|
set(SOURCE_FILES ${SOURCE_FILES} src/X11KeyboardHook.cpp)
|
||||||
endif()
|
endif()
|
||||||
|
@ -13,8 +13,7 @@ using namespace std;
|
|||||||
#include "src/Win32KeyboardHook.h"
|
#include "src/Win32KeyboardHook.h"
|
||||||
#else
|
#else
|
||||||
#include "src/KeyboardHook.h"
|
#include "src/KeyboardHook.h"
|
||||||
#include "src/X11KeyboardHook.h"
|
#include "src/X11KeyboardHook.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,16 +6,10 @@
|
|||||||
|
|
||||||
enum struct KeyboardHookType {
|
enum struct KeyboardHookType {
|
||||||
X11,
|
X11,
|
||||||
|
RAW_INPUT
|
||||||
RAW_INPUT,
|
|
||||||
SYSTEM_HOOK
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class KeyboardHook {
|
class KeyboardHook {
|
||||||
#ifdef HOOK_WIN32_LL
|
|
||||||
friend LRESULT CALLBACK _keyboard_hook_callback(int, WPARAM, LPARAM);
|
|
||||||
friend LRESULT CALLBACK _mouse_hook_callback(int, WPARAM, LPARAM);
|
|
||||||
#endif
|
|
||||||
public:
|
public:
|
||||||
typedef unsigned int KeyID;
|
typedef unsigned int KeyID;
|
||||||
|
|
||||||
|
@ -9,29 +9,6 @@ namespace hooks {
|
|||||||
extern std::string key_string_from_vk(DWORD code, bool extended);
|
extern std::string key_string_from_vk(DWORD code, bool extended);
|
||||||
extern std::string key_string_from_sc(USHORT code);
|
extern std::string key_string_from_sc(USHORT code);
|
||||||
|
|
||||||
class Win32SystemHook : public KeyboardHook {
|
|
||||||
public:
|
|
||||||
Win32SystemHook();
|
|
||||||
|
|
||||||
bool attach() override;
|
|
||||||
void detach() override;
|
|
||||||
|
|
||||||
bool keytype_supported() const override { return true; }
|
|
||||||
private:
|
|
||||||
static LRESULT CALLBACK _keyboard_hook_callback(int, WPARAM, LPARAM);
|
|
||||||
static LRESULT CALLBACK _mouse_hook_callback(int, WPARAM, LPARAM);
|
|
||||||
|
|
||||||
HHOOK keyboad_hook_id{nullptr};
|
|
||||||
bool keyboard_hook_callback(int, WPARAM, LPARAM);
|
|
||||||
|
|
||||||
HHOOK mouse_hook_id{nullptr};
|
|
||||||
bool mouse_hook_callback(int, WPARAM, LPARAM);
|
|
||||||
|
|
||||||
bool active{false};
|
|
||||||
std::thread poll_thread;
|
|
||||||
void poll_events();
|
|
||||||
};
|
|
||||||
|
|
||||||
class Win32RawHook : public KeyboardHook {
|
class Win32RawHook : public KeyboardHook {
|
||||||
public:
|
public:
|
||||||
Win32RawHook();
|
Win32RawHook();
|
||||||
@ -39,12 +16,12 @@ namespace hooks {
|
|||||||
bool attach() override;
|
bool attach() override;
|
||||||
void detach() override;
|
void detach() override;
|
||||||
|
|
||||||
bool keytype_supported() const override { return true; }
|
[[nodiscard]] bool keytype_supported() const override { return true; }
|
||||||
private:
|
private:
|
||||||
static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
|
static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
|
||||||
|
|
||||||
std::thread wthread;
|
std::thread window_thread;
|
||||||
void wloop();
|
void window_loop();
|
||||||
|
|
||||||
enum struct WorkerStatus {
|
enum struct WorkerStatus {
|
||||||
STOPPED,
|
STOPPED,
|
||||||
@ -63,6 +40,6 @@ namespace hooks {
|
|||||||
void set_wstatus(WorkerStatus);
|
void set_wstatus(WorkerStatus);
|
||||||
void handle_raw_input(RAWINPUT&);
|
void handle_raw_input(RAWINPUT&);
|
||||||
|
|
||||||
HWND hwnd{0};
|
HWND hwnd{nullptr};
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -1,301 +0,0 @@
|
|||||||
#include <iostream>
|
|
||||||
#include <cassert>
|
|
||||||
#include <string>
|
|
||||||
#include <mutex>
|
|
||||||
#include "./Win32KeyboardHook.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace hooks {
|
|
||||||
void init_global_ed();
|
|
||||||
void shutdown_global_ed();
|
|
||||||
|
|
||||||
typedef KBDLLHOOKSTRUCT KeyboardHookStruct;
|
|
||||||
thread_local Win32SystemHook* thread_hook{nullptr};
|
|
||||||
|
|
||||||
Win32SystemHook::Win32SystemHook() : KeyboardHook{KeyboardHookType::SYSTEM_HOOK} {}
|
|
||||||
|
|
||||||
bool Win32SystemHook::attach() {
|
|
||||||
if(!KeyboardHook::attach())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
init_global_ed();
|
|
||||||
|
|
||||||
this->active = true;
|
|
||||||
this->poll_thread = std::thread(std::bind(&Win32SystemHook::poll_events, this));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Win32SystemHook::detach() {
|
|
||||||
this->active = false;
|
|
||||||
{
|
|
||||||
//TODO trigger no message!
|
|
||||||
}
|
|
||||||
if(this->poll_thread.joinable())
|
|
||||||
this->poll_thread.join();
|
|
||||||
|
|
||||||
/* will flush all events */
|
|
||||||
shutdown_global_ed();
|
|
||||||
|
|
||||||
KeyboardHook::detach();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LRESULT Win32SystemHook::_mouse_hook_callback(int nCode, WPARAM event, LPARAM ptr_keyboard) {
|
|
||||||
assert(thread_hook);
|
|
||||||
auto consume = thread_hook->mouse_hook_callback(nCode, event, ptr_keyboard);
|
|
||||||
auto end = std::chrono::high_resolution_clock::now();
|
|
||||||
if(consume)
|
|
||||||
return 1;
|
|
||||||
return CallNextHookEx(nullptr, nCode, event, ptr_keyboard);
|
|
||||||
}
|
|
||||||
|
|
||||||
LRESULT Win32SystemHook::_keyboard_hook_callback(int nCode, WPARAM event, LPARAM ptr_keyboard) {
|
|
||||||
assert(thread_hook);
|
|
||||||
auto consume = thread_hook->keyboard_hook_callback(nCode, event, ptr_keyboard);
|
|
||||||
if(consume)
|
|
||||||
return 1;
|
|
||||||
return CallNextHookEx(nullptr, nCode, event, ptr_keyboard);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Win32SystemHook::poll_events() {
|
|
||||||
thread_hook = this;
|
|
||||||
|
|
||||||
if(!SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS))
|
|
||||||
std::cerr << "Failed to set priority class to realtime!" << std::endl;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
std::string msg_box{"Priority Class: "};
|
|
||||||
msg_box += std::to_string((int) GetPriorityClass(GetCurrentProcess()));
|
|
||||||
msg_box += " Priority: ";
|
|
||||||
msg_box += std::to_string((int) GetThreadPriority(GetCurrentProcess()));
|
|
||||||
MessageBox(nullptr, msg_box.c_str(), "PPT-Thread", MB_OK);
|
|
||||||
#endif
|
|
||||||
#if 0
|
|
||||||
int cur_priority = GetThreadPriority(GetCurrentThread());
|
|
||||||
DWORD cur_priority_class = GetPriorityClass(GetCurrentProcess());
|
|
||||||
std::cout << "P: " << cur_priority << " C: " << cur_priority_class << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
this->keyboad_hook_id = SetWindowsHookEx(WH_KEYBOARD_LL, &Win32SystemHook::_keyboard_hook_callback, GetModuleHandle(nullptr), 0);
|
|
||||||
if(!this->keyboad_hook_id) {
|
|
||||||
cerr << "Failed to register keyboard hook" << endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
this->mouse_hook_id = SetWindowsHookEx(WH_MOUSE_LL, &Win32SystemHook::_mouse_hook_callback, GetModuleHandle(nullptr), 0);
|
|
||||||
if(!this->keyboad_hook_id) {
|
|
||||||
UnhookWindowsHookEx(this->keyboad_hook_id);
|
|
||||||
cerr << "Failed to register mouse hook" << endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
this->mouse_hook_id = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
MSG msg;
|
|
||||||
while(!GetMessage(&msg, nullptr, 0, 0) && this->active) {
|
|
||||||
TranslateMessage(&msg);
|
|
||||||
DispatchMessage(&msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this->mouse_hook_id > 0)
|
|
||||||
UnhookWindowsHookEx(this->mouse_hook_id);
|
|
||||||
UnhookWindowsHookEx(this->keyboad_hook_id);
|
|
||||||
thread_hook = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string key_code(KeyboardHookStruct* keyboard) {
|
|
||||||
return key_string_from_vk(keyboard->vkCode, (keyboard->flags & LLKHF_EXTENDED) > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
using KeyType = KeyboardHook::KeyType;
|
|
||||||
|
|
||||||
bool Win32SystemHook::keyboard_hook_callback(int nCode, WPARAM event, LPARAM ptr_keyboard) {
|
|
||||||
auto keyboard = (KeyboardHookStruct*) ptr_keyboard;
|
|
||||||
if(event == WM_KEYDOWN || event == WM_SYSKEYDOWN) {
|
|
||||||
auto& state = this->map_key[keyboard->vkCode];
|
|
||||||
bool typed = state;
|
|
||||||
state = true;
|
|
||||||
|
|
||||||
auto type = key_type_from_vk(keyboard->vkCode);
|
|
||||||
if(type != KeyType::KEY_NORMAL)
|
|
||||||
this->map_special[type] = true;
|
|
||||||
else
|
|
||||||
this->map_special[type] = keyboard->vkCode;
|
|
||||||
|
|
||||||
if(!typed)
|
|
||||||
this->trigger_key_event(KeyEvent::PRESS, type == KeyType::KEY_NORMAL ? key_code(keyboard) : key_string_from_vk(this->map_special[KeyType::KEY_NORMAL], false));
|
|
||||||
this->trigger_key_event(KeyEvent::TYPE, type == KeyType::KEY_NORMAL ? key_code(keyboard) : key_string_from_vk(this->map_special[KeyType::KEY_NORMAL], false));
|
|
||||||
} else if(event == WM_KEYUP || event == WM_SYSKEYUP) {
|
|
||||||
auto& state = this->map_key[keyboard->vkCode];
|
|
||||||
if(!state) return false; //Duplicate
|
|
||||||
state = false;
|
|
||||||
|
|
||||||
auto type = key_type_from_vk(keyboard->vkCode);
|
|
||||||
if(type != KeyType::KEY_NORMAL)
|
|
||||||
this->map_special[type] = false;
|
|
||||||
else if(this->map_special[KeyType::KEY_NORMAL] == keyboard->vkCode)
|
|
||||||
this->map_special[KeyType::KEY_NORMAL] = 0;
|
|
||||||
|
|
||||||
this->trigger_key_event(KeyEvent::RELEASE, type == KeyType::KEY_NORMAL ? key_code(keyboard) : key_string_from_vk(this->map_special[KeyType::KEY_NORMAL], false));
|
|
||||||
}
|
|
||||||
|
|
||||||
//Consume the event: return 1
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef MSLLHOOKSTRUCT MouseLLHookStruct;
|
|
||||||
|
|
||||||
struct MouseButtonEventEntry {
|
|
||||||
MouseButtonEventEntry* next;
|
|
||||||
KeyboardHook* hook;
|
|
||||||
|
|
||||||
enum KeyboardHook::KeyEvent::type type;
|
|
||||||
std::string key;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline MouseButtonEventEntry* allocate_mb_event() {
|
|
||||||
return new MouseButtonEventEntry{};
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void delete_mb_event(MouseButtonEventEntry* event) {
|
|
||||||
delete event;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MouseButtonEventDispatcher {
|
|
||||||
bool active{true};
|
|
||||||
|
|
||||||
std::thread dispatcher{};
|
|
||||||
|
|
||||||
CRITICAL_SECTION mutex;
|
|
||||||
CONDITION_VARIABLE cv_flushed;
|
|
||||||
CONDITION_VARIABLE cv_work;
|
|
||||||
|
|
||||||
MouseButtonEventEntry* event_head{nullptr};
|
|
||||||
MouseButtonEventEntry** event_tail{&event_head};
|
|
||||||
};
|
|
||||||
|
|
||||||
MouseButtonEventDispatcher* global_event_dispatcher{};
|
|
||||||
size_t global_ed_ref_count{0};
|
|
||||||
|
|
||||||
void init_global_ed() {
|
|
||||||
if(global_event_dispatcher) {
|
|
||||||
global_ed_ref_count++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
global_event_dispatcher = new MouseButtonEventDispatcher{};
|
|
||||||
InitializeCriticalSection(&global_event_dispatcher->mutex);
|
|
||||||
InitializeConditionVariable(&global_event_dispatcher->cv_flushed);
|
|
||||||
InitializeConditionVariable(&global_event_dispatcher->cv_work);
|
|
||||||
|
|
||||||
global_event_dispatcher->dispatcher = std::thread([]{
|
|
||||||
auto ed = global_event_dispatcher;
|
|
||||||
|
|
||||||
while(ed->active) {
|
|
||||||
MouseButtonEventEntry* entry{nullptr};
|
|
||||||
{
|
|
||||||
EnterCriticalSection(&ed->mutex);
|
|
||||||
while(!global_event_dispatcher->event_head && ed->active) {
|
|
||||||
WakeAllConditionVariable(&ed->cv_flushed);
|
|
||||||
SleepConditionVariableCS(&ed->cv_work, &ed->mutex, INFINITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = global_event_dispatcher->event_head;
|
|
||||||
global_event_dispatcher->event_head = nullptr;
|
|
||||||
global_event_dispatcher->event_tail = &global_event_dispatcher->event_head;
|
|
||||||
LeaveCriticalSection(&ed->mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
while(entry) {
|
|
||||||
entry->hook->trigger_key_event(entry->type, std::string{entry->key});
|
|
||||||
|
|
||||||
auto next = entry->next;
|
|
||||||
delete_mb_event(entry);
|
|
||||||
entry = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void shutdown_global_ed() {
|
|
||||||
/* flush all events */
|
|
||||||
EnterCriticalSection(&global_event_dispatcher->mutex);
|
|
||||||
WakeAllConditionVariable(&global_event_dispatcher->cv_work);
|
|
||||||
SleepConditionVariableCS(&global_event_dispatcher->cv_flushed, &global_event_dispatcher->mutex, INFINITE);
|
|
||||||
LeaveCriticalSection(&global_event_dispatcher->mutex);
|
|
||||||
|
|
||||||
if(--global_ed_ref_count > 0) return;
|
|
||||||
|
|
||||||
auto ed = std::exchange(global_event_dispatcher, nullptr);
|
|
||||||
ed->active = false;
|
|
||||||
WakeAllConditionVariable(&ed->cv_work);
|
|
||||||
|
|
||||||
if(ed->dispatcher.joinable())
|
|
||||||
ed->dispatcher.join();
|
|
||||||
|
|
||||||
DeleteCriticalSection(&ed->mutex);
|
|
||||||
delete ed;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Win32SystemHook::mouse_hook_callback(int nCode, WPARAM event, LPARAM ptr_mouse) {
|
|
||||||
MouseButtonEventEntry* mb_event;
|
|
||||||
switch (event) {
|
|
||||||
case WM_LBUTTONDOWN:
|
|
||||||
mb_event = allocate_mb_event();
|
|
||||||
mb_event->type = KeyEvent::PRESS;
|
|
||||||
mb_event->key = "MOUSE1";
|
|
||||||
break;
|
|
||||||
case WM_LBUTTONUP:
|
|
||||||
mb_event = allocate_mb_event();
|
|
||||||
mb_event->type = KeyEvent::RELEASE;
|
|
||||||
mb_event->key = "MOUSE1";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_RBUTTONDOWN:
|
|
||||||
mb_event = allocate_mb_event();
|
|
||||||
mb_event->type = KeyEvent::PRESS;
|
|
||||||
mb_event->key = "MOUSE3";
|
|
||||||
break;
|
|
||||||
case WM_RBUTTONUP:
|
|
||||||
mb_event = allocate_mb_event();
|
|
||||||
mb_event->type = KeyEvent::RELEASE;
|
|
||||||
mb_event->key = "MOUSE3";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_XBUTTONDOWN: {
|
|
||||||
auto mouse = (MouseLLHookStruct*) ptr_mouse;
|
|
||||||
auto x_index = GET_XBUTTON_WPARAM(mouse->mouseData);
|
|
||||||
|
|
||||||
mb_event = allocate_mb_event();
|
|
||||||
mb_event->type = KeyEvent::PRESS;
|
|
||||||
mb_event->key = "MOUSEX" + std::to_string(x_index);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case WM_XBUTTONUP: {
|
|
||||||
auto mouse = (MouseLLHookStruct*) ptr_mouse;
|
|
||||||
auto x_index = GET_XBUTTON_WPARAM(mouse->mouseData);
|
|
||||||
|
|
||||||
mb_event = allocate_mb_event();
|
|
||||||
mb_event->type = KeyEvent::RELEASE;
|
|
||||||
mb_event->key = "MOUSEX" + std::to_string(x_index);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
mb_event->next = nullptr;
|
|
||||||
mb_event->hook = thread_hook;
|
|
||||||
|
|
||||||
EnterCriticalSection(&global_event_dispatcher->mutex);
|
|
||||||
*global_event_dispatcher->event_tail = mb_event;
|
|
||||||
global_event_dispatcher->event_tail = &mb_event->next;
|
|
||||||
WakeAllConditionVariable(&global_event_dispatcher->cv_work);
|
|
||||||
LeaveCriticalSection(&global_event_dispatcher->mutex);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
@ -15,7 +15,7 @@ namespace hooks {
|
|||||||
|
|
||||||
this->wactive = true;
|
this->wactive = true;
|
||||||
this->set_wstatus(WorkerStatus::INITIALIZING);
|
this->set_wstatus(WorkerStatus::INITIALIZING);
|
||||||
this->wthread = std::thread(std::bind(&Win32RawHook::wloop, this));
|
this->window_thread = std::thread([this] { this->window_loop(); });
|
||||||
|
|
||||||
std::unique_lock ws_lock{this->wstatus_mutex};
|
std::unique_lock ws_lock{this->wstatus_mutex};
|
||||||
this->wstatus_changed_cv.wait(ws_lock, [&]{
|
this->wstatus_changed_cv.wait(ws_lock, [&]{
|
||||||
@ -27,12 +27,14 @@ namespace hooks {
|
|||||||
|
|
||||||
void Win32RawHook::detach() {
|
void Win32RawHook::detach() {
|
||||||
this->wactive = false;
|
this->wactive = false;
|
||||||
{
|
|
||||||
//TODO trigger no message!
|
if(this->hwnd) {
|
||||||
|
PostMessage(this->hwnd, WM_CLOSE, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this->wthread.joinable())
|
if(this->window_thread.joinable())
|
||||||
this->wthread.join();
|
this->window_thread.join();
|
||||||
|
|
||||||
this->set_wstatus(WorkerStatus::STOPPED);
|
this->set_wstatus(WorkerStatus::STOPPED);
|
||||||
|
|
||||||
KeyboardHook::detach();
|
KeyboardHook::detach();
|
||||||
@ -46,7 +48,7 @@ namespace hooks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define WORKER_CLASS_NAME ("TeaClient - KeyHook worker")
|
#define WORKER_CLASS_NAME ("TeaClient - KeyHook worker")
|
||||||
void Win32RawHook::wloop() {
|
void Win32RawHook::window_loop() {
|
||||||
this->set_wstatus(WorkerStatus::INITIALIZING);
|
this->set_wstatus(WorkerStatus::INITIALIZING);
|
||||||
|
|
||||||
/* setup */
|
/* setup */
|
||||||
@ -55,12 +57,12 @@ namespace hooks {
|
|||||||
WNDCLASS wc = {0};
|
WNDCLASS wc = {0};
|
||||||
wc.lpfnWndProc = window_proc;
|
wc.lpfnWndProc = window_proc;
|
||||||
wc.cbWndExtra = sizeof(void*);
|
wc.cbWndExtra = sizeof(void*);
|
||||||
wc.hInstance = 0;
|
wc.hInstance = nullptr;
|
||||||
wc.lpszClassName = WORKER_CLASS_NAME;
|
wc.lpszClassName = WORKER_CLASS_NAME;
|
||||||
RegisterClass(&wc);
|
RegisterClass(&wc);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->hwnd = CreateWindow(WORKER_CLASS_NAME, "TeaClient - KeyHook worker window", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, this);
|
this->hwnd = CreateWindow(WORKER_CLASS_NAME, "TeaClient - KeyHook worker window", 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr, nullptr, this);
|
||||||
if(!this->hwnd) {
|
if(!this->hwnd) {
|
||||||
this->worker_died_reason = "Failed to create window";
|
this->worker_died_reason = "Failed to create window";
|
||||||
this->set_wstatus(WorkerStatus::DIED);
|
this->set_wstatus(WorkerStatus::DIED);
|
||||||
@ -70,12 +72,12 @@ namespace hooks {
|
|||||||
RAWINPUTDEVICE devices[2];
|
RAWINPUTDEVICE devices[2];
|
||||||
devices[0].usUsagePage = 0x01; //HID_USAGE_PAGE_GENERIC;
|
devices[0].usUsagePage = 0x01; //HID_USAGE_PAGE_GENERIC;
|
||||||
devices[0].usUsage = 0x02; //HID_USAGE_GENERIC_MOUSE;
|
devices[0].usUsage = 0x02; //HID_USAGE_GENERIC_MOUSE;
|
||||||
devices[0].dwFlags = RIDEV_NOLEGACY | RIDEV_INPUTSINK;
|
devices[0].dwFlags = (uint32_t) RIDEV_NOLEGACY | (uint32_t) RIDEV_INPUTSINK;
|
||||||
devices[0].hwndTarget = hwnd;
|
devices[0].hwndTarget = hwnd;
|
||||||
|
|
||||||
devices[1].usUsagePage = 0x01; //HID_USAGE_PAGE_GENERIC;
|
devices[1].usUsagePage = 0x01; //HID_USAGE_PAGE_GENERIC;
|
||||||
devices[1].usUsage = 0x06; //HID_USAGE_GENERIC_KEYBOARD;
|
devices[1].usUsage = 0x06; //HID_USAGE_GENERIC_KEYBOARD;
|
||||||
devices[1].dwFlags = RIDEV_NOLEGACY | RIDEV_INPUTSINK;
|
devices[1].dwFlags = (uint32_t) RIDEV_NOLEGACY | (uint32_t) RIDEV_INPUTSINK;
|
||||||
devices[1].hwndTarget = hwnd;
|
devices[1].hwndTarget = hwnd;
|
||||||
|
|
||||||
if(!RegisterRawInputDevices(devices, 2, sizeof *devices)) {
|
if(!RegisterRawInputDevices(devices, 2, sizeof *devices)) {
|
||||||
@ -86,18 +88,19 @@ namespace hooks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this->set_wstatus(WorkerStatus::RUNNING);
|
this->set_wstatus(WorkerStatus::RUNNING);
|
||||||
|
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
MSG msg;
|
MSG msg;
|
||||||
while (this->wactive) {
|
while (this->wactive) {
|
||||||
ret = GetMessage(&msg, this->hwnd, 0, 0);
|
ret = GetMessage(&msg, this->hwnd, 0, 0);
|
||||||
if(ret == 0)
|
if(ret == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
this->worker_died_reason = "GetMessage() threw an error";
|
this->worker_died_reason = "GetMessage() threw an error";
|
||||||
this->set_wstatus(WorkerStatus::DIED);
|
this->set_wstatus(WorkerStatus::DIED);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
TranslateMessage(&msg);
|
TranslateMessage(&msg);
|
||||||
DispatchMessage(&msg);
|
DispatchMessage(&msg);
|
||||||
}
|
}
|
||||||
@ -105,10 +108,8 @@ namespace hooks {
|
|||||||
this->set_wstatus(WorkerStatus::STOPPED);
|
this->set_wstatus(WorkerStatus::STOPPED);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if(this->hwnd > 0) {
|
if(auto window{std::exchange(this->hwnd, nullptr)}; window)
|
||||||
DestroyWindow(this->hwnd);
|
DestroyWindow(window);
|
||||||
this->hwnd = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LRESULT Win32RawHook::window_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
|
LRESULT Win32RawHook::window_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
|
||||||
@ -116,18 +117,17 @@ namespace hooks {
|
|||||||
|
|
||||||
switch (msg) {
|
switch (msg) {
|
||||||
case WM_CREATE: {
|
case WM_CREATE: {
|
||||||
CREATESTRUCT *s = reinterpret_cast<CREATESTRUCT *>(lp);
|
auto s = reinterpret_cast<CREATESTRUCT *>(lp);
|
||||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) s->lpCreateParams);
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) s->lpCreateParams);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case WM_CLOSE:
|
case WM_CLOSE:
|
||||||
DestroyWindow(hwnd);
|
/* nothing to do here, the window will be cleaned up by the event dispatchers */
|
||||||
PostQuitMessage(0);
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case WM_INPUT: {
|
case WM_INPUT: {
|
||||||
UINT target_size{0};
|
UINT target_size{0};
|
||||||
GetRawInputData((HRAWINPUT) lp, RID_INPUT, NULL, &target_size, sizeof(RAWINPUTHEADER));
|
GetRawInputData((HRAWINPUT) lp, RID_INPUT, nullptr, &target_size, sizeof(RAWINPUTHEADER));
|
||||||
if(target_size > sizeof(RAWINPUT)) {
|
if(target_size > sizeof(RAWINPUT)) {
|
||||||
std::cerr << "Failed to retrieve input (Target size is longer than expected)" << std::endl;
|
std::cerr << "Failed to retrieve input (Target size is longer than expected)" << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
|
190
package-lock.json
generated
190
package-lock.json
generated
@ -172,6 +172,11 @@
|
|||||||
"integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==",
|
"integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/color-name": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ=="
|
||||||
|
},
|
||||||
"@types/ejs": {
|
"@types/ejs": {
|
||||||
"version": "2.7.0",
|
"version": "2.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-2.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-2.7.0.tgz",
|
||||||
@ -523,6 +528,11 @@
|
|||||||
"integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
|
"integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"astral-regex": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ=="
|
||||||
|
},
|
||||||
"async-each": {
|
"async-each": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz",
|
||||||
@ -1102,6 +1112,50 @@
|
|||||||
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.3.0.tgz",
|
||||||
"integrity": "sha512-Xs2Hf2nzrvJMFKimOR7YR0QwZ8fc0u98kdtwN1eNAZzNQgH3vK2pXzff6GJtKh7S5hoJ87ECiAiZFS2fb5Ii2w=="
|
"integrity": "sha512-Xs2Hf2nzrvJMFKimOR7YR0QwZ8fc0u98kdtwN1eNAZzNQgH3vK2pXzff6GJtKh7S5hoJ87ECiAiZFS2fb5Ii2w=="
|
||||||
},
|
},
|
||||||
|
"cli-truncate": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==",
|
||||||
|
"requires": {
|
||||||
|
"slice-ansi": "^3.0.0",
|
||||||
|
"string-width": "^4.2.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-regex": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg=="
|
||||||
|
},
|
||||||
|
"emoji-regex": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||||
|
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
|
||||||
|
},
|
||||||
|
"is-fullwidth-code-point": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
|
||||||
|
},
|
||||||
|
"string-width": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
|
||||||
|
"requires": {
|
||||||
|
"emoji-regex": "^8.0.0",
|
||||||
|
"is-fullwidth-code-point": "^3.0.0",
|
||||||
|
"strip-ansi": "^6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"strip-ansi": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
|
||||||
|
"requires": {
|
||||||
|
"ansi-regex": "^5.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"cliui": {
|
"cliui": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
|
||||||
@ -1679,6 +1733,26 @@
|
|||||||
"extract-zip": "^1.0.3"
|
"extract-zip": "^1.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"electron-context-menu": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/electron-context-menu/-/electron-context-menu-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-XYsYkNY+jvX4C5o09qMuZoKL6e9frnQzBFehZSIiKp6zK0u3XYowJYDyK3vDKKZxYsOIGiE/Gbx40jERC03Ctw==",
|
||||||
|
"requires": {
|
||||||
|
"cli-truncate": "^2.0.0",
|
||||||
|
"electron-dl": "^3.0.0",
|
||||||
|
"electron-is-dev": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"electron-dl": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/electron-dl/-/electron-dl-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-pRgE9Jbhoo5z6Vk3qi+vIrfpMDlCp2oB1UeR96SMnsfz073jj0AZGQwp69EdIcEvlUlwBSGyJK8Jt6OB6JLn+g==",
|
||||||
|
"requires": {
|
||||||
|
"ext-name": "^5.0.0",
|
||||||
|
"pupa": "^2.0.1",
|
||||||
|
"unused-filename": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"electron-fetch": {
|
"electron-fetch": {
|
||||||
"version": "1.5.0",
|
"version": "1.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/electron-fetch/-/electron-fetch-1.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/electron-fetch/-/electron-fetch-1.5.0.tgz",
|
||||||
@ -1770,6 +1844,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"electron-is-dev": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/electron-is-dev/-/electron-is-dev-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-R1oD5gMBPS7PVU8gJwH6CtT0e6VSoD0+SzSnYpNm+dBkcijgA+K7VAMHDfnRq/lkKPZArpzplTW6jfiMYosdzw=="
|
||||||
|
},
|
||||||
"electron-osx-sign": {
|
"electron-osx-sign": {
|
||||||
"version": "0.4.15",
|
"version": "0.4.15",
|
||||||
"resolved": "https://registry.npmjs.org/electron-osx-sign/-/electron-osx-sign-0.4.15.tgz",
|
"resolved": "https://registry.npmjs.org/electron-osx-sign/-/electron-osx-sign-0.4.15.tgz",
|
||||||
@ -2318,6 +2397,11 @@
|
|||||||
"integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==",
|
"integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"escape-goat": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q=="
|
||||||
|
},
|
||||||
"escape-string-regexp": {
|
"escape-string-regexp": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
||||||
@ -2397,6 +2481,23 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ext-list": {
|
||||||
|
"version": "2.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz",
|
||||||
|
"integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==",
|
||||||
|
"requires": {
|
||||||
|
"mime-db": "^1.28.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ext-name": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==",
|
||||||
|
"requires": {
|
||||||
|
"ext-list": "^2.0.0",
|
||||||
|
"sort-keys-length": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"extend": {
|
"extend": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||||
@ -3901,6 +4002,11 @@
|
|||||||
"path-is-inside": "^1.0.1"
|
"path-is-inside": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"is-plain-obj": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
|
||||||
|
"integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4="
|
||||||
|
},
|
||||||
"is-plain-object": {
|
"is-plain-object": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
|
||||||
@ -4518,6 +4624,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"modify-filename": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/modify-filename/-/modify-filename-1.1.0.tgz",
|
||||||
|
"integrity": "sha1-mi3sg4Bvuy2XXyK+7IWcoms5OqE="
|
||||||
|
},
|
||||||
"moment": {
|
"moment": {
|
||||||
"version": "2.26.0",
|
"version": "2.26.0",
|
||||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.26.0.tgz",
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.26.0.tgz",
|
||||||
@ -5313,6 +5424,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
|
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
|
||||||
},
|
},
|
||||||
|
"pupa": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/pupa/-/pupa-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA==",
|
||||||
|
"requires": {
|
||||||
|
"escape-goat": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"pure-uuid": {
|
"pure-uuid": {
|
||||||
"version": "1.6.0",
|
"version": "1.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/pure-uuid/-/pure-uuid-1.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/pure-uuid/-/pure-uuid-1.6.0.tgz",
|
||||||
@ -5842,6 +5961,45 @@
|
|||||||
"string-width": "^1.0.1"
|
"string-width": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"slice-ansi": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==",
|
||||||
|
"requires": {
|
||||||
|
"ansi-styles": "^4.0.0",
|
||||||
|
"astral-regex": "^2.0.0",
|
||||||
|
"is-fullwidth-code-point": "^3.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-styles": {
|
||||||
|
"version": "4.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
|
||||||
|
"integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
|
||||||
|
"requires": {
|
||||||
|
"@types/color-name": "^1.1.1",
|
||||||
|
"color-convert": "^2.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"color-convert": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||||
|
"requires": {
|
||||||
|
"color-name": "~1.1.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"color-name": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||||
|
},
|
||||||
|
"is-fullwidth-code-point": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"snapdragon": {
|
"snapdragon": {
|
||||||
"version": "0.8.2",
|
"version": "0.8.2",
|
||||||
"resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
|
"resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
|
||||||
@ -5970,6 +6128,22 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"sort-keys": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz",
|
||||||
|
"integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=",
|
||||||
|
"requires": {
|
||||||
|
"is-plain-obj": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sort-keys-length": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=",
|
||||||
|
"requires": {
|
||||||
|
"sort-keys": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"source-map": {
|
"source-map": {
|
||||||
"version": "0.1.32",
|
"version": "0.1.32",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.32.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.32.tgz",
|
||||||
@ -6668,6 +6842,22 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"unused-filename": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/unused-filename/-/unused-filename-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-BMiNwJbuWmqCpAM1FqxCTD7lXF97AvfQC8Kr/DIeA6VtvhJaMDupZ82+inbjl5yVP44PcxOuCSxye1QMS0wZyg==",
|
||||||
|
"requires": {
|
||||||
|
"modify-filename": "^1.1.0",
|
||||||
|
"path-exists": "^4.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"path-exists": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"unzip-response": {
|
"unzip-response": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz",
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
"aws4": "^1.10.0",
|
"aws4": "^1.10.0",
|
||||||
"color.js": "^0.1.3",
|
"color.js": "^0.1.3",
|
||||||
"electron": "8.0.0",
|
"electron": "8.0.0",
|
||||||
|
"electron-context-menu": "^2.3.0",
|
||||||
"electron-installer-windows": "^1.1.0",
|
"electron-installer-windows": "^1.1.0",
|
||||||
"electron-rebuild": "^1.11.0",
|
"electron-rebuild": "^1.11.0",
|
||||||
"electron-wix-msi": "^2.1.1",
|
"electron-wix-msi": "^2.1.1",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user