|
|
|
@ -1,6 +1,7 @@ |
|
|
|
using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Diagnostics.CodeAnalysis; |
|
|
|
using System.Linq; |
|
|
|
using System.Runtime.InteropServices; |
|
|
|
using Avalonia.Automation.Peers; |
|
|
|
using Avalonia.Controls; |
|
|
|
@ -983,7 +984,8 @@ namespace Avalonia.Win32 |
|
|
|
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:
|
|
|
|
// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmousemovepointsex#remarks
|
|
|
|
@ -994,6 +996,7 @@ namespace Avalonia.Win32 |
|
|
|
{ |
|
|
|
var movePointCopy = movePoint; |
|
|
|
movePointCopy.time = 0; // empty "time" as otherwise WinAPI will always fail
|
|
|
|
|
|
|
|
int pointsCount = GetMouseMovePointsEx( |
|
|
|
(uint)(Marshal.SizeOf(movePointCopy)), |
|
|
|
&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.
|
|
|
|
if (pointsCount <= 1) |
|
|
|
{ |
|
|
|
return Array.Empty<RawPointerPoint>(); |
|
|
|
} |
|
|
|
|
|
|
|
s_intermediatePointsPooledList.Clear(); |
|
|
|
s_intermediatePointsPooledList.Capacity = pointsCount; |
|
|
|
for (int i = pointsCount - 1; i >= 1; i--) |
|
|
|
{ |
|
|
|
var historyInfo = s_mouseHistoryInfos[i]; |
|
|
|
// Skip points newer than current point.
|
|
|
|
if (historyInfo.time > movePoint.time || |
|
|
|
(historyInfo.time == movePoint.time && |
|
|
|
historyInfo.x == movePoint.x && |
|
|
|
historyInfo.y == movePoint.y)) |
|
|
|
s_sortedPoints.Clear(); |
|
|
|
|
|
|
|
s_sortedPoints.Capacity = pointsCount; |
|
|
|
|
|
|
|
for (int i = 0; i < pointsCount; i++) |
|
|
|
{ |
|
|
|
var mp = movePoints[i]; |
|
|
|
|
|
|
|
var x = mp.x > 32767 ? mp.x - 65536 : mp.x; |
|
|
|
var y = mp.y > 32767 ? mp.y - 65536 : mp.y; |
|
|
|
|
|
|
|
if(mp.time <= prevMovePoint.time || mp.time >= movePoint.time) |
|
|
|
continue; |
|
|
|
} |
|
|
|
// Skip points older from previous WM_MOUSEMOVE point.
|
|
|
|
if (historyInfo.time < prevMovePoint.time || |
|
|
|
(historyInfo.time == prevMovePoint.time && |
|
|
|
historyInfo.x == prevMovePoint.x && |
|
|
|
historyInfo.y == prevMovePoint.y)) |
|
|
|
|
|
|
|
s_sortedPoints.Add(new InternalPoint |
|
|
|
{ |
|
|
|
continue; |
|
|
|
Time = mp.time, |
|
|
|
Pt = new PixelPoint(x, y) |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
// To support multiple screens.
|
|
|
|
if (historyInfo.x > 32767) |
|
|
|
historyInfo.x -= 65536; |
|
|
|
// sorting is required to ensure points are in order from oldest to newest
|
|
|
|
s_sortedPoints.Sort(static (a, b) => a.Time.CompareTo(b.Time)); |
|
|
|
|
|
|
|
if (historyInfo.y > 32767) |
|
|
|
historyInfo.y -= 65536; |
|
|
|
foreach (var p in s_sortedPoints) |
|
|
|
{ |
|
|
|
var client = PointToClient(p.Pt); |
|
|
|
|
|
|
|
var point = PointToClient(new PixelPoint(historyInfo.x, historyInfo.y)); |
|
|
|
s_intermediatePointsPooledList.Add(new RawPointerPoint |
|
|
|
{ |
|
|
|
Position = point |
|
|
|
Position = client |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
return s_intermediatePointsPooledList; |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
private RawPointerEventArgs CreatePointerArgs(IInputDevice device, ulong timestamp, RawPointerEventType eventType, RawPointerPoint point, RawInputModifiers modifiers, uint rawPointerId) |
|
|
|
|