// SPDX-FIleCopyrightText: 2017 Francisco Lopes da Silva // SPDX-FIleCopyrightText: 2023 Sam Nystrom // SPDX-License-Identifier: MIT // Map the caps lock key to escape and caps+hjkl to the arrow keys #include #include #include #include #include const struct input_event syn = {.type = EV_SYN, .code = SYN_REPORT, .value = 0}, esc_up = {.type = EV_KEY, .code = KEY_ESC , .value = 0}, esc_down = {.type = EV_KEY, .code = KEY_ESC , .value = 1}; const int delay = 10000; void hjkl_to_arrow(struct input_event *event) { switch (event->code) { case KEY_H: event->code = KEY_LEFT; break; case KEY_J: event->code = KEY_DOWN; break; case KEY_K: event->code = KEY_UP; break; case KEY_L: event->code = KEY_RIGHT; break; } } int main(int argc, char** argv) { setbuf(stdin, NULL); setbuf(stdout, NULL); enum { START, CAPSLOCK_HELD, CAPSLOCK_IS_MODIFIER } state = START; struct input_event event; while (fread(&event, sizeof(event), 1, stdin) == 1) { if (event.type == EV_MSC && event.code == MSC_SCAN) { continue; } if (event.type != EV_KEY && event.type != EV_REL && event.type != EV_ABS) { fwrite(&event, sizeof(event), 1, stdout); continue; } switch (state) { case START: if (event.type == EV_KEY && event.code == KEY_CAPSLOCK && event.value) { state = CAPSLOCK_HELD; } else { fwrite(&event, sizeof(event), 1, stdout); } break; case CAPSLOCK_HELD: if (event.type == EV_KEY && event.code == KEY_CAPSLOCK) { if (event.value == 0) { fwrite(&esc_down, sizeof(esc_down), 1, stdout); fwrite(&syn, sizeof(syn), 1, stdout); usleep(delay); fwrite(&esc_up, sizeof(esc_up), 1, stdout); state = START; } } else if (event.type == EV_KEY && event.value) { hjkl_to_arrow(&event); fwrite(&event, sizeof(event), 1, stdout); state = CAPSLOCK_IS_MODIFIER; } else { fwrite(&event, sizeof(event), 1, stdout); } break; case CAPSLOCK_IS_MODIFIER: if (event.type == EV_KEY && event.code == KEY_CAPSLOCK) { if (event.value == 0) { state = START; } } else { hjkl_to_arrow(&event); fwrite(&event, sizeof(event), 1, stdout); } break; } } }