Skip to content

Commit e1f5543

Browse files
committed
fix(pointers): Ensure that a manipulation cancelled by ManipStarting event is cleanup
1 parent f3d53bc commit e1f5543

File tree

3 files changed

+56
-28
lines changed

3 files changed

+56
-28
lines changed

src/Uno.UWP/UI/Input/GestureRecognizer.Manipulation.cs

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,35 @@ private enum ManipulationState
7777
public bool IsRotateEnabled => _isRotateEnabled;
7878
public bool IsScaleEnabled => _isScaleEnabled;
7979

80-
public Manipulation(GestureRecognizer recognizer, PointerPoint pointer1)
80+
internal static void AddPointer(GestureRecognizer recognizer, PointerPoint pointer)
81+
{
82+
var current = recognizer._manipulation;
83+
if (current != null)
84+
{
85+
if (current.TryAdd(pointer))
86+
{
87+
// The pending manipulation which can either handle the pointer, either is still active with another pointer,
88+
// just ignore the new pointer.
89+
return;
90+
}
91+
92+
// The current manipulation should be discarded
93+
current.Complete(); // Will removed 'current' from the 'recognizer._manipulation' field.
94+
}
95+
96+
var manipulation = new Manipulation(recognizer, pointer);
97+
if (manipulation._state == ManipulationState.Completed)
98+
{
99+
// The new manipulation has been cancelled in the ManipStarting handler, throw it away.
100+
manipulation.Complete(); // Should not do anything, safety only
101+
}
102+
else
103+
{
104+
recognizer._manipulation = manipulation;
105+
}
106+
}
107+
108+
private Manipulation(GestureRecognizer recognizer, PointerPoint pointer1)
81109
{
82110
_recognizer = recognizer;
83111
_deviceType = pointer1.PointerDevice.PointerDeviceType;
@@ -114,35 +142,37 @@ public Manipulation(GestureRecognizer recognizer, PointerPoint pointer1)
114142

115143
if ((_settings & (GestureSettingsHelper.Manipulations | GestureSettingsHelper.DragAndDrop)) == 0)
116144
{
145+
// The manipulation has been cancelled (all possible manip has been removed)
146+
// WARNING: The _gestureRecognizer._manipulation has not been set yet! We cannot invoke the Complete right now (cf. AddPointer)
147+
117148
_state = ManipulationState.Completed;
149+
return;
118150
}
119-
else
120-
{
121-
_isDraggingEnable = (_settings & GestureSettings.Drag) != 0;
122-
_isTranslateXEnabled = (_settings & (GestureSettings.ManipulationTranslateX | GestureSettings.ManipulationTranslateRailsX)) != 0;
123-
_isTranslateYEnabled = (_settings & (GestureSettings.ManipulationTranslateY | GestureSettings.ManipulationTranslateRailsY)) != 0;
124-
_isRotateEnabled = (_settings & GestureSettings.ManipulationRotate) != 0;
125-
_isScaleEnabled = (_settings & GestureSettings.ManipulationScale) != 0;
126-
}
151+
152+
_isDraggingEnable = (_settings & GestureSettings.Drag) != 0;
153+
_isTranslateXEnabled = (_settings & (GestureSettings.ManipulationTranslateX | GestureSettings.ManipulationTranslateRailsX)) != 0;
154+
_isTranslateYEnabled = (_settings & (GestureSettings.ManipulationTranslateY | GestureSettings.ManipulationTranslateRailsY)) != 0;
155+
_isRotateEnabled = (_settings & GestureSettings.ManipulationRotate) != 0;
156+
_isScaleEnabled = (_settings & GestureSettings.ManipulationScale) != 0;
127157

128158
_recognizer.ManipulationConfigured?.Invoke(_recognizer, this);
129159
StartDragTimer();
130160
}
131161

132-
public bool IsActive(PointerDeviceType type, uint id)
162+
public bool IsActive(PointerIdentifier pointer)
133163
=> _state != ManipulationState.Completed
134-
&& _deviceType == type
135-
&& _origins.ContainsPointer(id);
164+
&& _deviceType == pointer.Type
165+
&& _origins.ContainsPointer(pointer.Id);
136166

