caps2esc:logo4alt

Interception tools plugin that maps caps->{esc,ctrl} and logo<->alt
git clone git://git.deurzen.net/caps2esc:logo4alt
Log | Files | Refs | README | LICENSE

commit 41a2fa7f1edf594bf220f1fcb5e7a7a0a7033680
parent 230f5c70d33b19e8f517cba0addb053b4d871cfa
Author: Francisco Lopes <francisco@nosubstance.me>
Date:   Mon, 28 Dec 2020 23:05:56 -0300

Rewrite in state machine look

- Also add new option to control internal delay of programmatic key
  sequences, when they're necessary.

Diffstat:
MREADME.md | 17+++++++++--------
Mcaps2esc.c | 143++++++++++++++++++++++++++++++++++++++++---------------------------------------
2 files changed, 81 insertions(+), 79 deletions(-)

diff --git a/README.md b/README.md @@ -37,19 +37,20 @@ $ cmake --build build ``` caps2esc - transforming the most useless key ever in the most useful one -usage: caps2esc [-h] [-m mode] +usage: caps2esc [-h] [-m mode] [-t delay] options: -h show this message and exit + -t delay used for key sequences (default: 20000 microseconds) -m mode 0: default - - caps as esc/ctrl - - esc as caps + - caps as esc/ctrl + - esc as caps 1: minimal - - caps as esc/ctrl + - caps as esc/ctrl 2: useful on 60% layouts - - caps as esc/ctrl - - esc as grave accent - - grave accent as caps + - caps as esc/ctrl + - esc as grave accent + - grave accent as caps ``` `caps2esc` is an [_Interception Tools_][interception-tools] plugin. A suggested @@ -117,7 +118,7 @@ As always, there's always a caveat: I can't recall when I started using CAPSLOCK as both ESC and CTRL but it has been quite some time already. It started when I was on OS X where it was quite easy to achieve using the [Karabiner][], which already provides an option to -turn CTRL into CTRL/ESC (which can be coupled with OS X system settings that +turn CTRL into ESC/CTRL (which can be coupled with OS X system settings that turn CAPSLOCK into CTRL). Moving on, permanently making Linux my home, I searched and tweaked a similar diff --git a/caps2esc.c b/caps2esc.c @@ -6,16 +6,11 @@ // clang-format off const struct input_event -esc_up = {.type = EV_KEY, .code = KEY_ESC, .value = 0}, -ctrl_up = {.type = EV_KEY, .code = KEY_LEFTCTRL, .value = 0}, -capslock_up = {.type = EV_KEY, .code = KEY_CAPSLOCK, .value = 0}, -esc_down = {.type = EV_KEY, .code = KEY_ESC, .value = 1}, -ctrl_down = {.type = EV_KEY, .code = KEY_LEFTCTRL, .value = 1}, -capslock_down = {.type = EV_KEY, .code = KEY_CAPSLOCK, .value = 1}, -esc_repeat = {.type = EV_KEY, .code = KEY_ESC, .value = 2}, -ctrl_repeat = {.type = EV_KEY, .code = KEY_LEFTCTRL, .value = 2}, -capslock_repeat = {.type = EV_KEY, .code = KEY_CAPSLOCK, .value = 2}, -syn = {.type = EV_SYN, .code = SYN_REPORT, .value = 0}; +syn = {.type = EV_SYN, .code = SYN_REPORT, .value = 0}, +esc_up = {.type = EV_KEY, .code = KEY_ESC, .value = 0}, +ctrl_up = {.type = EV_KEY, .code = KEY_LEFTCTRL, .value = 0}, +esc_down = {.type = EV_KEY, .code = KEY_ESC, .value = 1}, +ctrl_down = {.type = EV_KEY, .code = KEY_LEFTCTRL, .value = 1}; // clang-format on void print_usage(FILE *stream, const char *program) { @@ -23,28 +18,24 @@ void print_usage(FILE *stream, const char *program) { fprintf(stream, "caps2esc - transforming the most useless key ever in the most useful one\n" "\n" - "usage: %s [-h] [-m mode]\n" + "usage: %s [-h] [-m mode] [-t delay]\n" "\n" "options:\n" " -h show this message and exit\n" + " -t delay used for key sequences (default: 20000 microseconds)\n" " -m mode 0: default\n" - " - caps as esc/ctrl\n" - " - esc as caps\n" + " - caps as esc/ctrl\n" + " - esc as caps\n" " 1: minimal\n" - " - caps as esc/ctrl\n" + " - caps as esc/ctrl\n" " 2: useful on 60%% layouts\n" - " - caps as esc/ctrl\n" - " - esc as grave accent\n" - " - grave accent as caps\n", + " - caps as esc/ctrl\n" + " - esc as grave accent\n" + " - grave accent as caps\n", program); // clang-format on } -int equal(const struct input_event *first, const struct input_event *second) { - return first->type == second->type && first->code == second->code && - first->value == second->value; -} - int read_event(struct input_event *event) { return fread(event, sizeof(struct input_event), 1, stdin) == 1; } @@ -54,22 +45,45 @@ void write_event(const struct input_event *event) { exit(EXIT_FAILURE); } +void write_event_with_mode(struct input_event *event, int mode) { + switch (mode) { + case 0: + if (event->code == KEY_ESC) + event->code = KEY_CAPSLOCK; + break; + case 2: + switch (event->code) { + case KEY_ESC: + event->code = KEY_GRAVE; + break; + case KEY_GRAVE: + event->code = KEY_CAPSLOCK; + break; + } + break; + } + write_event(event); +} + int main(int argc, char *argv[]) { - int opt, mode = 0; - while ((opt = getopt(argc, argv, "hm:")) != -1) { + int opt, mode = 0, delay = 20000; + while ((opt = getopt(argc, argv, "ht:m:")) != -1) { switch (opt) { case 'h': return print_usage(stdout, argv[0]), EXIT_SUCCESS; + case 't': + delay = atoi(optarg); + continue; case 'm': - mode = optarg[0] - '0'; + mode = atoi(optarg); continue; } return print_usage(stderr, argv[0]), EXIT_FAILURE; } - int capslock_is_down = 0, esc_give_up = 0; struct input_event input; + enum { START, CAPSLOCK_HELD, CAPSLOCK_IS_CTRL } state = START; setbuf(stdin, NULL), setbuf(stdout, NULL); @@ -82,53 +96,40 @@ int main(int argc, char *argv[]) { continue; } - if (capslock_is_down) { - if (equal(&input, &capslock_down) || - equal(&input, &capslock_repeat)) - continue; - - if (equal(&input, &capslock_up)) { - capslock_is_down = 0; - if (esc_give_up) { - esc_give_up = 0; - write_event(&ctrl_up); - continue; - } - write_event(&esc_down); - write_event(&syn); - usleep(20000); - write_event(&esc_up); - continue; - } - - if (!esc_give_up && input.value) { - esc_give_up = 1; - write_event(&ctrl_down); - write_event(&syn); - usleep(20000); - } - } else if (equal(&input, &capslock_down)) { - capslock_is_down = 1; - continue; - } - - switch (mode) { - case 0: - if (input.code == KEY_ESC) - input.code = KEY_CAPSLOCK; + switch (state) { + case START: + if (input.code == KEY_CAPSLOCK && input.value) + state = CAPSLOCK_HELD; + else + write_event_with_mode(&input, mode); break; - case 2: - switch (input.code) { - case KEY_ESC: - input.code = KEY_GRAVE; - break; - case KEY_GRAVE: - input.code = KEY_CAPSLOCK; - break; - } + case CAPSLOCK_HELD: + if (input.code == KEY_CAPSLOCK) { + if (input.value == 0) { + write_event(&esc_down); + write_event(&syn); + usleep(delay); + write_event(&esc_up); + state = START; + } + } else if (input.value == 1) { + write_event(&ctrl_down); + write_event(&syn); + usleep(delay); + write_event_with_mode(&input, mode); + state = CAPSLOCK_IS_CTRL; + } else + write_event_with_mode(&input, mode); + break; + case CAPSLOCK_IS_CTRL: + if (input.code == KEY_CAPSLOCK) { + input.code = KEY_LEFTCTRL; + write_event(&input); + if (input.value == 0) + state = START; + } else + write_event_with_mode(&input, mode); break; } - - write_event(&input); } }