Skip to content

Commit

Permalink
Merge pull request #6 from minteeaa/main
Browse files Browse the repository at this point in the history
introduce sticky-keys
  • Loading branch information
cafali authored Jul 25, 2024
2 parents 82ebbbc + c55b237 commit 7c3e29a
Showing 1 changed file with 73 additions and 44 deletions.
117 changes: 73 additions & 44 deletions src.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,25 @@
#include <fstream>
#include <sstream>
#include <string>
#include <unordered_map>

using namespace std;

#define ID_TRAY_APP_ICON 1001
#define ID_TRAY_EXIT_CONTEXT_MENU_ITEM 3000
#define WM_TRAYICON (WM_USER + 1)

struct KeyState
{
bool pressed = false;
};

// Global variables
int keyA_code = 'A'; // Default to 'A'
int keyD_code = 'D'; // Default to 'D'
bool keyA_pressed = false;
bool keyD_pressed = false;
unordered_map<int, KeyState> keyStates;
int activeKey = 0;
int previousKey = 0;
HHOOK hHook = NULL;
NOTIFYICONDATA nid;

Expand Down Expand Up @@ -104,57 +113,77 @@ int main()
return 0;
}

LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
void handleKeyDown(int keyCode)
{
if (nCode == HC_ACTION)
if (keyCode == keyA_code || keyCode == keyD_code)
{
KBDLLHOOKSTRUCT *pKeyBoard = (KBDLLHOOKSTRUCT *)lParam;
switch (wParam)
// get key state
auto& keyState = keyStates[keyCode];
if (!keyState.pressed)
{
case WM_KEYDOWN:
if (pKeyBoard->vkCode == keyA_code)
// set key state + check if key is current key
keyState.pressed = true;
if (activeKey == 0 || activeKey == keyCode) activeKey = keyCode;
else
{
if (keyD_pressed)
{
// Release D
keyD_pressed = false;
INPUT input = {0};
input.type = INPUT_KEYBOARD;
input.ki.wVk = keyD_code;
input.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &input, sizeof(INPUT));
}
keyA_pressed = true;
// set previous key to current key and active to current
previousKey = activeKey;
activeKey = keyCode;

// send keyup input to previous
INPUT input = {0};
input.type = INPUT_KEYBOARD;
input.ki.wVk = previousKey;
input.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &input, sizeof(INPUT));
}
else if (pKeyBoard->vkCode == keyD_code)
{
if (keyA_pressed)
{
// Release A
keyA_pressed = false;
INPUT input = {0};
input.type = INPUT_KEYBOARD;
input.ki.wVk = keyA_code;
input.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &input, sizeof(INPUT));
}
keyD_pressed = true;
}
break;
}
}
}

case WM_KEYUP:
if (pKeyBoard->vkCode == keyA_code)
{
keyA_pressed = false;
}
else if (pKeyBoard->vkCode == keyD_code)
void handleKeyUp(int keyCode)
{
if (keyCode == keyA_code || keyCode == keyD_code)
{
auto& keyState = keyStates[keyCode];
// to prevent previous key getting stuck, check if it is the called key as well as if it's (not) pressed
if (previousKey == keyCode && !keyState.pressed) previousKey = 0;
if (keyState.pressed)
{
// set key state to released
keyState.pressed = false;
// check if previous key exists and the current key is the one we just released
if (activeKey == keyCode && previousKey != 0)
{
keyD_pressed = false;
// set active to previous and clear previous
activeKey = previousKey;
previousKey = 0;

// send keydown input to active
INPUT input = {0};
input.type = INPUT_KEYBOARD;
input.ki.wVk = activeKey;
SendInput(1, &input, sizeof(INPUT));
}
break;
}
}
}

default:
break;
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HC_ACTION)
{
KBDLLHOOKSTRUCT *pKeyBoard = (KBDLLHOOKSTRUCT *)lParam;
switch (wParam)
{
case WM_KEYDOWN:
handleKeyDown(pKeyBoard->vkCode);
break;
case WM_KEYUP:
handleKeyUp(pKeyBoard->vkCode);
break;
default:
break;
}
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
Expand Down

0 comments on commit 7c3e29a

Please sign in to comment.