Initial commit: Chatter — assistive-writing app for reMarkable Paper Pro Move

Direct-framebuffer ink pipeline (stock-quality strokes), finger-wipe erase,
growable scrolling canvas with color-ghost cleanup, bidirectional toggle with a
persistent 4-finger return launcher, instant button feedback. Includes prebuilt
aarch64 binaries (dist/), build/deploy/install scripts, a user guide, and a
complete technical reference.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-27 16:34:28 +02:00
commit 5f21d9099c
43 changed files with 2878 additions and 0 deletions

46
tools/swapshim.cpp Normal file
View File

@@ -0,0 +1,46 @@
// LD_PRELOAD trace shim: intercept EPFramebuffer::swapBuffers in libqsgepaper to
// learn the exact (contentType, screenMode, flags) the stock app uses for pen
// strokes. We define functions with the real mangled names so the dynamic loader
// interposes them, log the args, then chain to the real implementation.
//
// QRect is passed by value; its memory layout is {int x1,y1,x2,y2} (l,t,r,b), so
// we model it as a 16-byte POD to match the ABI without linking Qt. The enums and
// QFlags are all 4-byte int-sized.
#include <dlfcn.h>
#include <cstdio>
struct RawRect { int x1, y1, x2, y2; };
extern "C" {
// swapBuffers(QRect, EPContentType, EPScreenMode, QFlags<UpdateFlag>)
void _ZN13EPFramebuffer11swapBuffersE5QRect13EPContentType12EPScreenMode6QFlagsINS_10UpdateFlagEE(
void *self, RawRect r, int contentType, int screenMode, int flags)
{
static void (*real)(void *, RawRect, int, int, int) = nullptr;
if (!real)
real = (void (*)(void *, RawRect, int, int, int))dlsym(
RTLD_NEXT,
"_ZN13EPFramebuffer11swapBuffersE5QRect13EPContentType12EPScreenMode6QFlagsINS_10UpdateFlagEE");
fprintf(stderr, "SWAPTRACE1 rect=(%d,%d)-(%d,%d) %dx%d content=%d screen=%d flags=%d\n",
r.x1, r.y1, r.x2, r.y2, r.x2 - r.x1 + 1, r.y2 - r.y1 + 1,
contentType, screenMode, flags);
if (real) real(self, r, contentType, screenMode, flags);
}
// swapBuffers(const QRegion&, const EPContentMap&, const EPScreenModeMap&, QFlags<UpdateFlag>)
void _ZN13EPFramebuffer11swapBuffersERK7QRegionRK12EPContentMapRK15EPScreenModeMap6QFlagsINS_10UpdateFlagEE(
void *self, const void *region, const void *contentMap, const void *modeMap, int flags)
{
static void (*real)(void *, const void *, const void *, const void *, int) = nullptr;
if (!real)
real = (void (*)(void *, const void *, const void *, const void *, int))dlsym(
RTLD_NEXT,
"_ZN13EPFramebuffer11swapBuffersERK7QRegionRK12EPContentMapRK15EPScreenModeMap6QFlagsINS_10UpdateFlagEE");
fprintf(stderr, "SWAPTRACE2 region=%p contentMap=%p modeMap=%p flags=%d\n",
region, contentMap, modeMap, flags);
if (real) real(self, region, contentMap, modeMap, flags);
}
} // extern "C"