I'm especially wondering if we even need the 'snapToPixel' property at all.
I never needed it, never saw it being used or set somewhere else.

With that said, I was also wondering about potential consequences to performance if we try to track the parent snapping property. If we move forward with that, we need to find a good implementation for that.

-- Marius

On 9/9/26 4:52 PM, John Hendrikx wrote:
The docs on `snapToPixelProperty` state:

/**

* Defines whether this region adjusts position, spacing, and size values of

* its children to pixel boundaries. This defaults to true, which is
generally

* the expected behavior in order to have crisp user interfaces. A value of

* false will allow for fractional alignment, which may lead to "fuzzy"

* looking borders.

*/

This does leave a lot ambiguous as to what should happen when a region
is not snapped, but its children (or grand children) are snapped again.

The problem:

1. When an ancestor is unsnapped, no amount of snapping of children will
return the claimed "crisp user interfaces" for those children.  Once an
ancestor decides to allocate a non-integer number of pixels at a
non-grid aligned location, even snapped children will not look crisp.

2. Children that are snapped that receive a width/height that is not an
integer multiple will be faced with a dilemma:

   - Do they round their width/height down to not exceed their allocated
size?
   - Do they round it up to ensure they cover the allocated size
potentially overlapping another child of the unsnapped parent?
      - That could undo whatever the parent was trying to achieve...

   - What do they do with those fractional pixels that are left over when
distributing (snapped) space over their own children?
      - Add the "left over" space to one of those, which then pushes the
problem down another layer (the grand child receives a non-integer
number of pixels from a snapped(!!) parent)?
      - Not pass them down to any child, but let the background of the
container fill that space?

The current implementation in JavaFX for this situation, an unsnapped
parent with snapped children,  essentially ignores these questions and
allows the layout algorithm to use the width and height as given. The
result can therefore depend on the exact implementation and order of
calculations, without the situation itself being explicitly accounted for.

Furthermore, re-enabling snapping below an unsnapped ancestor seems
counterintuitive and is unlikely to be useful in practice. If an
ancestor has explicitly opted out of pixel snapping, descendants cannot
generally undo that decision without either compromising the ancestor's
positioning or size allocations, or propagating the fractional-layout
problem further down the hierarchy

Proposal:

I think the existing API documentation has enough leeway to change how
we implement snapping in the case of an unsnapped ancestor.  I therefore
propose to make snapping dependent on the ancestor.  A node is only
snapped if all of its ancestors are snapped.

This would eliminate a number of ambiguities with relatively little
downside:

- As today, children of an unsnapped container can still end up looking
fuzzy. However, they would follow the unsnapped calculation path rather
than being presented with an inconsistent combination of snapped and
unsnapped constraints.
- There would be no need to define how a snapped child should resolve
fractional space received from an unsnapped parent.
- We would not need to decide where fractional space should go when
distributing space among descendants, or whether that space should be
propagated to another level.
- We would avoid having a snapped child round its dimensions up or down
in a way that could contradict the layout decisions made by its
unsnapped parent.

So once an ancestor opts out of snapping, that should apply to the
entire subtree.  This makes it much more predictable (and also is likely
what was intended) and avoids having to find an unsatisfactory solution
for all the edge cases when combining snapped nodes with unsnapped
ancestors.

I'm curious what others think, and this is relevant as we're about to
enshrine snapping rules in the next release I think.

--John

Reply via email to