summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@gmail.com>2026-04-09 17:46:26 +0200
committerFelix Morgner <felix.morgner@gmail.com>2026-04-09 17:46:26 +0200
commit614037c9af4641217ecd03d36baa41911d3c2680 (patch)
tree4e719d98caf85fcb61c4eac6ff1e4bc0ac5d7e21
downloadpen-fix-614037c9af4641217ecd03d36baa41911d3c2680.tar.xz
pen-fix-614037c9af4641217ecd03d36baa41911d3c2680.zip
initial commitmaster
-rw-r--r--.clang-format120
-rw-r--r--.gitignore1
-rw-r--r--CMakeLists.txt13
-rw-r--r--pen-fix/main.cpp113
4 files changed, 247 insertions, 0 deletions
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..e54cb03
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,120 @@
+---
+AccessModifierOffset: "-2"
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments:
+ Enabled: false
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCompound: false
+ AlignFunctionPointers: false
+ PadOperators: true
+AlignConsecutiveDeclarations:
+ Enabled: false
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCompound: false
+ AlignFunctionPointers: false
+ PadOperators: true
+AlignEscapedNewlines: LeftWithLastLine
+AlignTrailingComments: "true"
+AllowAllParametersOfDeclarationOnNextLine: "true"
+AllowShortBlocksOnASingleLine: Never
+AllowShortCaseLabelsOnASingleLine: "false"
+AllowShortFunctionsOnASingleLine: Empty
+AllowShortIfStatementsOnASingleLine: Never
+AllowShortLoopsOnASingleLine: "false"
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakTemplateDeclarations: "true"
+BinPackArguments: "true"
+BinPackParameters: "true"
+BreakBeforeBraces: Custom
+BraceWrapping:
+ AfterClass: "true"
+ AfterControlStatement: "true"
+ AfterEnum: "true"
+ AfterFunction: "true"
+ AfterNamespace: "true"
+ AfterStruct: "true"
+ AfterUnion: "true"
+ AfterExternBlock: "true"
+ BeforeCatch: "true"
+ BeforeElse: "true"
+ IndentBraces: "false"
+ AfterCaseLabel: true
+ SplitEmptyFunction: false
+ SplitEmptyRecord: true
+ SplitEmptyNamespace: true
+BreakBeforeInheritanceComma: "false"
+BreakConstructorInitializers: BeforeComma
+BreakStringLiterals: "true"
+ColumnLimit: "120"
+CompactNamespaces: "false"
+Cpp11BracedListStyle: "true"
+DerivePointerAlignment: "false"
+FixNamespaceComments: "true"
+IncludeBlocks: Regroup
+IncludeCategories:
+ - Regex: 'kapi/[[:alnum:]._\/]+\.hpp'
+ Priority: 100
+ - Regex: 'x86_64/[[:alnum:]._\/]+\.hpp'
+ Priority: 110
+ - Regex: '"[[:alnum:]._\/]+\.hpp"'
+ Priority: 300
+ - Regex: '<kstd/[[:alnum:]._\/]+>'
+ Priority: 400
+ - Regex: '<[[:alnum:]._\/]+\.hpp>'
+ Priority: 600
+ - Regex: '<[[:alnum:]._]+(?!\.(h|hpp))>'
+ Priority: 900
+IndentCaseLabels: "true"
+IndentPPDirectives: None
+IndentWidth: "2"
+KeepEmptyLinesAtTheStartOfBlocks: "false"
+Language: Cpp
+MaxEmptyLinesToKeep: "1"
+NamespaceIndentation: All
+PointerAlignment: Middle
+ReflowComments: "true"
+SortIncludes: "true"
+SortUsingDeclarations: "true"
+SpaceAfterCStyleCast: "false"
+SpaceAfterTemplateKeyword: "false"
+SpaceBeforeAssignmentOperators: "true"
+SpaceBeforeParens: ControlStatements
+SpaceInEmptyParentheses: "false"
+SpacesBeforeTrailingComments: "2"
+SpacesInAngles: "false"
+SpacesInContainerLiterals: "false"
+SpacesInCStyleCastParentheses: "false"
+SpacesInParentheses: "false"
+SpacesInSquareBrackets: "false"
+Standard: Latest
+TabWidth: "2"
+UseTab: Never
+AlignArrayOfStructures: Right
+AlignConsecutiveBitFields: {}
+AllowAllArgumentsOnNextLine: false
+AllowBreakBeforeNoexceptSpecifier: Never
+AllowShortCaseExpressionOnASingleLine: false
+AllowShortCompoundRequirementOnASingleLine: true
+AllowShortEnumsOnASingleLine: false
+AllowShortLambdasOnASingleLine: Inline
+BitFieldColonSpacing: Both
+BracedInitializerIndentWidth: 2
+IntegerLiteralSeparator:
+ Binary: 4
+ BinaryMinDigits: 8
+ Decimal: 3
+ DecimalMinDigits: 6
+ Hex: 4
+ HexMinDigits: 8
+QualifierAlignment: Custom
+QualifierOrder:
+ - constexpr
+ - type
+ - static
+ - inline
+ - const
+SpaceBeforeRangeBasedForLoopColon: true
+SpaceBeforeSquareBrackets: false
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a007fea
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+build/*
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..9d6f6c1
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,13 @@
+cmake_minimum_required(VERSION "3.30.0")
+
+project("pen-fix"
+ LANGUAGES CXX
+)
+
+add_executable("pen-fix"
+ "pen-fix/main.cpp"
+)
+
+target_compile_features("pen-fix" PRIVATE
+ "cxx_std_23"
+)
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;
+}