You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Stylus on tablet: strokes break up, and pencil pressure is ignored #338
Two symptoms, filed together because they share the stylus input path and may share a cause:
The line breaks up — a stroke comes out in pieces instead of one continuous line.
Pencil pressure does nothing — width does not follow how hard the pen is pressed.
What is already ruled out
setPointerCapture is set on pointer down (hooks/useGesture.ts:51), so losing the pointer off
the element is not it.
touch-action: none is on the canvas and its wrapper (ui/CanvasStage.tsx:73,91), so the
browser's own scroll/zoom gesture is not stealing the move events.
If the tablet reports the pencil as pointerType === 'touch' rather than 'pen' — some
Android stylus stacks do — then pen is false. The renderer then falls back to the heuristic at canvas/strokes.ts:411, which decides there is pressure only if some point differs from 0.5.
Touch pointers commonly report pressure as a constant 1, or 0. A constant is not 0.5, so
the heuristic would say "has pressure" and then draw every point at the same width — which
looks exactly like pressure being ignored.
Worth logging pointerType, pressure and getCoalescedEvents().length from the actual device
before changing anything. Which of these it is decides the fix.
Leads for the breaking-up half
samplesOf (App.tsx:1138) only expands coalesced events when raw.length > 1, so it is not
dropping the single-sample case.
More likely somewhere in the live overlay's rAF throttle, or a re-render dropping the in-progress
stroke. Needs reproducing with the event stream logged.
Unknown whether the two are one bug or two; splitting this issue is fine once the device log says.
Both halves are now on main, found by measurement rather than on the device. Leaving this open until it is confirmed on the tablet.
Pencil pressure ignored — #360. The width term was 0.65 + 0.35 * Math.min(1, pr * 2), and the * 2 puts the neutral 0.5 at 1×, so the clamp bit at exactly neutral: every press above it drew the same stroke to the pixel.
pressure
0.1
0.25
0.5
0.6
0.75
0.9
1.0
before
18
20
24
24
24
24
24
after
18
20
24
26
28
32
34
A stylus writes well above 0.5, so the whole range you actually press in was flat. Checked byte-for-byte that mouse strokes and every pressure at or below neutral render identically, so existing drawings are untouched.
Strokes break up — #361. A PC has one pointer; a tablet has the pen and the palm. startDraw refused to begin from a touch, but nothing stopped a touch from feeding the gesture already running — the palm's moves were appended to the pen's stroke as points, and the palm lifting committed the stroke mid-line. The gesture already knew whose pointer it was; pointerId was set by begin() and read by nobody.
To check on the tablet
필압 on, pencil, draw light → hard. The line should visibly thicken; before, anything past a light press was one fixed width.
Draw a long line with your hand resting on the screen — that is the condition the break-up needs. It should stay one unbroken stroke.
Existing drawings should look exactly as they did.
If (2) still breaks up, it is a different cause from the palm and worth saying so — the pointer-ownership half is pinned by tests, so a remaining symptom points somewhere else.
Activity
fix: the pencil keeps answering pressure above the neutral point (#338)
fix: a palm on the glass no longer drives the pen's stroke (#338)
fix: the pencil keeps answering pressure above the neutral point (#338)
fix: a palm on the glass no longer drives the pen's stroke (#338)
fix: a palm on the glass no longer drives the pen's stroke (#338)
difficcd commentedon Oct 6, 2026
Both halves are now on
main, found by measurement rather than on the device. Leaving this open until it is confirmed on the tablet.Pencil pressure ignored — #360. The width term was
0.65 + 0.35 * Math.min(1, pr * 2), and the* 2puts the neutral 0.5 at 1×, so the clamp bit at exactly neutral: every press above it drew the same stroke to the pixel.A stylus writes well above 0.5, so the whole range you actually press in was flat. Checked byte-for-byte that mouse strokes and every pressure at or below neutral render identically, so existing drawings are untouched.
Strokes break up — #361. A PC has one pointer; a tablet has the pen and the palm.
startDrawrefused to begin from a touch, but nothing stopped a touch from feeding the gesture already running — the palm's moves were appended to the pen's stroke as points, and the palm lifting committed the stroke mid-line. The gesture already knew whose pointer it was;pointerIdwas set bybegin()and read by nobody.To check on the tablet
If (2) still breaks up, it is a different cause from the palm and worth saying so — the pointer-ownership half is pinned by tests, so a remaining symptom points somewhere else.
chore(process): measure the process, then fix what the measurement found