summaryrefslogtreecommitdiff
path: root/pen-fix/main.cpp
blob: 4688f28f247411ac5716f6f3809096b096dc9c1c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
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;
}