From 858514a19cf7575ece662199a35ae2a77a7d07e9 Mon Sep 17 00:00:00 2001 From: Sential Date: Thu, 12 Dec 2019 18:38:11 +0100 Subject: [PATCH] fix: some functions not working on Windows --- example.js | 6 +- lib/windows.cc | 307 ++++++++++++++++++++++--------------------------- src/index.ts | 6 +- 3 files changed, 143 insertions(+), 176 deletions(-) diff --git a/example.js b/example.js index 524bd7a..a79305d 100644 --- a/example.js +++ b/example.js @@ -20,6 +20,8 @@ console.timeEnd("setBounds"); console.log("[info]: Visible Windows List"); windowManager.getWindows().forEach(window => { - console.log('Title: '+window.getTitle(), '\n', 'Path: '+window.path); - window.bringToTop(); + if (window.isVisible()) { + console.log(window.getInfo()); + window.bringToTop(); + } }); \ No newline at end of file diff --git a/lib/windows.cc b/lib/windows.cc index 904d82a..9ff1c09 100644 --- a/lib/windows.cc +++ b/lib/windows.cc @@ -1,13 +1,12 @@ -#include -#include -#include #include #include #include +#include +#include #include +#include -typedef int(__stdcall *lp_GetScaleFactorForMonitor)(HMONITOR, - DEVICE_SCALE_FACTOR *); +typedef int(__stdcall* lp_GetScaleFactorForMonitor) (HMONITOR, DEVICE_SCALE_FACTOR*); struct Process { int pid; @@ -20,201 +19,181 @@ struct Window { }; template -T getValueFromCallbackData(const Napi::CallbackInfo &info, - unsigned handleIndex) { - return reinterpret_cast( - info[handleIndex].As().Int64Value()); +T getValueFromCallbackData (const Napi::CallbackInfo& info, unsigned handleIndex) { + return reinterpret_cast (info[handleIndex].As ().Int64Value ()); } -std::string toUtf8(const std::wstring &str) { +std::string toUtf8 (const std::wstring& str) { std::string ret; - int len = WideCharToMultiByte(CP_UTF8, 0, str.c_str(), str.length(), NULL, - 0, NULL, NULL); + int len = WideCharToMultiByte (CP_UTF8, 0, str.c_str (), str.length (), NULL, 0, NULL, NULL); if (len > 0) { - ret.resize(len); - WideCharToMultiByte(CP_UTF8, 0, str.c_str(), str.length(), &ret[0], len, - NULL, NULL); + ret.resize (len); + WideCharToMultiByte (CP_UTF8, 0, str.c_str (), str.length (), &ret[0], len, NULL, NULL); } return ret; } -Process getWindowProcess(HWND handle) { - DWORD pid{0}; - GetWindowThreadProcessId(handle, &pid); +Process getWindowProcess (HWND handle) { + DWORD pid{ 0 }; + GetWindowThreadProcessId (handle, &pid); - HANDLE pHandle{OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, pid)}; + HANDLE pHandle{ OpenProcess (PROCESS_QUERY_LIMITED_INFORMATION, false, pid) }; - DWORD dwSize{MAX_PATH}; + DWORD dwSize{ MAX_PATH }; wchar_t exeName[MAX_PATH]{}; - QueryFullProcessImageNameW(pHandle, 0, exeName, &dwSize); + QueryFullProcessImageNameW (pHandle, 0, exeName, &dwSize); - auto wspath(exeName); - auto path = toUtf8(wspath); + auto wspath (exeName); + auto path = toUtf8 (wspath); - return {static_cast(pid), path}; + return { static_cast (pid), path }; } -Napi::Object getActiveWindow(const Napi::CallbackInfo &info) { - Napi::Env env{info.Env()}; - - auto handle = GetForegroundWindow(); - auto process = getWindowProcess(handle); +Napi::Number getActiveWindow (const Napi::CallbackInfo& info) { + Napi::Env env{ info.Env () }; - Napi::Object obj{Napi::Object::New(env)}; + auto handle = GetForegroundWindow (); - obj.Set("processId", process.pid); - obj.Set("path", process.path); - obj.Set("id", reinterpret_cast(handle)); - - return obj; + return Napi::Number::New (env, reinterpret_cast (handle)); } std::vector _windows; -BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lparam) { - auto process = getWindowProcess(hwnd); - _windows.push_back({process, reinterpret_cast(hwnd)}); +BOOL CALLBACK EnumWindowsProc (HWND hwnd, LPARAM lparam) { + auto process = getWindowProcess (hwnd); + _windows.push_back ({ process, reinterpret_cast (hwnd) }); return TRUE; } -Napi::Array getWindows(const Napi::CallbackInfo &info) { - Napi::Env env{info.Env()}; +Napi::Array getWindows (const Napi::CallbackInfo& info) { + Napi::Env env{ info.Env () }; - _windows.clear(); - EnumWindows(&EnumWindowsProc, NULL); + _windows.clear (); + EnumWindows (&EnumWindowsProc, NULL); auto arr = Napi::Array::New (env); auto i = 0; for (auto _win : _windows) { if (_win.process.path.empty ()) continue; - auto obj{ Napi::Object::New (env) }; - obj.Set("id", _win.id); - obj.Set("processId", _win.process.pid); - obj.Set("path", _win.process.path); - arr.Set(i++, obj); + arr.Set (i++, Napi::Number::New (env, _win.id)); } return arr; } -Napi::Number getMonitorFromWindow(const Napi::CallbackInfo &info) { - Napi::Env env{info.Env()}; +Napi::Number getMonitorFromWindow (const Napi::CallbackInfo& info) { + Napi::Env env{ info.Env () }; - auto handle = getValueFromCallbackData(info, 0); + auto handle = getValueFromCallbackData (info, 0); - return Napi::Number::New( - env, reinterpret_cast(MonitorFromWindow(handle, 0))); + return Napi::Number::New (env, reinterpret_cast (MonitorFromWindow (handle, 0))); } -Napi::Object getWindowInfo(const Napi::CallbackInfo &info) { - Napi::Env env{info.Env()}; +Napi::Object getWindowInfo (const Napi::CallbackInfo& info) { + Napi::Env env{ info.Env () }; - auto handle{getValueFromCallbackData(info, 0)}; - auto process = getWindowProcess(handle); + auto handle{ getValueFromCallbackData (info, 0) }; + auto process = getWindowProcess (handle); BYTE opacity{}; - GetLayeredWindowAttributes(handle, NULL, &opacity, NULL); + GetLayeredWindowAttributes (handle, NULL, &opacity, NULL); - int bufsize = GetWindowTextLengthW(handle) + 1; + int bufsize = GetWindowTextLengthW (handle) + 1; LPWSTR t = new WCHAR[bufsize]; - GetWindowTextW(handle, t, bufsize); + GetWindowTextW (handle, t, bufsize); - std::wstring ws(t); - std::string title = toUtf8(ws); + std::wstring ws (t); + std::string title = toUtf8 (ws); RECT rect{}; - GetWindowRect(handle, &rect); + GetWindowRect (handle, &rect); - Napi::Object bounds{Napi::Object::New(env)}; + Napi::Object bounds{ Napi::Object::New (env) }; - bounds.Set("x", rect.left); - bounds.Set("y", rect.top); - bounds.Set("width", rect.right - rect.left); - bounds.Set("height", rect.bottom - rect.top); + bounds.Set ("x", rect.left); + bounds.Set ("y", rect.top); + bounds.Set ("width", rect.right - rect.left); + bounds.Set ("height", rect.bottom - rect.top); - Napi::Object obj{Napi::Object::New(env)}; + Napi::Object obj{ Napi::Object::New (env) }; - obj.Set("bounds", bounds); - obj.Set("processId", process.pid); - obj.Set("path", process.path); - obj.Set("opacity", static_cast(opacity) / 255.); - obj.Set("title", title); - obj.Set("owner", GetWindowLongPtrA(handle, GWLP_HWNDPARENT)); + obj.Set ("bounds", bounds); + obj.Set ("processId", process.pid); + obj.Set ("path", process.path); + obj.Set ("opacity", static_cast (opacity) / 255.); + obj.Set ("title", title); + obj.Set ("owner", GetWindowLongPtrA (handle, GWLP_HWNDPARENT)); return obj; } -Napi::Number getMonitorScaleFactor(const Napi::CallbackInfo &info) { - Napi::Env env{info.Env()}; +Napi::Number getMonitorScaleFactor (const Napi::CallbackInfo& info) { + Napi::Env env{ info.Env () }; - HMODULE hShcore{LoadLibraryA("SHcore.dll")}; - lp_GetScaleFactorForMonitor f{(lp_GetScaleFactorForMonitor)GetProcAddress( - hShcore, "GetScaleFactorForMonitor")}; + HMODULE hShcore{ LoadLibraryA ("SHcore.dll") }; + lp_GetScaleFactorForMonitor f{ ( + lp_GetScaleFactorForMonitor)GetProcAddress (hShcore, "GetScaleFactorForMonitor") }; DEVICE_SCALE_FACTOR sf{}; - f(getValueFromCallbackData(info, 0), &sf); + f (getValueFromCallbackData (info, 0), &sf); - return Napi::Number::New(env, static_cast(sf) / 100.); + return Napi::Number::New (env, static_cast (sf) / 100.); } -Napi::Boolean toggleWindowTransparency(const Napi::CallbackInfo &info) { - Napi::Env env{info.Env()}; +Napi::Boolean toggleWindowTransparency (const Napi::CallbackInfo& info) { + Napi::Env env{ info.Env () }; - auto handle{getValueFromCallbackData(info, 0)}; - bool toggle{info[1].As()}; - LONG_PTR style{GetWindowLongPtrA(handle, GWL_EXSTYLE)}; + auto handle{ getValueFromCallbackData (info, 0) }; + bool toggle{ info[1].As () }; + LONG_PTR style{ GetWindowLongPtrA (handle, GWL_EXSTYLE) }; - SetWindowLongPtrA( - handle, GWL_EXSTYLE, - ((toggle) ? (style | WS_EX_LAYERED) : (style & (~WS_EX_LAYERED)))); + SetWindowLongPtrA (handle, GWL_EXSTYLE, ((toggle) ? (style | WS_EX_LAYERED) : (style & (~WS_EX_LAYERED)))); - return Napi::Boolean::New(env, true); + return Napi::Boolean::New (env, true); } -Napi::Boolean setWindowOpacity(const Napi::CallbackInfo &info) { - Napi::Env env{info.Env()}; +Napi::Boolean setWindowOpacity (const Napi::CallbackInfo& info) { + Napi::Env env{ info.Env () }; - auto handle{getValueFromCallbackData(info, 0)}; - double opacity{info[1].As().DoubleValue()}; + auto handle{ getValueFromCallbackData (info, 0) }; + double opacity{ info[1].As ().DoubleValue () }; - SetLayeredWindowAttributes(handle, NULL, opacity * 255., LWA_ALPHA); + SetLayeredWindowAttributes (handle, NULL, opacity * 255., LWA_ALPHA); - return Napi::Boolean::New(env, true); + return Napi::Boolean::New (env, true); } -Napi::Boolean setWindowBounds(const Napi::CallbackInfo &info) { - Napi::Env env{info.Env()}; +Napi::Boolean setWindowBounds (const Napi::CallbackInfo& info) { + Napi::Env env{ info.Env () }; - Napi::Object bounds{info[1].As()}; - auto handle{getValueFromCallbackData(info, 0)}; + Napi::Object bounds{ info[1].As () }; + auto handle{ getValueFromCallbackData (info, 0) }; - BOOL b{MoveWindow( - handle, bounds.Get("x").ToNumber(), bounds.Get("y").ToNumber(), - bounds.Get("width").ToNumber(), bounds.Get("height").ToNumber(), true)}; + BOOL b{ MoveWindow (handle, bounds.Get ("x").ToNumber (), bounds.Get ("y").ToNumber (), + bounds.Get ("width").ToNumber (), bounds.Get ("height").ToNumber (), true) }; - return Napi::Boolean::New(env, b); + return Napi::Boolean::New (env, b); } -Napi::Boolean setWindowOwner(const Napi::CallbackInfo &info) { - Napi::Env env{info.Env()}; +Napi::Boolean setWindowOwner (const Napi::CallbackInfo& info) { + Napi::Env env{ info.Env () }; - auto handle{getValueFromCallbackData(info, 0)}; - auto newOwner{ - static_cast(info[1].As().Int64Value())}; + auto handle{ getValueFromCallbackData (info, 0) }; + auto newOwner{ static_cast (info[1].As ().Int64Value ()) }; - SetWindowLongPtrA(handle, GWLP_HWNDPARENT, newOwner); + SetWindowLongPtrA (handle, GWLP_HWNDPARENT, newOwner); - return Napi::Boolean::New(env, true); + return Napi::Boolean::New (env, true); } -Napi::Boolean showWindow(const Napi::CallbackInfo &info) { - Napi::Env env{info.Env()}; +Napi::Boolean showWindow (const Napi::CallbackInfo& info) { + Napi::Env env{ info.Env () }; - auto handle{getValueFromCallbackData(info, 0)}; - std::string type{info[1].As()}; + auto handle{ getValueFromCallbackData (info, 0) }; + std::string type{ info[1].As () }; - DWORD flag{0}; + DWORD flag{ 0 }; if (type == "show") flag = SW_SHOW; @@ -227,80 +206,66 @@ Napi::Boolean showWindow(const Napi::CallbackInfo &info) { else if (type == "maximize") flag = SW_MAXIMIZE; - return Napi::Boolean::New(env, ShowWindow(handle, flag)); + return Napi::Boolean::New (env, ShowWindow (handle, flag)); } -Napi::Boolean bringWindowToTop(const Napi::CallbackInfo &info) { - Napi::Env env{info.Env()}; +Napi::Boolean bringWindowToTop (const Napi::CallbackInfo& info) { + Napi::Env env{ info.Env () }; - auto handle{getValueFromCallbackData(info, 0)}; - BOOL b{SetForegroundWindow(handle)}; - SetActiveWindow(handle); - SetWindowPos(handle, HWND_TOP, 0, 0, 0, 0, - SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE); + auto handle{ getValueFromCallbackData (info, 0) }; + BOOL b{ SetForegroundWindow (handle) }; + SetActiveWindow (handle); + SetWindowPos (handle, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE); - return Napi::Boolean::New(env, b); + return Napi::Boolean::New (env, b); } -Napi::Boolean redrawWindow(const Napi::CallbackInfo &info) { - Napi::Env env{info.Env()}; +Napi::Boolean redrawWindow (const Napi::CallbackInfo& info) { + Napi::Env env{ info.Env () }; - auto handle{getValueFromCallbackData(info, 0)}; - BOOL b{SetWindowPos(handle, 0, 0, 0, 0, 0, - SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | - SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE | - SWP_DRAWFRAME | SWP_NOCOPYBITS)}; + auto handle{ getValueFromCallbackData (info, 0) }; + BOOL b{ SetWindowPos (handle, 0, 0, 0, 0, 0, + SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | + SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_DRAWFRAME | SWP_NOCOPYBITS) }; - return Napi::Boolean::New(env, b); + return Napi::Boolean::New (env, b); } -Napi::Boolean isWindow(const Napi::CallbackInfo &info) { - Napi::Env env{info.Env()}; +Napi::Boolean isWindow (const Napi::CallbackInfo& info) { + Napi::Env env{ info.Env () }; - auto handle{getValueFromCallbackData(info, 0)}; + auto handle{ getValueFromCallbackData (info, 0) }; - return Napi::Boolean::New(env, IsWindow(handle)); + return Napi::Boolean::New (env, IsWindow (handle)); } -Napi::Boolean isVisible(const Napi::CallbackInfo &info) { - Napi::Env env{info.Env()}; +Napi::Boolean isVisible (const Napi::CallbackInfo& info) { + Napi::Env env{ info.Env () }; - auto handle{getValueFromCallbackData(info, 0)}; + auto handle{ getValueFromCallbackData (info, 0) }; - return Napi::Boolean::New(env, IsWindowVisible(handle)); + return Napi::Boolean::New (env, IsWindowVisible (handle)); } -Napi::Object Init(Napi::Env env, Napi::Object exports) { - exports.Set(Napi::String::New(env, "getActiveWindow"), - Napi::Function::New(env, getActiveWindow)); - exports.Set(Napi::String::New(env, "getMonitorFromWindow"), - Napi::Function::New(env, getMonitorFromWindow)); - exports.Set(Napi::String::New(env, "getMonitorScaleFactor"), - Napi::Function::New(env, getMonitorScaleFactor)); - exports.Set(Napi::String::New(env, "setWindowBounds"), - Napi::Function::New(env, setWindowBounds)); - exports.Set(Napi::String::New(env, "showWindow"), - Napi::Function::New(env, showWindow)); - exports.Set(Napi::String::New(env, "bringWindowToTop"), - Napi::Function::New(env, bringWindowToTop)); - exports.Set(Napi::String::New(env, "redrawWindow"), - Napi::Function::New(env, redrawWindow)); - exports.Set(Napi::String::New(env, "isWindow"), - Napi::Function::New(env, isWindow)); - exports.Set(Napi::String::New(env, "isVisible"), - Napi::Function::New(env, isVisible)); - exports.Set(Napi::String::New(env, "setWindowOpacity"), - Napi::Function::New(env, setWindowOpacity)); - exports.Set(Napi::String::New(env, "toggleWindowTransparency"), - Napi::Function::New(env, toggleWindowTransparency)); - exports.Set(Napi::String::New(env, "setWindowOwner"), - Napi::Function::New(env, setWindowOwner)); - exports.Set(Napi::String::New(env, "getWindowInfo"), - Napi::Function::New(env, getWindowInfo)); - exports.Set(Napi::String::New(env, "getWindows"), - Napi::Function::New(env, getWindows)); +Napi::Object Init (Napi::Env env, Napi::Object exports) { + exports.Set (Napi::String::New (env, "getActiveWindow"), Napi::Function::New (env, getActiveWindow)); + exports.Set (Napi::String::New (env, "getMonitorFromWindow"), Napi::Function::New (env, getMonitorFromWindow)); + exports.Set (Napi::String::New (env, "getMonitorScaleFactor"), + Napi::Function::New (env, getMonitorScaleFactor)); + exports.Set (Napi::String::New (env, "setWindowBounds"), Napi::Function::New (env, setWindowBounds)); + exports.Set (Napi::String::New (env, "showWindow"), Napi::Function::New (env, showWindow)); + exports.Set (Napi::String::New (env, "bringWindowToTop"), Napi::Function::New (env, bringWindowToTop)); + exports.Set (Napi::String::New (env, "redrawWindow"), Napi::Function::New (env, redrawWindow)); + exports.Set (Napi::String::New (env, "isWindow"), Napi::Function::New (env, isWindow)); + exports.Set (Napi::String::New (env, "isVisible"), Napi::Function::New (env, isVisible)); + exports.Set (Napi::String::New (env, "setWindowOpacity"), Napi::Function::New (env, setWindowOpacity)); + exports.Set (Napi::String::New (env, "toggleWindowTransparency"), + Napi::Function::New (env, toggleWindowTransparency)); + exports.Set (Napi::String::New (env, "setWindowOwner"), Napi::Function::New (env, setWindowOwner)); + exports.Set (Napi::String::New (env, "getWindowInfo"), Napi::Function::New (env, getWindowInfo)); + exports.Set (Napi::String::New (env, "getWindows"), Napi::Function::New (env, getWindows)); return exports; } -NODE_API_MODULE(addon, Init) \ No newline at end of file +NODE_API_MODULE (addon, Init) \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index eae6369..c0b86d9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -27,9 +27,9 @@ class WindowManager extends EventEmitter { if (event === "window-activated") { interval = setInterval(async () => { const win = addon.getActiveWindow(); - - if (lastId !== win.id) { - lastId = win.id; + + if (lastId !== win) { + lastId = win; this.emit("window-activated", new Window(win)); } }, 50);