Skip to content

Instantly share code, notes, and snippets.

@cjgajard
Created March 24, 2020 23:43
Show Gist options
  • Save cjgajard/617f118f4130cc4676de25aa38795efc to your computer and use it in GitHub Desktop.
Save cjgajard/617f118f4130cc4676de25aa38795efc to your computer and use it in GitHub Desktop.
Proof of concept for my symmetrical keyboard.
/*
* 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