From a21a12be77c79fe9f5d63ad66fa569bc2a9f53ae Mon Sep 17 00:00:00 2001 From: Max Ignatyev Date: Sat, 9 Apr 2022 01:51:24 +0300 Subject: [PATCH] Added the ability to disable Switchy * Added the ability to disable Switchy * Added debug messages * Fixed bugs --- Switchy/main.c | 78 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 25 deletions(-) diff --git a/Switchy/main.c b/Switchy/main.c index 0687918..1c9a936 100644 --- a/Switchy/main.c +++ b/Switchy/main.c @@ -1,4 +1,7 @@ #include +#if _DEBUG +#include +#endif // _DEBUG typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW); @@ -9,12 +12,14 @@ typedef struct { void ShowError(LPCSTR message); DWORD GetOSVersion(); +void ToggleCapsLockState(); LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam); HHOOK hHook; BOOL modifier; -BOOL processed = FALSE; +BOOL enabled = TRUE; +BOOL capsLockPressed = FALSE; BOOL winPressed = FALSE; Settings settings = { @@ -24,11 +29,14 @@ Settings settings = { int main(int argc, char** argv) { - if (argc > 1 && argv[1] == "nopopup") { + if (argc > 1 && strcmp(argv[1], "nopopup") == 0) { settings.popup = FALSE; } else { settings.popup = GetOSVersion() >= 10; } +#if _DEBUG + printf("Pop-up %s\n", settings.popup ? "enabled" : "disabled"); +#endif HANDLE hMutex = CreateMutex(0, 0, "Switchy"); if (GetLastError() == ERROR_ALREADY_EXISTS) { @@ -38,7 +46,7 @@ int main(int argc, char** argv) { hHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, 0, 0); if (hHook == NULL) { - ShowError("Error with \"SetWindowsHookEx\""); + ShowError("Error calling \"SetWindowsHookEx(...)\""); return 1; } @@ -74,26 +82,48 @@ DWORD GetOSVersion() { } -LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { - if (nCode == HC_ACTION) { - KBDLLHOOKSTRUCT* key = (KBDLLHOOKSTRUCT*)lParam; +void ToggleCapsLockState() { + UnhookWindowsHookEx(hHook); + keybd_event(VK_CAPITAL, 0x3A, 0, 0); + keybd_event(VK_CAPITAL, 0x3A, KEYEVENTF_KEYUP, 0); + hHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, 0, 0); +#if _DEBUG + printf("Caps Lock state has been toggled\n"); +#endif // _DEBUG +} + +LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { + KBDLLHOOKSTRUCT* key = (KBDLLHOOKSTRUCT*)lParam; + if (nCode == HC_ACTION && !(key->flags & LLKHF_INJECTED)) { +#if _DEBUG + const char* keyStatus = (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) ? "pressed" : "released"; + printf("Key %d has been %s\n", key->vkCode, keyStatus); +#endif // _DEBUG if (key->vkCode == VK_CAPITAL) { - if (wParam == WM_KEYDOWN) { - if (GetKeyState(settings.modifier)) { - UnhookWindowsHookEx(hHook); - keybd_event(VK_CAPITAL, 0x3a, 0, 0); - keybd_event(VK_CAPITAL, 0x3a, KEYEVENTF_KEYUP, 0); - hHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, 0, 0); - return 1; - } - else if (!processed) { - processed = TRUE; + if (wParam == WM_SYSKEYDOWN) { + enabled = !enabled; +#if _DEBUG + printf("Switchy has been %s\n", enabled ? "enabled" : "disabled"); +#endif // _DEBUG + return 1; + } + if (!enabled) { + return CallNextHookEx(NULL, nCode, wParam, lParam); + } + + if (wParam == WM_KEYDOWN && !capsLockPressed) { + capsLockPressed = TRUE; + + if (GetKeyState(settings.modifier) & 0x8000) { + ToggleCapsLockState(); + return 1; + } else { if (settings.popup) { - keybd_event(VK_LWIN, 0x3a, 0, 0); - keybd_event(VK_SPACE, 0x3a, 0, 0); - keybd_event(VK_SPACE, 0x3a, KEYEVENTF_KEYUP, 0); + keybd_event(VK_LWIN, 0x3A, 0, 0); + keybd_event(VK_SPACE, 0x3A, 0, 0); + keybd_event(VK_SPACE, 0x3A, KEYEVENTF_KEYUP, 0); winPressed = TRUE; } else { @@ -103,19 +133,17 @@ LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { PostMessage(hWnd, WM_INPUTLANGCHANGEREQUEST, 0, (LPARAM)HKL_NEXT); } } - - return 1; } } else if (wParam == WM_KEYUP) { - processed = FALSE; + capsLockPressed = FALSE; if (winPressed) { - keybd_event(VK_LWIN, 0x3a, KEYEVENTF_KEYUP, 0); + keybd_event(VK_LWIN, 0x3A, KEYEVENTF_KEYUP, 0); } - - return 1; } + + return 1; } }