-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Description
- .NET Core Version: 3.1 Preview1
- Windows version: (
winver) 1809 - Does the bug reproduce also in WPF for .NET Framework 4.8?: Yes
- Is this bug related specifically to tooling in Visual Studio (e.g. XAML Designer, Code editing, etc...)? No
Problem description:
Using the TouchMove event in a multi-dpi scenario, the interpolated points returned are not correctly adjusting for DPI, whereas the current point is.
When using the event to draw a path, you can see the discrepancy between these two inputs:

In this case my main monitor is scale factor 1.5x, whereas my touch-monitor where I'm running the app on is 1.0x.
The app has been configured to support multi-monitor DPI via the app.manifest.
Update: It appears the root issue here is in a multi-mon dpi aware app, when the DPI changes, the transform applied to the intermediate points are not using the new dpi, as this value is only initialized once.
Actual behavior:
Touch events (red line) are about 30% off from the correct location. If I multiple the location with 1.5, the location is correct (apart from the distance of the window top-bar). This is however weird, as the screen the app is running on is 1.0x screen scale (but main monitor is 1.5x). I'd guess the app registers it needs to run at 1.5 screen scale, then realizes the app is now running at 1.x and but forgot intermediate points should no longer be divided by 1.5x.
If I multiply the reported values by 1.5, and add the 30px that the canvas has as margin (or remove the margin), I get a perfect alignment.
Note: The issue does not seem to happen on single-monitor high-dpi setups, so I'm assuming it's related to multiple monitors at different DPIs
Expected behavior:
Intermediate and current touch points coincide.
Minimal repro:
Xaml:
<Grid>
<Canvas Margin="30" x:Name="canvas" TouchMove="canvas_TouchMove" IsManipulationEnabled="True" Background="White" />
</Grid>xaml.cs code-behind:
private PathFigure intermediatePoints;
private PathFigure currentPoint;
private void canvas_TouchMove(object sender, TouchEventArgs e)
{
foreach (var p in e.GetIntermediateTouchPoints(canvas))
intermediatePoints = AddVertex(p.Position, intermediatePoints, Colors.Red, 3);
currentPoint = AddVertex(e.GetTouchPoint(canvas).Position, currentPoint, Colors.Blue, 1);
}
private PathFigure AddVertex(Point point, PathFigure pf, Color color, double width)
{
if (pf == null)
{
pf = new PathFigure(point, new PathSegment[] { }, false);
PathGeometry pg = new PathGeometry(new PathFigure[] { pf });
Path p = new Path() { Data = pg };
p.StrokeThickness = width;
p.Stroke = new SolidColorBrush(color);
canvas.Children.Add(p);
}
else
{
pf.Segments.Add(new System.Windows.Media.LineSegment(point, true));
}
return pf;
}app.manifest:
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitor</dpiAwareness>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
</windowsSettings>
</application>
</assembly>Make sure you include the manifest in csproj:
<PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
Repro project:
TouchMoveDpiRepro.zip