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"