137-
public bool TryAdd(PointerPoint point)
167+
private bool TryAdd(PointerPoint point)
138168
{
139169
if (point.Pointer == _origins.Pointer1.Pointer)
140170
{
141171
this.Log().Error(
142172
"Invalid manipulation state: We are receiving a down for the second time for the same pointer!"
143173
+ "This is however common when using iOS emulator with VNC where we might miss some pointer events "
144174
+ "due to focus being stole by debugger, in that case you can safely ignore this message.");
145-
return false; // Request to create a new manipualtion
175+
return false; // Request to create a new manipulation
146176
}
147177
else if (_state >= ManipulationState.Inertia)
148178
{
@@ -236,12 +266,17 @@ public void Complete()
236266
new ManipulationCompletedEventArgs(_currents.Identifiers, position, cumulative, velocities, _state == ManipulationState.Inertia, _contacts.onStart, _contacts.current));
237267
break;
238268

239-
default:
269+
case ManipulationState.Starting:
240270
_inertia?.Dispose();
241271
_state = ManipulationState.Completed;
242272

243273
_recognizer.ManipulationAborted?.Invoke(_recognizer, this);
244274
break;
275+
276+
default: // Safety only
277+
_inertia?.Dispose();
278+
_state = ManipulationState.Completed;
279+
break;
245280
}
246281

247282
// Self scavenge our self from the _recognizer ... yes it's a bit strange,
@@ -524,6 +559,7 @@ private void StopDragTimer()
524559
{
525560
_dragHoldTimer?.Stop();
526561
}
562+
527563
// For pen and mouse this only means down -> * moves out of tap range;
528564
// For touch it means down -> * moves close to origin for DragUsingFingerMinDelayTicks -> * moves far from the origin
529565
private bool IsBeginningOfDragManipulation()

src/Uno.UWP/UI/Input/GestureRecognizer.cs

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -90,18 +90,10 @@ public void ProcessDownEvent(PointerPoint value)
9090
}
9191
_gestures[value.PointerId] = gesture;
9292

93-
// Create of update a Manipulation responsible to recognize multi-pointer and drag gestures
93+
// Create or update a Manipulation responsible to recognize multi-pointer and drag gestures
9494
if (_isManipulationOrDragEnabled)
9595
{
96-
if (_manipulation == null)
97-
{
98-
_manipulation = new Manipulation(this, value);
99-
}
100-
else if (!_manipulation.TryAdd(value))
101-
{
102-
_manipulation.Complete();
103-
_manipulation = new Manipulation(this, value);
104-
}
96+
Manipulation.AddPointer(this, value);
10597
}
10698
}
10799

@@ -191,8 +183,8 @@ internal void PreventHolding(uint pointerId)
191183

192184
#region Manipulations
193185
internal event TypedEventHandler<GestureRecognizer, ManipulationStartingEventArgs> ManipulationStarting; // This is not on the public API!
194-
internal event TypedEventHandler<GestureRecognizer, Manipulation> ManipulationConfigured; // Right after the ManipulationStarting, once application has configured settings
195-
internal event TypedEventHandler<GestureRecognizer, Manipulation> ManipulationAborted; // The manipulation has been aborted while in starting state
186+
internal event TypedEventHandler<GestureRecognizer, Manipulation> ManipulationConfigured; // Right after the ManipulationStarting, once application has configured settings ** ONLY if not cancelled in starting **
187+
internal event TypedEventHandler<GestureRecognizer, Manipulation> ManipulationAborted; // The manipulation has been aborted while in starting state ** ONLY if received a ManipulationConfigured **
196188
public event TypedEventHandler<GestureRecognizer, ManipulationCompletedEventArgs> ManipulationCompleted;
197189
public event TypedEventHandler<GestureRecognizer, ManipulationInertiaStartingEventArgs> ManipulationInertiaStarting;
198190
public event TypedEventHandler<GestureRecognizer, ManipulationStartedEventArgs> ManipulationStarted;

src/Uno.UWP/UI/Input/ManipulationCompletedEventArgs.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ internal ManipulationCompletedEventArgs(
3131
/// <summary>
3232
/// Gets identifiers of all pointer that has been involved in that manipulation (cf. Remarks).
3333
/// </summary>
34-
/// <remarks> This collection might contains pointers that has been released. <see cref="CurrentContactCount"/> gives the actual number of active pointers.</remarks>
34+
/// <remarks>This collection might contains pointers that has been released. <see cref="CurrentContactCount"/> gives the actual number of active pointers.</remarks>
3535
/// <remarks>All pointers are expected to have the same <see cref="PointerIdentifier.Type"/>.</remarks>
3636
internal PointerIdentifier[] Pointers { get; }
3737

0 commit comments

Comments
 (0)