From c646343beee6da4f8568751ffd56bdd2da1f92ff Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sun, 20 Mar 2022 23:54:04 -0400 Subject: [PATCH] WIP on intermediate points win --- src/Avalonia.Input/PointerEventArgs.cs | 3 +- src/Avalonia.Input/PointerPoint.cs | 17 +++ src/Avalonia.Input/Raw/RawPointerEventArgs.cs | 10 +- .../Avalonia.Win32/WindowImpl.AppWndProc.cs | 141 +++++++++++------- 4 files changed, 112 insertions(+), 59 deletions(-) diff --git a/src/Avalonia.Input/PointerEventArgs.cs b/src/Avalonia.Input/PointerEventArgs.cs index 0604d09dc4..a30c1c51dc 100644 --- a/src/Avalonia.Input/PointerEventArgs.cs +++ b/src/Avalonia.Input/PointerEventArgs.cs @@ -128,7 +128,8 @@ namespace Avalonia.Input for (var c = 0; c < previousPoints.Count; c++) { var pt = previousPoints[c]; - points[c] = new PointerPoint(Pointer, GetPosition(pt.Position, relativeTo), _properties); + var pointProperties = new PointerPointProperties(_properties, pt); + points[c] = new PointerPoint(Pointer, GetPosition(pt.Position, relativeTo), pointProperties); } points[points.Length - 1] = GetCurrentPoint(relativeTo); diff --git a/src/Avalonia.Input/PointerPoint.cs b/src/Avalonia.Input/PointerPoint.cs index 728bb1c579..ba69add7d8 100644 --- a/src/Avalonia.Input/PointerPoint.cs +++ b/src/Avalonia.Input/PointerPoint.cs @@ -84,6 +84,23 @@ namespace Avalonia.Input IsBarrelButtonPressed = isBarrel; } + internal PointerPointProperties(PointerPointProperties basedOn, Raw.RawPointerPoint rawPoint) + { + IsLeftButtonPressed = basedOn.IsLeftButtonPressed; + IsMiddleButtonPressed = basedOn.IsMiddleButtonPressed; + IsRightButtonPressed = basedOn.IsRightButtonPressed; + IsXButton1Pressed = basedOn.IsXButton1Pressed; + IsXButton2Pressed = basedOn.IsXButton2Pressed; + IsInverted = basedOn.IsInverted; + IsEraser = basedOn.IsEraser; + IsBarrelButtonPressed = basedOn.IsBarrelButtonPressed; + + Twist = rawPoint.Twist; + Pressure = rawPoint.Pressure; + XTilt = rawPoint.XTilt; + YTilt = rawPoint.YTilt; + } + public static PointerPointProperties None { get; } = new PointerPointProperties(); } diff --git a/src/Avalonia.Input/Raw/RawPointerEventArgs.cs b/src/Avalonia.Input/Raw/RawPointerEventArgs.cs index c157fa059c..cd99cdc23b 100644 --- a/src/Avalonia.Input/Raw/RawPointerEventArgs.cs +++ b/src/Avalonia.Input/Raw/RawPointerEventArgs.cs @@ -128,10 +128,16 @@ namespace Avalonia.Input.Raw /// Pointer position, in client DIPs. /// public Point Position { get; set; } - + + public float Twist { get; set; } + public float Pressure { get; set; } + public float XTilt { get; set; } + public float YTilt { get; set; } + + public RawPointerPoint() { - Position = default; + this = default; } } } diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index 1ef3cbaba2..5c17caa13b 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -1,4 +1,6 @@ using System; +using System.Buffers; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; using System.Text; @@ -413,78 +415,105 @@ namespace Avalonia.Win32 case WindowsMessage.WM_POINTERUPDATE: { GetDevicePointerInfo(wParam, out var device, out var info, ref timestamp); - Point[]? intermediatePoints = null; + if (info.pointerType == PointerInputType.PT_TOUCH + && ShouldIgnoreTouchEmulatedMessage()) + { + break; + } + var historyCount = (int)info.historyCount; + Lazy> intermediatePoints = null; if (info.historyCount > 1) { - if (info.pointerType == PointerInputType.PT_TOUCH) + intermediatePoints = new Lazy>(() => { - if (ShouldIgnoreTouchEmulatedMessage()) + var list = new List(historyCount - 1); + if (info.pointerType == PointerInputType.PT_TOUCH) { - break; - } - - var pointerId = (uint)(ToInt32(wParam) & 0xFFFF); - var historyCount = (int)info.historyCount; - var historyTouchInfos = new POINTER_TOUCH_INFO[historyCount]; - if (GetPointerTouchInfoHistory(pointerId, ref historyCount, historyTouchInfos)) - { - //last info is the same as the current so skip it - for (int i = 0; i < historyCount - 1; i++) + var pointerId = (uint)(ToInt32(wParam) & 0xFFFF); + var historyTouchInfos = ArrayPool.Shared.Rent(historyCount); + try + { + if (GetPointerTouchInfoHistory(pointerId, ref historyCount, historyTouchInfos)) + { + //last info is the same as the current so skip it + for (int i = 0; i < historyCount - 1; i++) + { + var historyTouchInfo = historyTouchInfos[i]; + var historyInfo = historyTouchInfo.pointerInfo; + var historyPoint = PointToClient(new PixelPoint( + historyInfo.ptPixelLocationX, historyInfo.ptPixelLocationY)); + list.Add(new RawPointerPoint + { + Position = historyPoint, + }); + } + } + } + finally { - var historyTouchInfo = historyTouchInfos[i]; - var historyInfo = historyTouchInfo.pointerInfo; - var historyEventType = GetEventType(message, historyInfo); - var historyPoint = PointToClient(new PixelPoint( - historyInfo.ptPixelLocationX, historyInfo.ptPixelLocationY)); - var historyModifiers = GetInputModifiers(historyInfo.dwKeyStates); - var historyTimestamp = historyInfo.dwTime == 0 ? timestamp : historyInfo.dwTime; - Input?.Invoke(new RawTouchEventArgs(_touchDevice, historyTimestamp, _owner, - historyEventType, historyPoint, historyModifiers, historyInfo.pointerId)); + ArrayPool.Shared.Return(historyTouchInfos); } } - } - else if (info.pointerType == PointerInputType.PT_PEN) - { - var pointerId = (uint)(ToInt32(wParam) & 0xFFFF); - var historyCount = (int)info.historyCount; - var historyPenInfos = new POINTER_PEN_INFO[historyCount]; - if (GetPointerPenInfoHistory(pointerId, ref historyCount, historyPenInfos)) + else if (info.pointerType == PointerInputType.PT_PEN) { - //last info is the same as the current so skip it - for (int i = 0; i < historyCount - 1; i++) + var pointerId = (uint)(ToInt32(wParam) & 0xFFFF); + var historyPenInfos = ArrayPool.Shared.Rent(historyCount); + try { - var historyPenInfo = historyPenInfos[i]; - var historyInfo = historyPenInfo.pointerInfo; - var historyEventType = GetEventType(message, historyInfo); - var historyPoint = PointToClient(new PixelPoint( - historyInfo.ptPixelLocationX, historyInfo.ptPixelLocationY)); - var historyModifiers = GetInputModifiers(historyInfo.dwKeyStates); - var historyTimestamp = historyInfo.dwTime == 0 ? timestamp : historyInfo.dwTime; - - ApplyPenInfo(historyPenInfo); - Input?.Invoke(new RawPointerEventArgs(_penDevice, historyTimestamp, _owner, - historyEventType, historyPoint, historyModifiers)); + if (GetPointerPenInfoHistory(pointerId, ref historyCount, historyPenInfos)) + { + //last info is the same as the current so skip it + for (int i = 0; i < historyCount - 1; i++) + { + var historyPenInfo = historyPenInfos[i]; + var historyInfo = historyPenInfo.pointerInfo; + var historyPoint = PointToClient(new PixelPoint( + historyInfo.ptPixelLocationX, historyInfo.ptPixelLocationY)); + list.Add(new RawPointerPoint + { + Position = historyPoint, + Pressure = historyPenInfo.pressure, + Twist = historyPenInfo.rotation, + XTilt = historyPenInfo.tiltX, + YTilt = historyPenInfo.tiltX + }); + } + } + } + finally + { + ArrayPool.Shared.Return(historyPenInfos); } } - } - else - { - var pointerId = (uint)(ToInt32(wParam) & 0xFFFF); - var historyCount = (int)info.historyCount; - var historyInfos = new POINTER_INFO[historyCount]; - if (GetPointerInfoHistory(pointerId, ref historyCount, historyInfos)) + else { - //last info is the same as the current so skip it - intermediatePoints = new Point[historyCount - 1]; - for (int i = 0;i < historyCount - 1; i++) + var pointerId = (uint)(ToInt32(wParam) & 0xFFFF); + var historyInfos = ArrayPool.Shared.Rent(historyCount); + try + { + if (GetPointerInfoHistory(pointerId, ref historyCount, historyInfos)) + { + //last info is the same as the current so skip it + for (int i = 0; i < historyCount - 1; i++) + { + var historyInfo = historyInfos[i]; + var historyPoint = PointToClient(new PixelPoint( + historyInfo.ptPixelLocationX, historyInfo.ptPixelLocationY)); + list.Add(new RawPointerPoint + { + Position = historyPoint + }); + } + } + } + finally { - var historyInfo = historyInfos[i]; - intermediatePoints[i] = PointToClient(new PixelPoint( - historyInfo.ptPixelLocationX, historyInfo.ptPixelLocationY)); + ArrayPool.Shared.Return(historyInfos); } } - } + return list; + }); } var eventType = GetEventType(message, info);