Created
March 24, 2020 23:43
-
-
Save cjgajard/617f118f4130cc4676de25aa38795efc to your computer and use it in GitHub Desktop.
Proof of concept for my symmetrical keyboard.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Based on https://renenyffenegger.ch/notes/Windows/tools/swap-keys_c | |
* This code uses Windows' hooks to catch and redirect input. | |
* This code is not yet tested for DLL compilation. | |
*/ | |
#include <stdio.h> | |
#ifdef __CYGWIN__ // 2017-07-18 (tsettgchabe) | |
#define _WIN32_WINNT 0x0500 /* 0x0404 */ | |
#endif | |
#include <windows.h> | |
HHOOK hook; | |
#ifdef AS_DLL | |
#pragma message("is DLL") | |
int i = 0; | |
BOOL APIENTRY DllMain (HMODULE hModule, DWORD reason4call, LPVOID lpvReserved) | |
{ | |
switch (reason4call) { | |
case DLL_PROCESS_ATTACH: | |
MessageBox(0, "Hey there!", "SwapKeys", 0); | |
break; | |
case DLL_THREAD_ATTACH: | |
case DLL_THREAD_DETACH: | |
case DLL_PROCESS_DETACH: | |
break; | |
} | |
return TRUE; | |
} | |
#endif | |
#define LLAYER (1 << 0) | |
#define RLAYER (1 << 1) | |
static int layermode = 0; | |
LRESULT CALLBACK keyboardHook(int nCode, WPARAM wParam, LPARAM lParam) | |
{ | |
KBDLLHOOKSTRUCT *p = (KBDLLHOOKSTRUCT *)lParam; | |
DWORD newVkCode; | |
INPUT inputs[3]; | |
UINT ret; | |
if (nCode < 0) | |
return CallNextHookEx(hook, nCode, wParam, lParam); | |
char vkStr[2]; | |
vkStr[0] = p->vkCode; | |
vkStr[1] = 0; | |
printf("%3lu | %9s | %3d\n", p->vkCode, vkStr, p->scanCode); | |
int iskeyup = (wParam == WM_KEYUP || wParam == WM_SYSKEYUP); | |
inputs[0].type = INPUT_KEYBOARD; | |
inputs[0].ki.wScan = 0; | |
inputs[0].ki.dwFlags = iskeyup ? KEYEVENTF_KEYUP : 0; | |
inputs[0].ki.time = 0; | |
inputs[0].ki.dwExtraInfo = 0; | |
inputs[0].ki.wVk = 160; | |
inputs[1].type = INPUT_KEYBOARD; | |
inputs[1].ki.wScan = 0; | |
inputs[1].ki.dwFlags = iskeyup ? KEYEVENTF_KEYUP : 0; | |
inputs[1].ki.time = 0; | |
inputs[1].ki.dwExtraInfo = 0; | |
inputs[2].type = INPUT_KEYBOARD; | |
inputs[2].ki.wScan = 0; | |
inputs[2].ki.dwFlags = KEYEVENTF_KEYUP; | |
inputs[2].ki.time = 0; | |
inputs[2].ki.dwExtraInfo = 0; | |
inputs[2].ki.wVk = 160; | |
if ((p->flags & LLKHF_INJECTED) == 0) { | |
int input_count = 1; | |
switch (p->vkCode) { | |
// Tab 9 -> L-Layer | |
case 9: | |
if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP) { | |
layermode &= ~LLAYER; | |
} | |
else { | |
layermode |= LLAYER; | |
} | |
return 1; | |
// [ 219 + ] 221 -> R-Layer | |
case 219: | |
case 221: | |
if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP) { | |
layermode &= ~RLAYER; | |
} | |
else { | |
layermode |= RLAYER; | |
} | |
return 1; | |
// CapsLock 20 -> L-Ctrl 162 | |
case 20: | |
inputs[0].ki.wVk = 162; | |
break; | |
// B 66 -> B 66, \ 220 | |
case 66: | |
if (!layermode) | |
goto quit; | |
inputs[0].ki.wVk = 220; | |
break; | |
// J 74 -> J 74, [ 219 | |
case 74: | |
if (!layermode) | |
goto quit; | |
inputs[0].ki.wVk = 219; | |
break; | |
// K 75 -> K 75, ] 221 | |
case 75: | |
if (!layermode) | |
goto quit; | |
inputs[0].ki.wVk = 221; | |
break; | |
// L 76 -> L 76, ' 222 | |
case 76: | |
if (!layermode) | |
goto quit; | |
inputs[0].ki.wVk = 222; | |
break; | |
// M 77 -> M 77, { S219 | |
case 77: | |
if (!layermode) | |
goto quit; | |
if (iskeyup) { | |
inputs[0].ki.wVk = 219; | |
} | |
else { | |
inputs[0].ki.dwFlags = 0; | |
inputs[1].ki.wVk = 219; | |
input_count = 3; | |
} | |
break; | |
// N 78 -> N 78, | S220 | |
case 78: | |
if (!layermode) | |
goto quit; | |
if (iskeyup) { | |
inputs[0].ki.wVk = 220; | |
} | |
else { | |
inputs[0].ki.dwFlags = 0; | |
inputs[1].ki.wVk = 220; | |
input_count = 3; | |
} | |
break; | |
// L-Win 91 + L-Ctrl 162 -> ESC 27, Tab 9 | |
case 91: | |
case 162: | |
inputs[0].ki.wVk = layermode ? 9 : 27; | |
break; | |
// R-Ctrl 163 -> Win 91 | |
case 163: | |
inputs[0].ki.wVk = 91; | |
break; | |
// ; 186 -> ; 186, " S222 | |
case 186: | |
if (!layermode) | |
goto quit; | |
if (iskeyup) { | |
inputs[0].ki.wVk = 222; | |
} | |
else { | |
inputs[0].ki.dwFlags = 0; | |
inputs[1].ki.wVk = 222; | |
input_count = 3; | |
} | |
break; | |
// , 188 -> , 188, } S221 | |
case 188: | |
if (!layermode) | |
goto quit; | |
if (iskeyup) { | |
inputs[0].ki.wVk = 221; | |
} | |
else { | |
inputs[0].ki.dwFlags = 0; | |
inputs[1].ki.wVk = 221; | |
input_count = 3; | |
} | |
break; | |
// ' 220 + \ 222 -> R-Ctrl 163 | |
case 220: | |
case 222: | |
inputs[0].ki.wVk = 163; | |
break; | |
// OEM102 226 -> L-Shift 160 | |
case 226: | |
inputs[0].ki.wVk = 160; | |
break; | |
default: | |
goto quit; | |
break; | |
} | |
ret = SendInput(input_count, inputs, sizeof(INPUT)); | |
return 1; | |
} | |
quit: | |
return CallNextHookEx(hook, nCode, wParam, lParam); | |
} | |
#ifdef AS_DLL | |
// 2017-07-21 - tsettchabe / CYGWIN | |
extern __declspec(dllexport) | |
#endif | |
int startSwapKeys() | |
{ | |
MSG messages; | |
hook = SetWindowsHookEx(WH_KEYBOARD_LL, keyboardHook, NULL, 0); | |
if (hook == NULL) { | |
printf("Error %d\n", GetLastError()); | |
return 1; | |
} | |
#ifndef AS_DLL | |
printf("Waiting for messages ...\n"); | |
while (GetMessage (&messages, NULL, 0, 0)) { | |
TranslateMessage(&messages); | |
DispatchMessage(&messages); | |
} | |
#endif | |
return 0; | |
} | |
#ifndef AS_DLL | |
int main(int argc, char *argv[]) { | |
return startSwapKeys(); | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment