Browse Source

Fixed intermediate points order for windows (#20075)

* Fixed points order for windows

* Added static comparer

* Fixed points order for windows

* Added static comparer

* optimization
release/11.3.10
Krzysztof Krysiński 2 months ago
committed by Julien Lebosquain
parent
commit
10b12e5e45
No known key found for this signature in database GPG Key ID: 1833CAD10ACC46FD
  1. 56
      src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs
  2. 7
      src/Windows/Avalonia.Win32/WindowImpl.cs

56
src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Avalonia.Automation.Peers; using Avalonia.Automation.Peers;
using Avalonia.Controls; using Avalonia.Controls;
@ -983,7 +984,8 @@ namespace Avalonia.Win32
return null; return null;
} }
private unsafe IReadOnlyList<RawPointerPoint> CreateIntermediatePoints(MOUSEMOVEPOINT movePoint, MOUSEMOVEPOINT prevMovePoint) private unsafe IReadOnlyList<RawPointerPoint> CreateIntermediatePoints(MOUSEMOVEPOINT movePoint,
MOUSEMOVEPOINT prevMovePoint)
{ {
// To understand some of this code, please check MS docs: // To understand some of this code, please check MS docs:
// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmousemovepointsex#remarks // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmousemovepointsex#remarks
@ -994,6 +996,7 @@ namespace Avalonia.Win32
{ {
var movePointCopy = movePoint; var movePointCopy = movePoint;
movePointCopy.time = 0; // empty "time" as otherwise WinAPI will always fail movePointCopy.time = 0; // empty "time" as otherwise WinAPI will always fail
int pointsCount = GetMouseMovePointsEx( int pointsCount = GetMouseMovePointsEx(
(uint)(Marshal.SizeOf(movePointCopy)), (uint)(Marshal.SizeOf(movePointCopy)),
&movePointCopy, movePoints, s_mouseHistoryInfos.Length, &movePointCopy, movePoints, s_mouseHistoryInfos.Length,
@ -1001,47 +1004,46 @@ namespace Avalonia.Win32
// GetMouseMovePointsEx can return -1 if point wasn't found or there is so beeg delay that original points were erased from the buffer. // GetMouseMovePointsEx can return -1 if point wasn't found or there is so beeg delay that original points were erased from the buffer.
if (pointsCount <= 1) if (pointsCount <= 1)
{
return Array.Empty<RawPointerPoint>(); return Array.Empty<RawPointerPoint>();
}
s_intermediatePointsPooledList.Clear(); s_intermediatePointsPooledList.Clear();
s_intermediatePointsPooledList.Capacity = pointsCount; s_sortedPoints.Clear();
for (int i = pointsCount - 1; i >= 1; i--)
s_sortedPoints.Capacity = pointsCount;
for (int i = 0; i < pointsCount; i++)
{ {
var historyInfo = s_mouseHistoryInfos[i]; var mp = movePoints[i];
// Skip points newer than current point.
if (historyInfo.time > movePoint.time || var x = mp.x > 32767 ? mp.x - 65536 : mp.x;
(historyInfo.time == movePoint.time && var y = mp.y > 32767 ? mp.y - 65536 : mp.y;
historyInfo.x == movePoint.x &&
historyInfo.y == movePoint.y)) if(mp.time <= prevMovePoint.time || mp.time >= movePoint.time)
{
continue; continue;
}
// Skip points older from previous WM_MOUSEMOVE point. s_sortedPoints.Add(new InternalPoint
if (historyInfo.time < prevMovePoint.time ||
(historyInfo.time == prevMovePoint.time &&
historyInfo.x == prevMovePoint.x &&
historyInfo.y == prevMovePoint.y))
{ {
continue; Time = mp.time,
} Pt = new PixelPoint(x, y)
});
}
// To support multiple screens. // sorting is required to ensure points are in order from oldest to newest
if (historyInfo.x > 32767) s_sortedPoints.Sort(static (a, b) => a.Time.CompareTo(b.Time));
historyInfo.x -= 65536;
if (historyInfo.y > 32767) foreach (var p in s_sortedPoints)
historyInfo.y -= 65536; {
var client = PointToClient(p.Pt);
var point = PointToClient(new PixelPoint(historyInfo.x, historyInfo.y));
s_intermediatePointsPooledList.Add(new RawPointerPoint s_intermediatePointsPooledList.Add(new RawPointerPoint
{ {
Position = point Position = client
}); });
} }
return s_intermediatePointsPooledList; return s_intermediatePointsPooledList;
} }
} }
private RawPointerEventArgs CreatePointerArgs(IInputDevice device, ulong timestamp, RawPointerEventType eventType, RawPointerPoint point, RawInputModifiers modifiers, uint rawPointerId) private RawPointerEventArgs CreatePointerArgs(IInputDevice device, ulong timestamp, RawPointerEventType eventType, RawPointerPoint point, RawInputModifiers modifiers, uint rawPointerId)

7
src/Windows/Avalonia.Win32/WindowImpl.cs

@ -111,6 +111,7 @@ namespace Avalonia.Win32
private const int MaxPointerHistorySize = 512; private const int MaxPointerHistorySize = 512;
private static readonly PooledList<RawPointerPoint> s_intermediatePointsPooledList = new(); private static readonly PooledList<RawPointerPoint> s_intermediatePointsPooledList = new();
private static readonly List<InternalPoint> s_sortedPoints = new(64);
private static POINTER_TOUCH_INFO[]? s_historyTouchInfos; private static POINTER_TOUCH_INFO[]? s_historyTouchInfos;
private static POINTER_PEN_INFO[]? s_historyPenInfos; private static POINTER_PEN_INFO[]? s_historyPenInfos;
private static POINTER_INFO[]? s_historyInfos; private static POINTER_INFO[]? s_historyInfos;
@ -1741,5 +1742,11 @@ namespace Avalonia.Win32
public double Scaling => _owner.RenderScaling; public double Scaling => _owner.RenderScaling;
} }
private struct InternalPoint
{
public int Time;
public PixelPoint Pt;
}
} }
} }

Loading…
Cancel
Save