From 01d6dc6206be7ffb4f1eadff5d7c855082f2aa4c Mon Sep 17 00:00:00 2001 From: Max Katz Date: Wed, 20 Mar 2024 14:04:07 -0700 Subject: [PATCH 1/4] Fix stylus input state mapping on iOS --- src/iOS/Avalonia.iOS/InputHandler.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/iOS/Avalonia.iOS/InputHandler.cs b/src/iOS/Avalonia.iOS/InputHandler.cs index 6f58a78e8fc..02af811df43 100644 --- a/src/iOS/Avalonia.iOS/InputHandler.cs +++ b/src/iOS/Avalonia.iOS/InputHandler.cs @@ -68,8 +68,12 @@ public void Handle(NSSet touches, UIEvent? evt) (TouchDevice, UITouchPhase.Cancelled) => RawPointerEventType.TouchCancel, (TouchDevice, _) => RawPointerEventType.TouchUpdate, - (_, UITouchPhase.Began) => IsRightClick() ? RawPointerEventType.RightButtonDown : RawPointerEventType.LeftButtonDown, - (_, UITouchPhase.Ended or UITouchPhase.Cancelled) => IsRightClick() ? RawPointerEventType.RightButtonUp : RawPointerEventType.RightButtonDown, + (_, UITouchPhase.Began) => IsRightClick() + ? RawPointerEventType.RightButtonDown + : RawPointerEventType.LeftButtonDown, + (_, UITouchPhase.Ended or UITouchPhase.Cancelled) => IsRightClick() + ? RawPointerEventType.RightButtonUp + : RawPointerEventType.LeftButtonUp, (_, _) => RawPointerEventType.Move, }, ToPointerPoint(t), modifiers, id) { From 821fab2b2f711cd4a613565f568cc7f7a013430f Mon Sep 17 00:00:00 2001 From: Max Katz Date: Wed, 20 Mar 2024 14:04:22 -0700 Subject: [PATCH 2/4] Fix UIKeyboardHidUsage.KeyboardDeleteOrBackspace mapping on iOS, should be mapped to Backspace --- src/iOS/Avalonia.iOS/InputHandler.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/iOS/Avalonia.iOS/InputHandler.cs b/src/iOS/Avalonia.iOS/InputHandler.cs index 02af811df43..a35560ff23e 100644 --- a/src/iOS/Avalonia.iOS/InputHandler.cs +++ b/src/iOS/Avalonia.iOS/InputHandler.cs @@ -292,7 +292,8 @@ private static RawInputModifiers ConvertModifierKeys(UIKeyModifierFlags? uiModif [UIKeyboardHidUsage.Keyboard0] = PhysicalKey.Digit0, [UIKeyboardHidUsage.KeyboardReturnOrEnter] = PhysicalKey.Enter, [UIKeyboardHidUsage.KeyboardEscape] = PhysicalKey.Escape, - [UIKeyboardHidUsage.KeyboardDeleteOrBackspace] = PhysicalKey.Delete, + // See KeyboardDeleteForward for an actual Delete. + [UIKeyboardHidUsage.KeyboardDeleteOrBackspace] = PhysicalKey.Backspace, [UIKeyboardHidUsage.KeyboardTab] = PhysicalKey.Tab, [UIKeyboardHidUsage.KeyboardSpacebar] = PhysicalKey.Space, [UIKeyboardHidUsage.KeyboardHyphen] = PhysicalKey.NumPadSubtract, From bdf180b0b18b058a2fbce20b2da30d81cd8ec9cf Mon Sep 17 00:00:00 2001 From: Max Katz Date: Wed, 20 Mar 2024 14:23:58 -0700 Subject: [PATCH 3/4] Release iOS pen pointer on PenUp event, fixing IsPrimary state --- src/Avalonia.Base/Input/PenDevice.cs | 51 +++++++++++++++++----------- src/iOS/Avalonia.iOS/InputHandler.cs | 5 +-- 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/src/Avalonia.Base/Input/PenDevice.cs b/src/Avalonia.Base/Input/PenDevice.cs index 85352f88dd2..7637de05acc 100644 --- a/src/Avalonia.Base/Input/PenDevice.cs +++ b/src/Avalonia.Base/Input/PenDevice.cs @@ -1,12 +1,10 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Reflection; using Avalonia.Input.GestureRecognizers; using Avalonia.Input.Raw; using Avalonia.Interactivity; using Avalonia.Metadata; -using Avalonia.Platform; using Avalonia.VisualTree; #pragma warning disable CS0618 @@ -20,6 +18,7 @@ namespace Avalonia.Input public class PenDevice : IPenDevice, IDisposable { private readonly Dictionary _pointers = new(); + private readonly bool _releasePointerOnPenUp; private int _clickCount; private Rect _lastClickRect; private ulong _lastClickTime; @@ -27,6 +26,11 @@ public class PenDevice : IPenDevice, IDisposable private bool _disposed; + public PenDevice(bool releasePointerOnPenUp = false) + { + _releasePointerOnPenUp = releasePointerOnPenUp; + } + public void ProcessRawEvent(RawInputEventArgs e) { if (!e.Handled && e is RawPointerEventArgs margs) @@ -52,26 +56,35 @@ private void ProcessRawEvent(RawPointerEventArgs e) var keyModifiers = e.InputModifiers.ToKeyModifiers(); bool shouldReleasePointer = false; - switch (e.Type) + try { - case RawPointerEventType.LeaveWindow: - shouldReleasePointer = true; - break; - case RawPointerEventType.LeftButtonDown: - e.Handled = PenDown(pointer, e.Timestamp, e.Root, e.Position, props, keyModifiers, e.InputHitTestResult); - break; - case RawPointerEventType.LeftButtonUp: - e.Handled = PenUp(pointer, e.Timestamp, e.Root, e.Position, props, keyModifiers, e.InputHitTestResult); - break; - case RawPointerEventType.Move: - e.Handled = PenMove(pointer, e.Timestamp, e.Root, e.Position, props, keyModifiers, e.InputHitTestResult, e.IntermediatePoints); - break; + switch (e.Type) + { + case RawPointerEventType.LeaveWindow: + shouldReleasePointer = true; + break; + case RawPointerEventType.LeftButtonDown: + e.Handled = PenDown(pointer, e.Timestamp, e.Root, e.Position, props, keyModifiers, e.InputHitTestResult); + break; + case RawPointerEventType.LeftButtonUp: + if (_releasePointerOnPenUp) + { + shouldReleasePointer = true; + } + e.Handled = PenUp(pointer, e.Timestamp, e.Root, e.Position, props, keyModifiers, e.InputHitTestResult); + break; + case RawPointerEventType.Move: + e.Handled = PenMove(pointer, e.Timestamp, e.Root, e.Position, props, keyModifiers, e.InputHitTestResult, e.IntermediatePoints); + break; + } } - - if (shouldReleasePointer) + finally { - pointer.Dispose(); - _pointers.Remove(e.RawPointerId); + if (shouldReleasePointer) + { + pointer.Dispose(); + _pointers.Remove(e.RawPointerId); + } } } diff --git a/src/iOS/Avalonia.iOS/InputHandler.cs b/src/iOS/Avalonia.iOS/InputHandler.cs index a35560ff23e..2a289502194 100644 --- a/src/iOS/Avalonia.iOS/InputHandler.cs +++ b/src/iOS/Avalonia.iOS/InputHandler.cs @@ -17,7 +17,7 @@ internal sealed class InputHandler private readonly ITopLevelImpl _tl; private readonly TouchDevice _touchDevice = new(); private readonly MouseDevice _mouseDevice = new(); - private readonly PenDevice _penDevice = new(); + private readonly PenDevice _penDevice = new(releasePointerOnPenUp: true); private static long _nextTouchPointId = 1; private readonly Dictionary _knownTouches = new(); @@ -71,9 +71,10 @@ public void Handle(NSSet touches, UIEvent? evt) (_, UITouchPhase.Began) => IsRightClick() ? RawPointerEventType.RightButtonDown : RawPointerEventType.LeftButtonDown, - (_, UITouchPhase.Ended or UITouchPhase.Cancelled) => IsRightClick() + (_, UITouchPhase.Ended) => IsRightClick() ? RawPointerEventType.RightButtonUp : RawPointerEventType.LeftButtonUp, + (_, UITouchPhase.Cancelled) => RawPointerEventType.LeaveWindow, (_, _) => RawPointerEventType.Move, }, ToPointerPoint(t), modifiers, id) { From 320d7e06678551128d8b084429b3d8a9d83fb8d3 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Wed, 20 Mar 2024 14:25:03 -0700 Subject: [PATCH 4/4] Don't limit scroll gestures to single primary input - user should be able to scroll two different scrolls --- .../Input/GestureRecognizers/ScrollGestureRecognizer.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs index a89a3d4c33b..baaf63f1121 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs @@ -94,8 +94,7 @@ public int ScrollStartDistance protected override void PointerPressed(PointerPressedEventArgs e) { - if (e.Pointer.IsPrimary && - (e.Pointer.Type == PointerType.Touch || e.Pointer.Type == PointerType.Pen)) + if (e.Pointer.Type == PointerType.Touch || e.Pointer.Type == PointerType.Pen) { EndGesture(); _tracking = e.Pointer;