mirror of
https://github.com/RecentRunner/interception-vimproved-personal.git
synced 2026-06-04 16:19:18 -06:00
Move to c++, handle multiple mapped keys
This commit is contained in:
committed by
Nikola Marić
parent
8ddea4e1ae
commit
eec5ba4288
8
Makefile
8
Makefile
@@ -1,4 +1,4 @@
|
|||||||
CFLAGS += -std=c99 -D_POSIX_C_SOURCE=199309L -O3 -g -Wall -Wextra -Werror -Wno-type-limits
|
CXXFLAGS += -std=c++20 -D_POSIX_C_SOURCE=199309L -O3 -g -Wall -Wextra -Werror -Wno-type-limits
|
||||||
TIMEOUT ?= 10
|
TIMEOUT ?= 10
|
||||||
|
|
||||||
INSTALL_FILE := /opt/interception/interception-pipe-maricn-remap
|
INSTALL_FILE := /opt/interception/interception-pipe-maricn-remap
|
||||||
@@ -8,8 +8,8 @@ TARGET = remap
|
|||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(TARGET).c
|
$(TARGET): $(TARGET).cpp
|
||||||
$(CC) $(CFLAGS) -o $(TARGET) $(TARGET).c
|
$(CXX) $(CXXFLAGS) -o $(TARGET) $(TARGET).cpp
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
@@ -22,6 +22,6 @@ install:
|
|||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test:
|
test:
|
||||||
CFLAGS=-DVERBOSE make
|
CXXFLAGS=-DVERBOSE make
|
||||||
make install
|
make install
|
||||||
timeout $(TIMEOUT) udevmon -c /etc/udevmon.yaml
|
timeout $(TIMEOUT) udevmon -c /etc/udevmon.yaml
|
||||||
|
|||||||
172
remap.c
172
remap.c
@@ -1,172 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include <linux/input.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Global constants
|
|
||||||
**/
|
|
||||||
#define MS_TO_NS 1000000L // 1 millisecond = 1,000,000 Nanoseconds
|
|
||||||
const int KEY_STROKE_UP = 0, KEY_STROKE_DOWN = 1, KEY_STROKE_REPEAT = 2;
|
|
||||||
const int INPUT_BUFFER_SIZE = 16;
|
|
||||||
const long SLEEP_INTERVAL_NS = 20 * MS_TO_NS;
|
|
||||||
const int input_event_struct_size = sizeof(struct input_event);
|
|
||||||
|
|
||||||
int map_space[KEY_MAX];
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
const struct input_event
|
|
||||||
_space_up = {.type = EV_KEY, .code = KEY_SPACE, .value = KEY_STROKE_UP},
|
|
||||||
_meta_up = {.type = EV_KEY, .code = KEY_LEFTMETA, .value = KEY_STROKE_UP},
|
|
||||||
_space_down = {.type = EV_KEY, .code = KEY_SPACE, .value = KEY_STROKE_DOWN},
|
|
||||||
_meta_down = {.type = EV_KEY, .code = KEY_LEFTMETA, .value = KEY_STROKE_DOWN},
|
|
||||||
_space_repeat = {.type = EV_KEY, .code = KEY_SPACE, .value = KEY_STROKE_REPEAT},
|
|
||||||
_meta_repeat = {.type = EV_KEY, .code = KEY_LEFTMETA, .value = KEY_STROKE_REPEAT},
|
|
||||||
_syn = {.type = EV_SYN, .code = SYN_REPORT, .value = KEY_STROKE_UP};
|
|
||||||
const struct input_event
|
|
||||||
*space_up = &_space_up,
|
|
||||||
*meta_up = &_meta_up,
|
|
||||||
*space_down = &_space_down,
|
|
||||||
*meta_down = &_meta_down,
|
|
||||||
*space_repeat = &_space_repeat,
|
|
||||||
*meta_repeat = &_meta_repeat,
|
|
||||||
*syn = &_syn;
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
/*
|
|
||||||
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() {
|
|
||||||
map_space[KEY_H] = KEY_LEFT;
|
|
||||||
map_space[KEY_J] = KEY_DOWN;
|
|
||||||
map_space[KEY_K] = KEY_UP;
|
|
||||||
map_space[KEY_L] = KEY_RIGHT;
|
|
||||||
}
|
|
||||||
|
|
||||||
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, 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_events(const struct input_event *ev1,
|
|
||||||
const struct input_event *ev2) {
|
|
||||||
const struct input_event buffer[3] = {*ev1, _syn, *ev2};
|
|
||||||
if (fwrite(&buffer, input_event_struct_size, 3, stdout) != 3)
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
struct input_event *input =
|
|
||||||
(struct input_event *)malloc(input_event_struct_size);
|
|
||||||
struct input_event *input_mapped_down =
|
|
||||||
(struct input_event *)malloc(input_event_struct_size),
|
|
||||||
*input_origin_up =
|
|
||||||
(struct input_event *)malloc(input_event_struct_size),
|
|
||||||
*input_mapped_up =
|
|
||||||
(struct input_event *)malloc(input_event_struct_size);
|
|
||||||
*input_mapped_down = *space_down;
|
|
||||||
*input_origin_up = *space_up;
|
|
||||||
*input_mapped_up = *space_up;
|
|
||||||
enum { START, SPACE_HELD, KEY_HELD } state = START;
|
|
||||||
int space_down_not_emitted = 1;
|
|
||||||
|
|
||||||
map_space_init();
|
|
||||||
|
|
||||||
setbuf(stdin, NULL), setbuf(stdout, NULL);
|
|
||||||
|
|
||||||
while (read_event(input)) {
|
|
||||||
if (input->type == EV_MSC && input->code == MSC_SCAN)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (input->type != EV_KEY) {
|
|
||||||
write_event(input);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (state) {
|
|
||||||
case START:
|
|
||||||
if (equal(input, space_down) || equal(input, space_repeat)) {
|
|
||||||
state = SPACE_HELD;
|
|
||||||
space_down_not_emitted = 1;
|
|
||||||
} else {
|
|
||||||
write_event(input);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SPACE_HELD:
|
|
||||||
if (equal(input, space_down) || equal(input, space_repeat))
|
|
||||||
break;
|
|
||||||
if (input->value == KEY_STROKE_DOWN) {
|
|
||||||
if (map_space[input->code] != 0) {
|
|
||||||
// TODO: any mapped key needs to go to a set of HELD keys and
|
|
||||||
// only when last of HELD keys is released, we can go back to SPACE_HELD state
|
|
||||||
// we should also accept new HELD keys while in KEY_HELD state
|
|
||||||
*input_origin_up = *input;
|
|
||||||
input_origin_up->value = KEY_STROKE_UP;
|
|
||||||
|
|
||||||
*input_mapped_down = *input;
|
|
||||||
input_mapped_down->code = map_space[input->code];
|
|
||||||
|
|
||||||
*input_mapped_up = *input_mapped_down;
|
|
||||||
input_mapped_up->value = KEY_STROKE_UP;
|
|
||||||
|
|
||||||
write_event(input_mapped_down);
|
|
||||||
state = KEY_HELD;
|
|
||||||
} else {
|
|
||||||
write_event(input);
|
|
||||||
}
|
|
||||||
} else { // KEY_STROKE_REPEAT or KEY_STROKE_UP
|
|
||||||
if (input->code == KEY_SPACE && space_down_not_emitted) {
|
|
||||||
write_events(space_down, input);
|
|
||||||
space_down_not_emitted = 0;
|
|
||||||
} else {
|
|
||||||
write_event(input);
|
|
||||||
}
|
|
||||||
state = equal(input, space_up) ? START : SPACE_HELD;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case KEY_HELD:
|
|
||||||
if (equal(input, space_down) || equal(input, space_repeat))
|
|
||||||
break;
|
|
||||||
if (equal(input, input_mapped_down)) // || equal(input, key_repeat))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (equal(input, input_origin_up)) {
|
|
||||||
write_event(input_mapped_up);
|
|
||||||
state = SPACE_HELD;
|
|
||||||
// even if it actually wasn't emitted, we don't want to emit it
|
|
||||||
// after we made sure space is supposed to behave as function key
|
|
||||||
space_down_not_emitted = 0;
|
|
||||||
} else {
|
|
||||||
write_event(input);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(input);
|
|
||||||
}
|
|
||||||
220
remap.cpp
Normal file
220
remap.cpp
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <set>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global constants
|
||||||
|
**/
|
||||||
|
#define MS_TO_NS 1000000L // 1 millisecond = 1,000,000 Nanoseconds
|
||||||
|
const int KEY_STROKE_UP = 0, KEY_STROKE_DOWN = 1, KEY_STROKE_REPEAT = 2;
|
||||||
|
const int INPUT_BUFFER_SIZE = 16;
|
||||||
|
const long SLEEP_INTERVAL_NS = 20 * MS_TO_NS;
|
||||||
|
const int input_event_struct_size = sizeof(struct input_event);
|
||||||
|
|
||||||
|
int map_space[KEY_MAX];
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
const struct input_event
|
||||||
|
_space_up = {.time = { .tv_sec = 0, .tv_usec = 0}, .type = EV_KEY, .code = KEY_SPACE, .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
|
||||||
|
*space_up = &_space_up,
|
||||||
|
*space_down = &_space_down,
|
||||||
|
*space_repeat = &_space_repeat,
|
||||||
|
*syn = &_syn;
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
/*
|
||||||
|
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() {
|
||||||
|
// vim home row
|
||||||
|
map_space[KEY_H] = KEY_LEFT;
|
||||||
|
map_space[KEY_J] = KEY_DOWN;
|
||||||
|
map_space[KEY_K] = KEY_UP;
|
||||||
|
map_space[KEY_L] = KEY_RIGHT;
|
||||||
|
|
||||||
|
// number row to F keys
|
||||||
|
map_space[KEY_1] = KEY_F1;
|
||||||
|
map_space[KEY_2] = KEY_F2;
|
||||||
|
map_space[KEY_3] = KEY_F3;
|
||||||
|
map_space[KEY_4] = KEY_F4;
|
||||||
|
map_space[KEY_5] = KEY_F5;
|
||||||
|
map_space[KEY_6] = KEY_F6;
|
||||||
|
map_space[KEY_7] = KEY_F7;
|
||||||
|
map_space[KEY_8] = KEY_F8;
|
||||||
|
map_space[KEY_9] = KEY_F9;
|
||||||
|
map_space[KEY_0] = KEY_F10;
|
||||||
|
map_space[KEY_MINUS] = KEY_F11;
|
||||||
|
map_space[KEY_EQUAL] = KEY_F12;
|
||||||
|
|
||||||
|
// xf86 audio
|
||||||
|
map_space[KEY_M] = KEY_MUTE;
|
||||||
|
map_space[KEY_COMMA] = KEY_VOLUMEDOWN;
|
||||||
|
map_space[KEY_DOT] = KEY_VOLUMEUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto cmp = [](const struct input_event *e1, const struct input_event *e2) {
|
||||||
|
return equal(e1, e2) != 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_events(std::vector<struct input_event> *events) {
|
||||||
|
const unsigned long size = events->size();
|
||||||
|
if (fwrite(events->data(), input_event_struct_size, size, stdout) != size)
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct input_event *map(const struct input_event *input, int direction = -1) {
|
||||||
|
struct input_event *result = new input_event(*input);
|
||||||
|
result->code = map_space[input->code];
|
||||||
|
if (direction != -1) {
|
||||||
|
result->value = direction;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
struct input_event *input = new input_event();
|
||||||
|
std::set<int> held_keys;
|
||||||
|
enum { START, SPACE_HELD, KEY_HELD } state = START;
|
||||||
|
int space_down_not_emitted = 1;
|
||||||
|
|
||||||
|
map_space_init();
|
||||||
|
setbuf(stdin, NULL), setbuf(stdout, NULL);
|
||||||
|
|
||||||
|
while (read_event(input)) {
|
||||||
|
if (input->type == EV_MSC && input->code == MSC_SCAN)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (input->type != EV_KEY) {
|
||||||
|
write_event(input);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case START:
|
||||||
|
if (equal(input, space_down) || equal(input, space_repeat)) {
|
||||||
|
state = SPACE_HELD;
|
||||||
|
space_down_not_emitted = 1;
|
||||||
|
} else {
|
||||||
|
write_event(input);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SPACE_HELD:
|
||||||
|
if (equal(input, space_down) || equal(input, space_repeat))
|
||||||
|
break;
|
||||||
|
if (input->value == KEY_STROKE_DOWN) {
|
||||||
|
if (map_space[input->code] != 0) {
|
||||||
|
held_keys.insert(input->code);
|
||||||
|
space_down_not_emitted = 0;
|
||||||
|
struct input_event *mapped_input = map(input);
|
||||||
|
write_event(mapped_input);
|
||||||
|
delete mapped_input;
|
||||||
|
state = KEY_HELD;
|
||||||
|
} else {
|
||||||
|
write_event(input);
|
||||||
|
}
|
||||||
|
} else { // KEY_STROKE_REPEAT or KEY_STROKE_UP
|
||||||
|
if (input->code == KEY_SPACE && space_down_not_emitted) {
|
||||||
|
space_down_not_emitted = 0;
|
||||||
|
struct input_event space_down_var(*space_down);
|
||||||
|
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 {
|
||||||
|
write_event(input);
|
||||||
|
}
|
||||||
|
state = equal(input, space_up) ? START : SPACE_HELD;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_HELD:
|
||||||
|
if (equal(input, space_down) || equal(input, space_repeat))
|
||||||
|
break;
|
||||||
|
if (input->value == KEY_STROKE_DOWN &&
|
||||||
|
held_keys.find(input->code) != held_keys.end()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input->value == KEY_STROKE_UP) {
|
||||||
|
if (held_keys.find(input->code) != held_keys.end()) { // one of mapped held keys goes up
|
||||||
|
write_event(map(input));
|
||||||
|
held_keys.erase(input->code);
|
||||||
|
if (held_keys.empty()) {
|
||||||
|
state = SPACE_HELD;
|
||||||
|
}
|
||||||
|
} else { // regular key goes up
|
||||||
|
if (equal(input, space_up)) {
|
||||||
|
std::vector<struct input_event> *held_keys_up =
|
||||||
|
new std::vector<struct input_event>();
|
||||||
|
for (auto held_key_code : held_keys) {
|
||||||
|
struct input_event held_key_up;
|
||||||
|
held_key_up.code = held_key_code;
|
||||||
|
held_key_up.value = KEY_STROKE_UP;
|
||||||
|
held_keys_up->push_back(held_key_up);
|
||||||
|
}
|
||||||
|
held_keys_up->push_back(*space_up);
|
||||||
|
|
||||||
|
write_events(held_keys_up);
|
||||||
|
delete held_keys_up;
|
||||||
|
held_keys.clear();
|
||||||
|
state = START;
|
||||||
|
} else {
|
||||||
|
write_event(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // KEY_STROKE_DOWN or KEY_STROKE_REPEAT
|
||||||
|
if (map_space[input->code] != 0) {
|
||||||
|
auto mapped = map(input);
|
||||||
|
write_event(mapped);
|
||||||
|
delete mapped;
|
||||||
|
if (input->value == KEY_STROKE_DOWN) {
|
||||||
|
held_keys.insert(input->code);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
write_event(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(input);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user