Repository navigation
fix: a palm on the glass no longer drives the pen's stroke (#338) - #361
Merged
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
difficcd
force-pushed
the
fix/palm-steals-the-pen
branch
from
October 1, 2026 06:19
f83e83d to
40bcd20
Compare
A PC has one pointer, so every event on the canvas belonged to the stroke being drawn and no handler had to ask which pointer it came from. A tablet has several: the pen, and the palm resting on the glass beside it. `startDraw` refused to *begin* a gesture from a touch - the palm rejection that has always been there - but nothing stopped a touch from feeding the gesture already running: - `onDraw` checked only `gesture.drawing.current`, so the palm's moves were appended to the pen's stroke as points, putting a jump across the drawing. - `stopDraw` took no event at all, so it could not check anything: the palm coming off the glass committed the pen's stroke mid-line. The pen then went on moving over a gesture that had ended, drawing nothing until it was lifted and put down again. Which is a line in pieces, on a tablet and nowhere else - #338's "strokes break up". The gesture already knew whose pointer it was; `pointerId` was set by begin() and read by nobody. It is now read, through one predicate both handlers share. Events with no pointer to name still pass, because onPointerLeaveCanvas ends a stroke without one, and so does every event while nothing is in flight, because onDraw does its hover work through the same guard. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
difficcd
force-pushed
the
fix/palm-steals-the-pen
branch
from
October 1, 2026 06:25
40bcd20 to
8d7c2bb
Compare
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The other half of #338 — "펜이 뚝뚝 끊김 (태블릿 환경에서)". Found by reading the pointer handlers rather than on the device, and the asymmetry it turns on is specific enough to be worth stating plainly.
Cause
A PC has one pointer. So every pointer event arriving at the canvas belonged to the stroke being drawn, and no handler ever had to ask which pointer it came from. A tablet has several: the pen, and the palm resting on the glass beside it.
startDrawrefuses to begin a gesture from a touch — the palm rejection that has always been there:But nothing stopped a touch from feeding the gesture already running:
onDrawif (!gesture.drawing.current) return;stopDraw() => {— took no event, so it could check nothingAfter that early commit the pen kept moving over a gesture that had ended, drawing nothing until it was lifted and put back down. A palm that rests and shifts while you write does this repeatedly: a line in pieces, on a tablet and nowhere else.
Change
The gesture already knew whose pointer it was —
pointerIdwas set bybegin()and read by nobody. It is now read, through one predicate inuseGesture.tsthat both handlers share:Two things deliberately pass through:
onPointerLeaveCanvasends a stroke without an event; refusing those would stop leaving the canvas from stopping the stroke.onDrawdoes its hover work through the same guard, and refusing a pointer there would leave the cursor stale over a selection's resize handles.stopDraw's parameter is optional for the same reason.Tests
test/hooks/gesturePointer.test.js, four cases — the owner check, the hover passthrough, the no-event passthrough, and:pointer id 0 is a real pointer, not a missing one— the guard cannot testeventIdfor truthiness, because a first pointer is legitimately id0on some browsers and!0would hand every stroke to whichever pointer came second. That is the shape this fix would most plausibly come back in.1284 tests pass;
npm run checkgreen (460 helpers indexed).To try
On the tablet, draw a long line with the pen while resting your hand on the screen — which is the natural way to draw and the condition this needs. The line should stay one unbroken stroke. Dragging a finger across the canvas mid-stroke should now do nothing to it.
This is the stroke break-up half of #338. The pencil-pressure half is #360.
🤖 Generated with Claude Code