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:
M | README.md | | | 17 | +++++++++-------- |
M | caps2esc.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);
}
}