caps2esclogo4alt.c (2889B)
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #include <unistd.h> 5 #include <linux/input.h> 6 7 const struct input_event 8 syn = { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, 9 esc_up = { .type = EV_KEY, .code = KEY_ESC, .value = 0 }, 10 ctrl_up = { .type = EV_KEY, .code = KEY_LEFTCTRL, .value = 0 }, 11 esc_down = { .type = EV_KEY, .code = KEY_ESC, .value = 1 }, 12 ctrl_down = { .type = EV_KEY, .code = KEY_LEFTCTRL, .value = 1 }; 13 14 static inline int 15 read_event(struct input_event *event) 16 { 17 return fread(event, sizeof(struct input_event), 1, stdin) == 1; 18 } 19 20 static inline void 21 write_event(const struct input_event *event) 22 { 23 if (fwrite(event, sizeof(struct input_event), 1, stdout) != 1) 24 exit(EXIT_FAILURE); 25 } 26 27 static inline void 28 intercept_event(struct input_event *event) 29 { 30 if (event->type == EV_KEY) { 31 if (event->code == KEY_LEFTALT) 32 event->code = KEY_LEFTMETA; 33 else if (event->code == KEY_LEFTMETA) 34 event->code = KEY_LEFTALT; 35 } 36 37 write_event(event); 38 } 39 40 int 41 main(void) 42 { 43 const int delay = 20000; 44 45 enum { 46 START, 47 CAPSLOCK_HELD, 48 CAPSLOCK_IS_CTRL 49 } state = START; 50 struct input_event input; 51 52 setbuf(stdin, NULL), setbuf(stdout, NULL); 53 54 while (read_event(&input)) { 55 if (input.type == EV_MSC && input.code == MSC_SCAN) 56 continue; 57 58 if (input.type != EV_KEY && input.type != EV_REL && input.type != EV_ABS) { 59 write_event(&input); 60 continue; 61 } 62 63 switch (state) { 64 case START: 65 if (input.type == EV_KEY && input.code == KEY_CAPSLOCK && 66 input.value) 67 state = CAPSLOCK_HELD; 68 else 69 intercept_event(&input); 70 break; 71 case CAPSLOCK_HELD: 72 if (input.type == EV_KEY && input.code == KEY_CAPSLOCK) { 73 if (input.value == 0) { 74 write_event(&esc_down); 75 write_event(&syn); 76 usleep(delay); 77 write_event(&esc_up); 78 state = START; 79 } 80 } else if ((input.type == EV_KEY && input.value == 1) || 81 input.type == EV_REL || input.type == EV_ABS) { 82 write_event(&ctrl_down); 83 write_event(&syn); 84 usleep(delay); 85 intercept_event(&input); 86 state = CAPSLOCK_IS_CTRL; 87 } else 88 intercept_event(&input); 89 break; 90 case CAPSLOCK_IS_CTRL: 91 if (input.type == EV_KEY && input.code == KEY_CAPSLOCK) { 92 input.code = KEY_LEFTCTRL; 93 write_event(&input); 94 if (input.value == 0) 95 state = START; 96 } else 97 intercept_event(&input); 98 break; 99 } 100 } 101 }