Skip to content
This repository has been archived by the owner on Sep 3, 2024. It is now read-only.

Commit

Permalink
Minor changes
Browse files Browse the repository at this point in the history
  • Loading branch information
erryox committed Apr 9, 2022
1 parent f9921d4 commit d6a746f
Showing 1 changed file with 84 additions and 42 deletions.
126 changes: 84 additions & 42 deletions Switchy/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,72 +7,84 @@ typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);

typedef struct {
BOOL popup;
BYTE modifier;
} Settings;

void ShowError(LPCSTR message);
DWORD GetOSVersion();
void PressKey(int keyCode);
void ReleaseKey(int keyCode);
void ToggleCapsLockState();
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);


HHOOK hHook;
BOOL modifier;
BOOL enabled = TRUE;
BOOL capsLockPressed = FALSE;
BOOL keystrokeProcessed = FALSE;
BOOL winPressed = FALSE;

Settings settings = {
.popup = FALSE,
.modifier = VK_LSHIFT
.popup = FALSE
};


int main(int argc, char** argv) {
if (argc > 1 && strcmp(argv[1], "nopopup") == 0) {
int main(int argc, char** argv)
{
if (argc > 1 && strcmp(argv[1], "nopopup") == 0)
{
settings.popup = FALSE;
} else {
}
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) {
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
ShowError("Another instance of Switchy is already running!");
return 1;
}

hHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, 0, 0);
if (hHook == NULL) {
if (hHook == NULL)
{
ShowError("Error calling \"SetWindowsHookEx(...)\"");
return 1;
}

MSG messages;
while (GetMessage(&messages, NULL, 0, 0)) {
while (GetMessage(&messages, NULL, 0, 0))
{
TranslateMessage(&messages);
DispatchMessage(&messages);
}

UnhookWindowsHookEx(hHook);

return 0;
}


void ShowError(LPCSTR message) {
void ShowError(LPCSTR message)
{
MessageBox(NULL, message, "Error", MB_OK | MB_ICONERROR);
}


DWORD GetOSVersion() {
DWORD GetOSVersion()
{
HMODULE hMod = GetModuleHandleW(L"ntdll.dll");
RTL_OSVERSIONINFOW osvi = { 0 };

if (hMod) {
if (hMod)
{
RtlGetVersionPtr p = (RtlGetVersionPtr)GetProcAddress(hMod, "RtlGetVersion");

if (p) {
if (p)
{
osvi.dwOSVersionInfoSize = sizeof(osvi);
p(&osvi);
}
Expand All @@ -82,68 +94,98 @@ DWORD GetOSVersion() {
}


void ToggleCapsLockState() {
keybd_event(VK_CAPITAL, 0x3A, 0, 0);
keybd_event(VK_CAPITAL, 0x3A, KEYEVENTF_KEYUP, 0);
void PressKey(int keyCode)
{
keybd_event(keyCode, 0, 0, 0);
}


void ReleaseKey(int keyCode)
{
keybd_event(keyCode, 0, KEYEVENTF_KEYUP, 0);
}


void ToggleCapsLockState()
{
PressKey(VK_CAPITAL);
ReleaseKey(VK_CAPITAL);
#if _DEBUG
printf("Caps Lock state has been toggled\n");
#endif // _DEBUG
}


LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
KBDLLHOOKSTRUCT* key = (KBDLLHOOKSTRUCT*)lParam;
if (nCode == HC_ACTION && !(key->flags & LLKHF_INJECTED)) {
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_SYSKEYDOWN) {
if (key->vkCode == VK_CAPITAL)
{
if (wParam == WM_SYSKEYDOWN && !keystrokeProcessed)
{
keystrokeProcessed = TRUE;
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_KEYUP || wParam == WM_SYSKEYUP)
{
keystrokeProcessed = FALSE;

if (winPressed)
{
winPressed = FALSE;
ReleaseKey(VK_LWIN);
}
}

if (!enabled)
{
return CallNextHookEx(hHook, nCode, wParam, lParam);
}

if (wParam == WM_KEYDOWN && !capsLockPressed) {
capsLockPressed = TRUE;
if (wParam == WM_KEYDOWN && !keystrokeProcessed)
{
keystrokeProcessed = TRUE;

if (GetKeyState(settings.modifier) & 0x8000) {
if (GetKeyState(VK_LSHIFT) & 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);
}
else
{
if (settings.popup)
{
PressKey(VK_LWIN);
PressKey(VK_SPACE);
ReleaseKey(VK_SPACE);
winPressed = TRUE;
}
else {
else
{
HWND hWnd = GetForegroundWindow();
if (hWnd) {
if (hWnd)
{
hWnd = GetAncestor(hWnd, GA_ROOTOWNER);
PostMessage(hWnd, WM_INPUTLANGCHANGEREQUEST, 0, (LPARAM)HKL_NEXT);
}
}
}
}
else if (wParam == WM_KEYUP) {
capsLockPressed = FALSE;

if (winPressed) {
keybd_event(VK_LWIN, 0x3A, KEYEVENTF_KEYUP, 0);
}
}

return 1;
}
}

return CallNextHookEx(NULL, nCode, wParam, lParam);
return CallNextHookEx(hHook, nCode, wParam, lParam);
}

0 comments on commit d6a746f

Please sign in to comment.