public override void TouchesEnded(NSSet touches, UIEvent evt) { try { var isHandledOrBubblingInManaged = default(bool); foreach (UITouch touch in touches) { var id = NativePointerId.Get(this, touch); var args = new PointerRoutedEventArgs(id.Value, touch, evt, this); isHandledOrBubblingInManaged |= OnNativePointerUp(args); isHandledOrBubblingInManaged |= OnNativePointerExited(args); id.Release(this); } if (!isHandledOrBubblingInManaged) { // Continue native bubbling up of the event base.TouchesEnded(touches, evt); } NotifyParentTouchesManagersManipulationEnded(); } catch (Exception e) { Application.Current.RaiseRecoverableUnhandledException(e); } }
public override void TouchesCancelled(NSSet touches, UIEvent evt) { try { var isHandledOrBubblingInManaged = default(bool); foreach (UITouch touch in touches) { var id = NativePointerId.Get(this, touch); var args = new PointerRoutedEventArgs(id.Value, touch, evt, this); // Note: We should have raise either PointerCaptureLost or PointerCancelled here depending of the reason which // drives the system to bubble a lost. However we don't have this kind of information on iOS, and it's // usually due to the ScrollView which kicks in. So we always raise the CaptureLost which is the behavior // on UWP when scroll starts (even if no capture are actives at this time). isHandledOrBubblingInManaged |= OnNativePointerCancel(args, isSwallowedBySystem: true); id.Release(this); } if (!isHandledOrBubblingInManaged) { // Continue native bubbling up of the event base.TouchesCancelled(touches, evt); } NotifyParentTouchesManagersManipulationEnded(); } catch (Exception e) { Application.Current.RaiseRecoverableUnhandledException(e); } }
public override void TouchesMoved(NSSet touches, UIEvent evt) { try { var isHandledOrBubblingInManaged = default(bool); foreach (UITouch touch in touches) { var id = NativePointerId.Get(this, touch); var args = new PointerRoutedEventArgs(id.Value, touch, evt, this); var isPointerOver = touch.IsTouchInView(this); // As we don't have enter/exit equivalents on iOS, we have to update the IsOver on each move // Note: Entered / Exited are raised *before* the Move (Checked using the args timestamp) isHandledOrBubblingInManaged |= OnNativePointerMoveWithOverCheck(args, isPointerOver); } if (!isHandledOrBubblingInManaged) { // Continue native bubbling up of the event base.TouchesMoved(touches, evt); } } catch (Exception e) { Application.Current.RaiseRecoverableUnhandledException(e); } }
public static NativePointerId Get(UIElement element, UITouch touch) { if (!_instances.TryGetValue(touch.Handle, out var id)) { _instances[touch.Handle] = id = new NativePointerId(touch.Handle); } id._leases.Add(element); return(id); }
public override void TouchesBegan(NSSet touches, UIEvent evt) { if (IsPointersSuspended) { return; // Will also prevent subsequents events } /* Note: Here we have a mismatching behavior with UWP, if the events bubble natively we're going to get * (with Ctrl_02 is a child of Ctrl_01): * Ctrl_02: Entered * Pressed * Ctrl_01: Entered * Pressed * * While on UWP we will get: * Ctrl_02: Entered * Ctrl_01: Entered * Ctrl_02: Pressed * Ctrl_01: Pressed * * However, to fix this is would mean that we handle all events in managed code, but this would * break lots of control (ScrollViewer) and ability to easily integrate an external component. */ try { NotifyParentTouchesManagersManipulationStarted(); var isHandledOrBubblingInManaged = default(bool); foreach (UITouch touch in touches) { var id = NativePointerId.Get(this, touch); var args = new PointerRoutedEventArgs(id.Value, touch, evt, this); isHandledOrBubblingInManaged |= OnNativePointerEnter(args); isHandledOrBubblingInManaged |= OnNativePointerDown(args); } /* * **** WARNING **** * * If we do not propagate the "TouchesBegan" to the parents, they won't receive the * "TouchesMoved" nor the "TouchesEnded". * * It means that if a control (like the Button) handles the "Pressed" (or the "Entered") * parent won't receive any touch event. As it doesn't seems to be have any impact in application, * it's accepted as a known limitation. * * There is 2 ways to fix this: * - Still propagate the native "TouchesBegan" and then in parents control filter out events * that was already raised in managed * - Keep a track in local element that the "TouchesBegan" was handled in managed, and then raise * all subsequent "Move", "Released" and "Exited" in managed only. */ if (!isHandledOrBubblingInManaged) { // Continue native bubbling up of the event base.TouchesBegan(touches, evt); } } catch (Exception e) { Application.Current.RaiseRecoverableUnhandledException(e); } }