feat: Add CAPS->CTRL.

* "Inline" `equal` and `cmp`
* Refactor combo key writing
* Cleanup unused stuff and use `typedef` and `using namespace`
This commit is contained in:
Nikola Maric
2020-09-14 13:07:59 +02:00
committed by Nikola Marić
parent 7ab9bfb7fe
commit 6696f3b516
2 changed files with 120 additions and 88 deletions

BIN
remap

Binary file not shown.

208
remap.cpp
View File

@@ -3,51 +3,31 @@
#include <linux/input.h> #include <linux/input.h>
#include <set> #include <set>
#include <time.h>
#include <unistd.h> #include <unistd.h>
#include <vector> #include <vector>
using namespace std;
/** /**
* Global constants * Global constants
**/ **/
#define MS_TO_NS 1000000L // 1 millisecond = 1,000,000 Nanoseconds #define MS_TO_NS 1000000L // 1 millisecond = 1,000,000 Nanoseconds
typedef struct input_event event;
const int KEY_STROKE_UP = 0, KEY_STROKE_DOWN = 1, KEY_STROKE_REPEAT = 2; const int KEY_STROKE_UP = 0, KEY_STROKE_DOWN = 1, KEY_STROKE_REPEAT = 2;
const int INPUT_BUFFER_SIZE = 16; const int INPUT_BUFFER_SIZE = 16;
const long SLEEP_INTERVAL_NS = 20 * MS_TO_NS; const long SLEEP_INTERVAL_NS = 20 * MS_TO_NS;
const int input_event_struct_size = sizeof(struct input_event); const int input_event_struct_size = sizeof(struct input_event);
int map_space[KEY_MAX];
// clang-format off // clang-format off
const struct input_event const struct input_event
_space_up = {.time = { .tv_sec = 0, .tv_usec = 0}, .type = EV_KEY, .code = KEY_SPACE, .value = KEY_STROKE_UP}, _syn = {.time = { .tv_sec = 0, .tv_usec = 0}, .type = EV_SYN, .code = SYN_REPORT, .value = KEY_STROKE_UP};
_space_down = {.time = { .tv_sec = 0, .tv_usec = 0}, .type = EV_KEY, .code = KEY_SPACE, .value = KEY_STROKE_DOWN},
_space_repeat = {.time = { .tv_sec = 0, .tv_usec = 0}, .type = EV_KEY, .code = KEY_SPACE, .value = KEY_STROKE_REPEAT},
_syn = {.time = { .tv_sec = 0, .tv_usec = 0}, .type = EV_SYN, .code = SYN_REPORT, .value = KEY_STROKE_UP};
const struct input_event const struct input_event
*space_up = &_space_up,
*space_down = &_space_down,
*space_repeat = &_space_repeat,
*syn = &_syn; *syn = &_syn;
// clang-format on // clang-format on
/* unsigned short map_space[KEY_MAX];
static int key_ismod(int code) {
switch (code) {
default:
return 0;
case KEY_LEFTSHIFT:
case KEY_RIGHTSHIFT:
case KEY_LEFTCTRL:
case KEY_RIGHTCTRL:
case KEY_LEFTALT:
case KEY_RIGHTALT:
case KEY_LEFTMETA:
case KEY_RIGHTMETA:
return 1;
}
}
*/
void map_space_init() { void map_space_init() {
// special chars // special chars
map_space[KEY_E] = KEY_ESC; map_space[KEY_E] = KEY_ESC;
@@ -86,44 +66,59 @@ void map_space_init() {
map_space[KEY_DOT] = KEY_VOLUMEUP; map_space[KEY_DOT] = KEY_VOLUMEUP;
} }
int equal(const struct input_event *first, const struct input_event *second) { int read_event(event *e) {
return first->type == second->type && first->code == second->code && return fread(e, input_event_struct_size, 1, stdin) == 1;
first->value == second->value;
} }
auto cmp = [](const struct input_event *e1, const struct input_event *e2) { void write_event(event *e) {
return equal(e1, e2) != 0; if (fwrite(e, input_event_struct_size, 1, stdout) != 1)
};
int read_event(struct input_event *event) {
return fread(event, input_event_struct_size, 1, stdin) == 1;
}
void write_event(const struct input_event *event) {
if (fwrite(event, input_event_struct_size, 1, stdout) != 1)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
void write_events(std::vector<struct input_event> *events) { void write_events(vector<input_event> *events) {
const unsigned long size = events->size(); const unsigned long size = events->size();
if (fwrite(events->data(), input_event_struct_size, size, stdout) != size) if (fwrite(events->data(), input_event_struct_size, size, stdout) != size)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
struct input_event *map(const struct input_event *input, int direction = -1) { void write_combo(unsigned short keycode) {
struct input_event *result = new input_event(*input); input_event key_down = {.time = {.tv_sec = 0, .tv_usec = 0},
result->code = map_space[input->code]; .type = EV_KEY,
.code = keycode,
.value = KEY_STROKE_DOWN};
input_event key_up = {.time = {.tv_sec = 0, .tv_usec = 0},
.type = EV_KEY,
.code = keycode,
.value = KEY_STROKE_UP};
vector<input_event> *combo = new vector<input_event>();
combo->push_back(key_down);
combo->push_back(*syn);
combo->push_back(key_up);
write_events(combo);
delete combo;
}
struct input_event map(const struct input_event *input, int direction = -1) {
struct input_event result(*input);
result.code = map_space[input->code];
if (direction != -1) { if (direction != -1) {
result->value = direction; result.value = direction;
} }
return result; return result;
} }
int main() { int main() {
struct input_event *input = new input_event(); input_event *input = new input_event();
std::set<int> held_keys; set<int> held_keys;
enum { START, SPACE_HELD, KEY_HELD } state = START; enum {
int space_down_not_emitted = 1; START,
MODIFIER_HELD,
KEY_HELD
} state_space = START,
state_caps = START;
bool space_not_emitted = true, caps_is_esc = true, ctrl_not_emitted = true;
map_space_init(); map_space_init();
setbuf(stdin, NULL), setbuf(stdout, NULL); setbuf(stdin, NULL), setbuf(stdout, NULL);
@@ -137,47 +132,84 @@ int main() {
continue; continue;
} }
switch (state) { switch (state_caps) {
case START: case START:
if (equal(input, space_down) || equal(input, space_repeat)) { if (input->code == KEY_CAPSLOCK && input->value == KEY_STROKE_DOWN) {
state = SPACE_HELD; caps_is_esc = true;
space_down_not_emitted = 1; ctrl_not_emitted = true;
state_caps = MODIFIER_HELD;
continue;
}
break;
case MODIFIER_HELD:
if (input->code == KEY_CAPSLOCK && input->value != KEY_STROKE_UP)
break;
if (input->code == KEY_CAPSLOCK) {
if (caps_is_esc) { // and key stroke up
write_combo(KEY_ESC);
} else { // caps is ctrl and key stroke up
event ctrl_up(*input);
ctrl_up.code = KEY_LEFTCTRL;
write_event(&ctrl_up);
}
state_caps = START;
continue;
} else if (input->value !=
KEY_STROKE_UP) { // any key != capslock goes down or repeat
caps_is_esc = false;
if (ctrl_not_emitted) {
event ctrl_down = {.time = {.tv_sec = 0, .tv_usec = 0},
.type = EV_KEY,
.code = KEY_LEFTCTRL,
.value = KEY_STROKE_DOWN};
write_event(&ctrl_down);
ctrl_not_emitted = false;
}
}
break;
default:
break;
}
switch (state_space) {
case START:
if (input->code == KEY_SPACE && input->value != KEY_STROKE_UP) {
space_not_emitted = true;
state_space = MODIFIER_HELD;
} else { } else {
write_event(input); write_event(input);
} }
break; break;
case SPACE_HELD: case MODIFIER_HELD:
if (equal(input, space_down) || equal(input, space_repeat)) if (input->code == KEY_SPACE && input->value != KEY_STROKE_UP)
break; break;
if (input->value == KEY_STROKE_DOWN) { if (input->value == KEY_STROKE_DOWN) {
if (map_space[input->code] != 0) { if (map_space[input->code] != 0) { // mapped key down
held_keys.insert(input->code); held_keys.insert(input->code);
space_down_not_emitted = 0; space_not_emitted = false;
struct input_event *mapped_input = map(input); event mapped = map(input);
write_event(mapped_input); write_event(&mapped);
delete mapped_input; state_space = KEY_HELD;
state = KEY_HELD; } else { // key stroke down any unmapped key
} else { if (input->code == KEY_CAPSLOCK) {
space_not_emitted = false;
}
write_event(input); write_event(input);
} }
} else { // KEY_STROKE_REPEAT or KEY_STROKE_UP } else { // KEY_STROKE_REPEAT or KEY_STROKE_UP
if (input->code == KEY_SPACE && space_down_not_emitted) { if (input->code == KEY_SPACE && space_not_emitted) { // && stroke up
space_down_not_emitted = 0; write_combo(KEY_SPACE);
struct input_event space_down_var(*space_down); space_not_emitted = false;
std::vector<struct input_event> *combo =
new std::vector<struct input_event>();
combo->push_back(*space_down);
combo->push_back(*input);
write_events(combo);
delete combo;
} else { } else {
write_event(input); write_event(input);
} }
state = equal(input, space_up) ? START : SPACE_HELD; if (input->code == KEY_SPACE && input->value == KEY_STROKE_UP) {
state_space = START;
}
} }
break; break;
case KEY_HELD: case KEY_HELD:
if (equal(input, space_down) || equal(input, space_repeat)) if (input->code == KEY_SPACE && input->value != KEY_STROKE_UP)
break; break;
if (input->value == KEY_STROKE_DOWN && if (input->value == KEY_STROKE_DOWN &&
held_keys.find(input->code) != held_keys.end()) { held_keys.find(input->code) != held_keys.end()) {
@@ -185,37 +217,37 @@ int main() {
} }
if (input->value == KEY_STROKE_UP) { if (input->value == KEY_STROKE_UP) {
if (held_keys.find(input->code) != held_keys.end()) { // one of mapped held keys goes up if (held_keys.find(input->code) !=
write_event(map(input)); held_keys.end()) { // one of mapped held keys goes up
struct input_event mapped = map(input);
write_event(&mapped);
held_keys.erase(input->code); held_keys.erase(input->code);
if (held_keys.empty()) { if (held_keys.empty()) {
state = SPACE_HELD; state_space = MODIFIER_HELD;
} }
} else { // regular key goes up } else { // key that was not mapped & held goes up
if (equal(input, space_up)) { if (input->code == KEY_SPACE) {
std::vector<struct input_event> *held_keys_up = vector<input_event> *held_keys_up = new vector<input_event>();
new std::vector<struct input_event>();
for (auto held_key_code : held_keys) { for (auto held_key_code : held_keys) {
struct input_event held_key_up; event held_key_up = {.time = {.tv_sec = 0, .tv_usec = 0},
held_key_up.code = held_key_code; .type = EV_KEY,
held_key_up.value = KEY_STROKE_UP; .code = map_space[held_key_code],
.value = KEY_STROKE_UP};
held_keys_up->push_back(held_key_up); held_keys_up->push_back(held_key_up);
} }
held_keys_up->push_back(*space_up);
write_events(held_keys_up); write_events(held_keys_up);
delete held_keys_up; delete held_keys_up;
held_keys.clear(); held_keys.clear();
state = START; state_space = START;
} else { } else { // unmapped key goes up
write_event(input); write_event(input);
} }
} }
} else { // KEY_STROKE_DOWN or KEY_STROKE_REPEAT } else { // KEY_STROKE_DOWN or KEY_STROKE_REPEAT
if (map_space[input->code] != 0) { if (map_space[input->code] != 0) {
auto mapped = map(input); auto mapped = map(input);
write_event(mapped); write_event(&mapped);
delete mapped;
if (input->value == KEY_STROKE_DOWN) { if (input->value == KEY_STROKE_DOWN) {
held_keys.insert(input->code); held_keys.insert(input->code);
} }