summaryrefslogtreecommitdiff
path: root/pen-fix
diff options
context:
space:
mode:
Diffstat (limited to 'pen-fix')
-rw-r--r--pen-fix/main.cpp113
1 files changed, 113 insertions, 0 deletions
diff --git a/pen-fix/main.cpp b/pen-fix/main.cpp
new file mode 100644
index 0000000..4688f28
--- /dev/null
+++ b/pen-fix/main.cpp
@@ -0,0 +1,113 @@
+#include <algorithm>
+#include <cstdio>
+#include <linux/input-event-codes.h>
+#include <linux/input.h>
+#include <poll.h>
+#include <sys/poll.h>
+#include <unistd.h>
+#include <utility>
+#include <vector>
+
+auto flush(std::vector<input_event> & frame) -> void
+{
+ std::ranges::for_each(frame, [](auto event) { std::fwrite(&event, sizeof(event), 1, stdout); });
+
+ std::fflush(stdout);
+ frame.clear();
+}
+
+auto main() -> int
+{
+ auto poll_descriptor = pollfd{.fd = STDIN_FILENO, .events = POLLIN, .revents = 0};
+
+ auto current_frame = std::vector<struct input_event>{};
+ auto deferred_frame = std::vector<struct input_event>{};
+ auto waiting_for_rubber_tool = false;
+
+ while (true)
+ {
+ auto timeout_ms = waiting_for_rubber_tool ? 50 : -1;
+ auto ret = poll(&poll_descriptor, 1, timeout_ms);
+
+ if (ret == 0)
+ {
+ if (waiting_for_rubber_tool)
+ {
+ flush(deferred_frame);
+ waiting_for_rubber_tool = false;
+ }
+ continue;
+ }
+
+ if (ret < 0)
+ {
+ break;
+ }
+
+ auto event = input_event{};
+ if (std::fread(&event, sizeof(event), 1, stdin) != 1)
+ {
+ break;
+ }
+
+ current_frame.push_back(event);
+
+ if (event.type == EV_SYN && event.code == SYN_REPORT)
+ {
+ auto has_pen_leave = false;
+ auto has_rubber_enter = false;
+ auto has_rubber_leave = false;
+
+ std::ranges::for_each(current_frame, [&](auto event) {
+ if (event.type == EV_KEY && event.code == BTN_TOOL_PEN && event.value == 0)
+ has_pen_leave = true;
+ if (event.type == EV_KEY && event.code == BTN_TOOL_RUBBER && event.value == 1)
+ has_rubber_enter = true;
+ if (event.type == EV_KEY && event.code == BTN_TOOL_RUBBER && event.value == 0)
+ has_rubber_leave = true;
+ });
+
+ if (has_pen_leave)
+ {
+ deferred_frame = std::move(current_frame);
+ waiting_for_rubber_tool = true;
+ }
+ else if (has_rubber_enter || has_rubber_leave)
+ {
+ auto mutated_frame = std::vector<input_event>{};
+
+ for (auto const & e : current_frame)
+ {
+ if (e.type == EV_KEY && e.code == BTN_TOOL_RUBBER)
+ {
+ struct input_event mutated_btn = e;
+ mutated_btn.code = BTN_STYLUS2;
+ mutated_frame.push_back(mutated_btn);
+ }
+ else if (e.type == EV_ABS)
+ {
+ continue;
+ }
+ else
+ {
+ mutated_frame.push_back(e);
+ }
+ }
+ deferred_frame.clear();
+ waiting_for_rubber_tool = false;
+ flush(mutated_frame);
+ }
+ else
+ {
+ if (waiting_for_rubber_tool)
+ {
+ flush(deferred_frame);
+ waiting_for_rubber_tool = false;
+ }
+ flush(current_frame);
+ }
+ current_frame.clear();
+ }
+ }
+ return 0;
+}