microsoft / microsoft/microsoft-ui-xaml

Grid children overlap by 1px deterministically based on floating-point error

Open
#11,166 0 comments 0 reactions 0 assignees View on GitHub
area-DataGrid area-Lists bug team-Core team-Rendering
Dominant language
C++
Stars
8.4k
Forks
942
Avg merge
2d 7h
Merged PRs (30d)
105

Description

### Describe the bug

When creating a Grid with two child Grids, the two Grids overlap slightly. This happens for specific combinations of the parent's padding and the first child's width.

### Why is this important?

I came across this bug because of a SplitButton in SplitButtonCommandBarStyle. The bug created a nice divider between the two sides on PointerOver. The divider was very noticeable, even if just 1px.

### Steps to reproduce the bug

1. Create a WinUI Blank App (Packaged).
2. Replace the Grid in MainWindow.xaml with the following code.
```xml








```
3. Set DPI scaling to 125%. This *will not* work on 100%.
4. Run. There will be a thin line where the two Grids overlap.

### Actual behavior

A 1px/0.8epx line appears where the two Grids overlap.

### Expected behavior

The Grids should not overlap.

### Screenshots

Image

### NuGet package version

2.2.0

### Windows version

_No response_

### Additional context

To explain exactly which combinations of padding and width...

When scaling is 125%, 1px = 0.8epx. The padding can be any number congruent to 2 mod 4, which will be a midpoint between two multiples of 0.8. The padding and the first child will get rounded up, e.g. 2.4, 10.4 in the repro. However, the second child's positioning will first calculate 10.4 + 2.0, round the value to the nearest multiple of 0.8, and use that rounded value. (I'm just describing the observed behavior, not the implementation)

So, the bug depends on floating point accuracy. Let k satisfy 2^k < v < 2^(k + 1) where v = the previously mentioned value. The following table provides the remainders of v mod 4 where the issue occurs.

| congruency class of k mod 4 | 0.4 | 1.2 | 2.0 | 2.8 |
| --------------------------- | --- | --- | --- | --- |
| 0 | x | | | x |
| 1 | | | | x |
| 2 | | x | | |
| 3 | x | x | | |

Because the binary expansions of 0.4, 1.2, 2.8 have a period of 4, this will repeat forever.

When this happens, the second child is positioned 0.8epx to the left of where it should be. That's the bug.

Contributor guide

Open the contributing guide

Research direction

Reproduce the issue in MainWindow.xaml using the provided nested Grid, with 125% DPI scaling and the stated padding and column widths. Trace the Grid layout and child positioning behavior, then verify that the two children no longer overlap and that the reproduction does not regress at other scaling combinations.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
desktop, frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.