diff --git a/Sources/OpenKey/win32/OpenKey/OpenKey/.claude/settings.local.json b/Sources/OpenKey/win32/OpenKey/OpenKey/.claude/settings.local.json new file mode 100644 index 0000000..08d96a1 --- /dev/null +++ b/Sources/OpenKey/win32/OpenKey/OpenKey/.claude/settings.local.json @@ -0,0 +1,8 @@ +{ + "permissions": { + "allow": [ + "Bash(cd C:\\\\Users\\\\vankh\\\\Documents\\\\Sources\\\\OpenKey:*)", + "Bash(curl:*)" + ] + } +} diff --git a/Sources/OpenKey/win32/OpenKey/OpenKey/OpenKey.cpp b/Sources/OpenKey/win32/OpenKey/OpenKey/OpenKey.cpp index faa179c..cceedb5 100644 --- a/Sources/OpenKey/win32/OpenKey/OpenKey/OpenKey.cpp +++ b/Sources/OpenKey/win32/OpenKey/OpenKey/OpenKey.cpp @@ -77,6 +77,27 @@ void OpenKeyFree() { UnhookWinEvent(hSystemEvent); } +void OpenKeyReinitHooks() { + // Unhook existing hooks + UnhookWindowsHookEx(hMouseHook); + UnhookWindowsHookEx(hKeyboardHook); + UnhookWinEvent(hSystemEvent); + + // IMPORTANT: Reset modifier key state to prevent stale state issues + // This fixes the bug where hotkeys don't work after unlock because + // _lastFlag still contains old modifier key values + _flag = 0; + _lastFlag = 0; + _keycode = 0; + _isFlagKey = false; + + // Reinitialize hooks + HINSTANCE hInstance = GetModuleHandle(NULL); + hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, keyboardHookProcess, hInstance, 0); + hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, mouseHookProcess, hInstance, 0); + hSystemEvent = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, NULL, winEventProcCallback, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS); +} + void OpenKeyInit() { APP_GET_DATA(vLanguage, 1); APP_GET_DATA(vInputType, 0); diff --git a/Sources/OpenKey/win32/OpenKey/OpenKey/OpenKey.vcxproj b/Sources/OpenKey/win32/OpenKey/OpenKey/OpenKey.vcxproj index 69b1e31..4c09617 100644 --- a/Sources/OpenKey/win32/OpenKey/OpenKey/OpenKey.vcxproj +++ b/Sources/OpenKey/win32/OpenKey/OpenKey/OpenKey.vcxproj @@ -97,6 +97,7 @@ Windows true AsInvoker + wtsapi32.lib;%(AdditionalDependencies) @@ -111,6 +112,7 @@ Windows true + wtsapi32.lib;%(AdditionalDependencies) @@ -131,6 +133,7 @@ true true AsInvoker + wtsapi32.lib;%(AdditionalDependencies) @@ -151,6 +154,7 @@ true true AsInvoker + wtsapi32.lib;%(AdditionalDependencies) diff --git a/Sources/OpenKey/win32/OpenKey/OpenKey/OpenKeyManager.cpp b/Sources/OpenKey/win32/OpenKey/OpenKey/OpenKeyManager.cpp index ea1181b..26fa534 100644 --- a/Sources/OpenKey/win32/OpenKey/OpenKey/OpenKeyManager.cpp +++ b/Sources/OpenKey/win32/OpenKey/OpenKey/OpenKeyManager.cpp @@ -51,6 +51,12 @@ void OpenKeyManager::freeEngine() { OpenKeyFree(); } +void OpenKeyManager::reinitHooks() { + // Reinitialize keyboard hooks after session unlock + extern void OpenKeyReinitHooks(); + OpenKeyReinitHooks(); +} + bool OpenKeyManager::checkUpdate(string& newVersion) { wstring dataW = OpenKeyHelper::getContentOfUrl(L"https://raw.githubusercontent.com/tuyenvm/OpenKey/master/version.json"); string data = wideStringToUtf8(dataW); diff --git a/Sources/OpenKey/win32/OpenKey/OpenKey/OpenKeyManager.h b/Sources/OpenKey/win32/OpenKey/OpenKey/OpenKeyManager.h index fc45cf2..0e875ab 100644 --- a/Sources/OpenKey/win32/OpenKey/OpenKey/OpenKeyManager.h +++ b/Sources/OpenKey/win32/OpenKey/OpenKey/OpenKeyManager.h @@ -22,6 +22,7 @@ class OpenKeyManager { static void initEngine(); static void freeEngine(); + static void reinitHooks(); static bool checkUpdate(string& newVersion); diff --git a/Sources/OpenKey/win32/OpenKey/OpenKey/SystemTrayHelper.cpp b/Sources/OpenKey/win32/OpenKey/OpenKey/SystemTrayHelper.cpp index 55d786e..686d17d 100644 --- a/Sources/OpenKey/win32/OpenKey/OpenKey/SystemTrayHelper.cpp +++ b/Sources/OpenKey/win32/OpenKey/OpenKey/SystemTrayHelper.cpp @@ -75,10 +75,27 @@ map menuData = { LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static UINT taskbarCreated; + const UINT_PTR HOOK_HEALTH_TIMER = 1; // Timer ID for hook health check switch (message) { case WM_CREATE: taskbarCreated = RegisterWindowMessage(_T("TaskbarCreated")); + // Register for session change notifications to handle lock/unlock + WTSRegisterSessionNotification(hWnd, NOTIFY_FOR_THIS_SESSION); + // Set up a 10-second timer to periodically fix stuck keyboard hooks + SetTimer(hWnd, HOOK_HEALTH_TIMER, 10000, NULL); + break; + case WM_WTSSESSION_CHANGE: + // Reinitialize keyboard hooks on session unlock (wParam == WTS_SESSION_UNLOCK) + if (wParam == WTS_SESSION_UNLOCK) { + OpenKeyManager::reinitHooks(); + } + break; + case WM_TIMER: + // Periodic hook health check - reinitialize hooks to fix random stuck issues + if (wParam == HOOK_HEALTH_TIMER) { + OpenKeyManager::reinitHooks(); + } break; case WM_USER+2019: AppDelegate::getInstance()->onControlPanel(); @@ -169,6 +186,12 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) Shell_NotifyIcon(NIM_ADD, &nid); } return DefWindowProc(hWnd, message, wParam, lParam); + case WM_DESTROY: + // Unregister session change notifications + WTSUnRegisterSessionNotification(hWnd); + // Kill the health check timer + KillTimer(hWnd, HOOK_HEALTH_TIMER); + return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } diff --git a/Sources/OpenKey/win32/OpenKey/OpenKey/stdafx.h b/Sources/OpenKey/win32/OpenKey/OpenKey/stdafx.h index 8960e21..7a81871 100644 --- a/Sources/OpenKey/win32/OpenKey/OpenKey/stdafx.h +++ b/Sources/OpenKey/win32/OpenKey/OpenKey/stdafx.h @@ -37,6 +37,7 @@ redistribute your new version, it MUST be open source. #include #include #include +#include #include "resource.h"