diff --git a/samples/ControlCatalog/Pages/PointerCanvas.cs b/samples/ControlCatalog/Pages/PointerCanvas.cs index b815a573f2..5843b13a0c 100644 --- a/samples/ControlCatalog/Pages/PointerCanvas.cs +++ b/samples/ControlCatalog/Pages/PointerCanvas.cs @@ -19,6 +19,7 @@ public class PointerCanvas : Control private IDisposable? _statusUpdated; private Dictionary _pointers = new(); private PointerPointProperties? _lastProperties; + private PointerUpdateKind? _lastNonOtherUpdateKind; class PointerPoints { struct CanvasPoint @@ -128,10 +129,11 @@ public class PointerCanvas : Control _statusUpdated = DispatcherTimer.Run(() => { - if (_stopwatch.Elapsed.TotalSeconds > 1) + if (_stopwatch.Elapsed.TotalMilliseconds > 250) { Status = $@"Events per second: {(_events / _stopwatch.Elapsed.TotalSeconds)} PointerUpdateKind: {_lastProperties?.PointerUpdateKind} +Last PointerUpdateKind != Other: {_lastNonOtherUpdateKind} IsLeftButtonPressed: {_lastProperties?.IsLeftButtonPressed} IsRightButtonPressed: {_lastProperties?.IsRightButtonPressed} IsMiddleButtonPressed: {_lastProperties?.IsMiddleButtonPressed} @@ -162,21 +164,27 @@ Twist: {_lastProperties?.Twist}"; void HandleEvent(PointerEventArgs e) { _events++; + if (_threadSleep != 0) { Thread.Sleep(_threadSleep); } InvalidateVisual(); + var lastPointer = e.GetCurrentPoint(this); + _lastProperties = lastPointer.Properties; + + if (_lastProperties.PointerUpdateKind != PointerUpdateKind.Other) + { + _lastNonOtherUpdateKind = _lastProperties.PointerUpdateKind; + } + if (e.RoutedEvent == PointerReleasedEvent && e.Pointer.Type == PointerType.Touch) { _pointers.Remove(e.Pointer.Id); return; } - var lastPointer = e.GetCurrentPoint(this); - _lastProperties = lastPointer.Properties; - if (e.Pointer.Type != PointerType.Pen || lastPointer.Properties.Pressure > 0) { @@ -218,4 +226,10 @@ Twist: {_lastProperties?.Twist}"; HandleEvent(e); base.OnPointerReleased(e); } + + protected override void OnPointerCaptureLost(PointerCaptureLostEventArgs e) + { + _lastProperties = null; + base.OnPointerCaptureLost(e); + } } diff --git a/samples/ControlCatalog/Pages/PointersPage.xaml b/samples/ControlCatalog/Pages/PointersPage.xaml index 1281ec77b6..c39106f29e 100644 --- a/samples/ControlCatalog/Pages/PointersPage.xaml +++ b/samples/ControlCatalog/Pages/PointersPage.xaml @@ -19,6 +19,7 @@ diff --git a/samples/ControlCatalog/Pages/PointersPage.xaml.cs b/samples/ControlCatalog/Pages/PointersPage.xaml.cs index b463cf364d..6fc468e37f 100644 --- a/samples/ControlCatalog/Pages/PointersPage.xaml.cs +++ b/samples/ControlCatalog/Pages/PointersPage.xaml.cs @@ -35,7 +35,8 @@ public class PointersPage : UserControl { var textBlock = (TextBlock)((Border)sender).Child; var position = e.GetPosition((Border)sender); - textBlock.Text = @$"Captured: {e.Pointer.Captured == sender} + textBlock.Text = @$"Type: {e.Pointer.Type} +Captured: {e.Pointer.Captured == sender} PointerId: {e.Pointer.Id} Position: {(int)position.X} {(int)position.Y}"; e.Handled = true; @@ -44,7 +45,8 @@ Position: {(int)position.X} {(int)position.Y}"; private void Border_PointerCaptureLost(object sender, PointerCaptureLostEventArgs e) { var textBlock = (TextBlock)((Border)sender).Child; - textBlock.Text = @$"Captured: {e.Pointer.Captured == sender} + textBlock.Text = @$"Type: {e.Pointer.Type} +Captured: {e.Pointer.Captured == sender} PointerId: {e.Pointer.Id} Position: ??? ???"; e.Handled = true; diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index 861110bf9a..2ce4d7d1f0 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -746,7 +746,6 @@ namespace Avalonia.Win32 { if (GetPointerPenInfoHistory(info.pointerId, ref historyCount, s_historyPenInfos)) { - uint timestamp = 0; for (int i = historyCount - 1; i >= 1; i--) { var historyPenInfo = s_historyPenInfos[i]; @@ -830,7 +829,7 @@ namespace Avalonia.Win32 timestamp = info.dwTime; } - modifiers |= GetInputModifiers(info.dwKeyStates); + modifiers |= GetInputModifiers(info.pointerFlags); } private RawPointerPoint CreateRawPointerPoint(POINTER_INFO pointerInfo) @@ -871,48 +870,40 @@ namespace Avalonia.Win32 private static RawPointerEventType GetEventType(WindowsMessage message, POINTER_INFO info) { - if (message == WindowsMessage.WM_POINTERUPDATE) + var isTouch = info.pointerType == PointerInputType.PT_TOUCH; + if (info.pointerFlags.HasFlag(PointerFlags.POINTER_FLAG_CANCELED)) { - return info.pointerType == PointerInputType.PT_TOUCH - ? RawPointerEventType.TouchUpdate - : RawPointerEventType.Move; + return isTouch ? RawPointerEventType.TouchCancel : RawPointerEventType.LeaveWindow; } - switch (info.pointerType) + + var eventType = ToEventType(info.ButtonChangeType, isTouch); + if (eventType == RawPointerEventType.LeftButtonDown && + message == WindowsMessage.WM_NCPOINTERDOWN) { - case PointerInputType.PT_TOUCH: - if (info.pointerFlags.HasFlag(PointerFlags.POINTER_FLAG_CANCELED)) - { - return RawPointerEventType.TouchCancel; - } - return message == WindowsMessage.WM_POINTERDOWN || message == WindowsMessage.WM_NCPOINTERDOWN - ? RawPointerEventType.TouchBegin - : RawPointerEventType.TouchEnd; - default: - var eventType = ToEventType(info.ButtonChangeType); - if (eventType == RawPointerEventType.LeftButtonDown && - message == WindowsMessage.WM_NCPOINTERDOWN) - { - eventType = RawPointerEventType.NonClientLeftButtonDown; - } - return eventType; + eventType = RawPointerEventType.NonClientLeftButtonDown; } + + return eventType; } - private static RawPointerEventType ToEventType(PointerButtonChangeType type) + private static RawPointerEventType ToEventType(PointerButtonChangeType type, bool isTouch) { return type switch { - PointerButtonChangeType.POINTER_CHANGE_FIRSTBUTTON_DOWN => RawPointerEventType.LeftButtonDown, + PointerButtonChangeType.POINTER_CHANGE_FIRSTBUTTON_DOWN when isTouch => RawPointerEventType.TouchBegin, + PointerButtonChangeType.POINTER_CHANGE_FIRSTBUTTON_DOWN when !isTouch => RawPointerEventType.LeftButtonDown, PointerButtonChangeType.POINTER_CHANGE_SECONDBUTTON_DOWN => RawPointerEventType.RightButtonDown, PointerButtonChangeType.POINTER_CHANGE_THIRDBUTTON_DOWN => RawPointerEventType.MiddleButtonDown, PointerButtonChangeType.POINTER_CHANGE_FOURTHBUTTON_DOWN => RawPointerEventType.XButton1Down, PointerButtonChangeType.POINTER_CHANGE_FIFTHBUTTON_DOWN => RawPointerEventType.XButton2Down, - PointerButtonChangeType.POINTER_CHANGE_FIRSTBUTTON_UP => RawPointerEventType.LeftButtonUp, + PointerButtonChangeType.POINTER_CHANGE_FIRSTBUTTON_UP when isTouch => RawPointerEventType.TouchEnd, + PointerButtonChangeType.POINTER_CHANGE_FIRSTBUTTON_UP when !isTouch => RawPointerEventType.LeftButtonUp, PointerButtonChangeType.POINTER_CHANGE_SECONDBUTTON_UP => RawPointerEventType.RightButtonUp, PointerButtonChangeType.POINTER_CHANGE_THIRDBUTTON_UP => RawPointerEventType.MiddleButtonUp, PointerButtonChangeType.POINTER_CHANGE_FOURTHBUTTON_UP => RawPointerEventType.XButton1Up, PointerButtonChangeType.POINTER_CHANGE_FIFTHBUTTON_UP => RawPointerEventType.XButton2Up, + _ when isTouch => RawPointerEventType.TouchUpdate, _ => RawPointerEventType.Move }; } @@ -1000,5 +991,37 @@ namespace Avalonia.Win32 return modifiers; } + + private static RawInputModifiers GetInputModifiers(PointerFlags flags) + { + var modifiers = WindowsKeyboardDevice.Instance.Modifiers; + + if (flags.HasAllFlags(PointerFlags.POINTER_FLAG_FIRSTBUTTON)) + { + modifiers |= RawInputModifiers.LeftMouseButton; + } + + if (flags.HasAllFlags(PointerFlags.POINTER_FLAG_SECONDBUTTON)) + { + modifiers |= RawInputModifiers.RightMouseButton; + } + + if (flags.HasAllFlags(PointerFlags.POINTER_FLAG_THIRDBUTTON)) + { + modifiers |= RawInputModifiers.MiddleMouseButton; + } + + if (flags.HasAllFlags(PointerFlags.POINTER_FLAG_FOURTHBUTTON)) + { + modifiers |= RawInputModifiers.XButton1MouseButton; + } + + if (flags.HasAllFlags(PointerFlags.POINTER_FLAG_FIFTHBUTTON)) + { + modifiers |= RawInputModifiers.XButton2MouseButton; + } + + return modifiers; + } } }