Skip to content

Collect pen ink from the pen, and add straight-line strokes - #73

Merged
marcosqlbi merged 2 commits into
mainfrom
feature/shift-straight-lines
Aug 26, 2026
Merged

Collect pen ink from the pen, and add straight-line strokes#73
marcosqlbi merged 2 commits into
mainfrom
feature/shift-straight-lines

Conversation

@marcosqlbi

Copy link
Copy Markdown
Collaborator

Straight-line strokes on Shift and on the pen's barrel button, and the ink path
that had to change for the button to work at all.

Straight lines

Holding Shift, or the barrel button when it is assigned to Straight line,
constrains the stroke to horizontal or vertical — whichever the first 24 px of
travel is nearer — at a uniform width. The axis is settled once and kept for the
whole segment, however far off it the hand drifts. Press or release at any time:
the part already drawn stays straight and the rest goes freehand from there.

Why the ink path changed

On a pen whose barrel switch shares its report with the tip switch, pressing or
releasing that button fabricates a stylus up followed by a stylus down, and
between a release and the next press the driver reports the tip as open while it
is still pressing. WPF tears the contact in two on every click and calls the pen
airborne in between, so an InkCanvas stroke joined stretches the pen never drew
and lost the ones it did. Several attempts to repair that from inside the
InkCanvas each moved the fault rather than removing it.

The pen's own packet stream never breaks — a trace of a real session established
that — so MainWindow.AppendPenInk now reads it directly and owns the contact,
the straight-line constraint and the calligraphy dynamics, with
BoardSurface.PendingStroke drawing the wet stroke. The constraint is then one
boolean read per point, which is what makes the button behave exactly like Shift:
neither has any opinion about whether WPF thinks the pen is down. Recorded as
decision 22.

PenOnlyInkCanvas becomes TouchInkCanvas and keeps the InkCanvas for finger
ink only, where nothing tears the contact.

Pen buttons

One configurable barrel button, Laser (default) or Straight line. Erasing is not
assignable: the reverse end of the pen erases, and so does the upper side button,
because Windows describes both by inverting the stylus and the trace shows the
two producing identical events on this hardware. PenTrace — off unless
SQLBI_WHITEBOARD_PENTRACE names a file — is what settled that, and is kept for
the next pen question.

Preferences

Pen button, Toolbar position and Toolbar layout now draw their options instead of
naming them, sharing one builder with the laser trail weights.

Also

Version 1.1.1. README architecture notes, site/shortcuts.html and
site/guide.html brought up to date; TODO records the hardware findings and the
two constants that stand in for signals the hardware does not give.

Release build clean with TreatWarningsAsErrors, smoke tests pass.

🤖 Generated with Claude Code

Alberto-Ferrari and others added 2 commits August 26, 2026 05:19
The barrel switch on a pen that shares its report with the tip switch
fabricates a stylus up and a stylus down on every press and every
release, and reports the tip as open while it is still pressing. WPF
therefore tears the contact in two per click and calls the pen airborne
in between, so no stroke the InkCanvas collected could follow it.

MainWindow.AppendPenInk now reads the pen packets directly and owns the
contact, the straight-line constraint and the calligraphy dynamics, with
BoardSurface.PendingStroke drawing the wet stroke. The constraint is one
boolean per point, so the barrel button behaves exactly like Shift.

TouchInkCanvas keeps the InkCanvas for finger ink only. The pen button
is a single configurable barrel button (Laser or Straight line); the
reverse end and the upper side button always erase, because Windows
reports the two identically. Preferences draws the options for the pen
button, toolbar position and toolbar layout instead of naming them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@marcosqlbi
marcosqlbi merged commit 825cf96 into main Aug 26, 2026
4 checks passed
@marcosqlbi
marcosqlbi deleted the feature/shift-straight-lines branch August 26, 2026 17:53
marcosqlbi added a commit that referenced this pull request Aug 27, 2026
Fixes a regression from #73.

Pen ink moved out of the `InkCanvas` and into `BoardSurface.OnRender`,
where draw
order matters — and the pending stroke was drawn *before* the loop over
document
objects. Images, text and LiveViews therefore painted straight over the
wet ink,
so a stroke crossing a container was invisible exactly where it
overlapped and
appeared all at once on lift, when it commits with the topmost z-index.

It is now drawn after the objects and before the hover and selection
chrome,
which is where it will sit once committed.

Version 1.1.2. Release build clean with `TreatWarningsAsErrors`, smoke
tests pass.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
marcosqlbi added a commit that referenced this pull request Aug 29, 2026
The drawn choices added in #73 — Pen button, Toolbar position, Toolbar
layout —
were clipped when the Preferences dialog was narrowed. Toolbar /
Position is the
one that showed it: five options in a row, and at the dialog's 560 px
minimum
each segment holds about 52 px inside its padding, against the ~44 px
"Bottom"
needs. A word too long for its line overflows and is clipped rather than
wrapped,
and `TextTrimming` does not help because it applies only when the height
is
constrained — so the label read as a different word, "Bottor right".

## The row reflows

The choices now sit in a small panel that measures and arranges its own
children,
taking its column count from the width the row actually occupies. Five
choices
stay in one row when there is room and fall to 4+1 and then 3+2 as the
dialog
narrows, rather than shrinking past legibility.

Two earlier attempts are worth recording, because both looked right and
neither
was. Recomputing on `SizeChanged` only fires when the width changes, so
the count
settled during the first layout pass stood for the life of the dialog.
Moving it
to `MeasureOverride` fixed the staleness but not the cause: the width a
row is
measured against arrives far narrower than the width it is finally
given, so the
count was still computed against a width the row never had.
`ArrangeOverride` has
the real width, and that is what it now reads.

## The samples scale

Each sample is wrapped in a down-only `Viewbox`, so it draws at its
designed size
when there is room and shrinks with the column instead of overflowing
and losing
its edges. The segment template honours `HorizontalContentAlignment` so
the label
is given the width it is measured against, and the padding drops from
`10,12` to
`6,12`.

Version 1.1.4. Release build clean with `TreatWarningsAsErrors`, smoke
tests pass.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants