Extract the fields from the Touch event that we need.  If we saved the event directly, it has references to other objects (like x-row) that might stick around for a long time.  This way we only have small objects in our lastTouch_ state.
352309
function(t) {
    return {
      id: t.identifier,
      y: t.clientY,
      x: t.clientX,
    };
  }
33154
function collectEventData(element, eventType, touches, ev) {

      // find out pointerType
      var pointerType = ionic.Gestures.POINTER_TOUCH;
      if(ev.type.match(/mouse/) || ionic.Gestures.PointerEvent.matchType(ionic.Gestures.POINTER_MOUSE, ev)) {
        pointerType = ionic.Gestures.POINTER_MOUSE;
      }

      return {
        center: ionic.Gestures.utils.getCenter(touches),
        timeStamp: new Date().getTime(),
        target: ev.target,
        touches: touches,
        eventType: eventType,
        pointerType: pointerType,
        srcEvent: ev,

        /**
         * prevent the browser default actions
         * mostly used to disable scrolling of the browser
         */
        preventDefault: function() {
          if(this.srcEvent.preventManipulation) {
            this.srcEvent.preventManipulation();
          }

          if(this.srcEvent.preventDefault) {
            // this.srcEvent.preventDefault();
          }
        },

        /**
         * stop bubbling the event up to its parents
         */
        stopPropagation: function() {
          this.srcEvent.stopPropagation();
        },

        /**
         * immediately stop gesture detection
         * might be useful after a swipe was detected
         * @return {*}
         */
        stopDetect: function() {
          return ionic.Gestures.detection.stopDetect();
        }
      };
    }
883854
function(mOptions, oEvent) {
			if (oEvent.type === "touchstart" || oEvent.pointerType === "touch") {
				var oScrollExtension = this._getScrollExtension();
				var oHSb = oScrollExtension.getHorizontalScrollbar();
				var oVSb = oScrollExtension.getVerticalScrollbar();
				var oTouchObject = oEvent.touches ? oEvent.touches[0] : oEvent;

				internal(this).mTouchSessionData = {
					initialPageX: oTouchObject.pageX,
					initialPageY: oTouchObject.pageY,
					initialScrollTop: oVSb ? oVSb.scrollTop : 0,
					initialScrollLeft: oHSb ? oHSb.scrollLeft : 0,
					initialScrolledToEnd: null,
					touchMoveDirection: null
				};
			}
		}
783747
def on_touch_down(self, touch):
        
        if not self.collide_point(*touch.pos):
            return
        if 'card' in touch.ud:
            return
        touch.grab(self)
        self.dragging = True
        touch.ud['card'] = self
        touch.ud['idx'] = self.idx
        touch.ud['deck'] = self.deck
        touch.ud['layout'] = self.parent
        self.collide_x = touch.x - self.x
        self.collide_y = touch.y - self.y
539
function touchStart(jqEvent) {
			//If we already in a touch event (a finger already in use) then ignore subsequent ones..
			if( getTouchInProgress() )
				return;
			
			//Check if this element matches any in the excluded elements selectors,  or its parent is excluded, if so, DON'T swipe
			if( $(jqEvent.target).closest( options.excludedElements, $element ).length>0 ) 
				return;
				
			//As we use Jquery bind for events, we need to target the original event object
			//If these events are being programmatically triggered, we don't have an original event object, so use the Jq one.
			var event = jqEvent.originalEvent ? jqEvent.originalEvent : jqEvent;
			
			var ret,
				touches = event.touches,
				evt = touches ? touches[0] : event;

			phase = PHASE_START;

			//If we support touches, get the finger count
			if (touches) {
				// get the total number of fingers touching the screen
				fingerCount = touches.length;
			}
			//Else this is the desktop, so stop the browser from dragging content
			else {
				jqEvent.preventDefault(); //call this on jq event so we are cross browser
			}

			//clear vars..
			distance = 0;
			direction = null;
			pinchDirection=null;
			duration = 0;
			startTouchesDistance=0;
			endTouchesDistance=0;
			pinchZoom = 1;
			pinchDistance = 0;
			fingerData=createAllFingerData();
			maximumsMap=createMaximumsData();
			cancelMultiFingerRelease();

			
			// check the number of fingers is what we are looking for, or we are capturing pinches
			if (!touches || (fingerCount === options.fingers || options.fingers === ALL_FINGERS) || hasPinches()) {
				// get the coordinates of the touch
				createFingerData( 0, evt );
				startTime = getTimeStamp();
				
				if(fingerCount==2) {
					//Keep track of the initial pinch distance, so we can calculate the diff later
					//Store second finger data as start
					createFingerData( 1, touches[1] );
					startTouchesDistance = endTouchesDistance = calculateTouchesDistance(fingerData[0].start, fingerData[1].start);
				}
				
				if (options.swipeStatus || options.pinchStatus) {
					ret = triggerHandler(event, phase);
				}
			}
			else {
				//A touch with more or less than the fingers we are looking for, so cancel
				ret = false; 
			}

			//If we have a return value from the users handler, then return and cancel
			if (ret === false) {
				phase = PHASE_CANCEL;
				triggerHandler(event, phase);
				return ret;
			}
			else {
				if (options.hold) {
					holdTimeout = setTimeout($.proxy(function() {
						//Trigger the event
						$element.trigger('hold', [event.target]);
						//Fire the callback
						if(options.hold) {
							ret = options.hold.call($element, event, event.target);
						}
					}, this), options.longTapThreshold );
				}

				setTouchInProgress(true);
			}

            return null;
		}
526247
function(evt) {
        evt.preventDefault();
        evt.stopPropagation();
        if (debug) { timedLog("handleTouchRepositioning"); }
        if (evt.touches.length < 2) {
          return;
        }
        if (debug) { timedLog("handleTouchRepositioning - continued"); }
        var x1 = evt.touches[0].pageX,
          y1 = evt.touches[0].pageY,
          x2 = evt.touches[1].pageX,
          y2 = evt.touches[1].pageY,
          dx = x2 - x1,
          dy = y2 - y1,
          d = Math.sqrt(dx*dx + dy*dy),
          a = Math.atan2(dy,dx),
          da = a - transform.angle + mark.angle,
          s = d/transform.distance * mark.scale;

        transform.modified = true;
        positionable.handleRotationAndScale(da, s);
      }
1368954
private int countEvents(TouchState newState) {
        int count = state.getPointCount();
        for (int i = 0; i < newState.getPointCount(); i++) {
            TouchState.Point newPoint = newState.getPoint(i);
            TouchState.Point oldPoint = state.getPointForID(newPoint.id);
            if (oldPoint == null) {
                count ++;
            }
        }
        return count;
    }
1217793
function (evt) {
    if (evt.touches.length !== 1 || !this.data.touchEnabled) { return; }
    this.touchStart = {
      x: evt.touches[0].pageX,
      y: evt.touches[0].pageY
    };
    this.touchStarted = true;
  }
650256
@Override
    public boolean onTouchEvent(@NonNull MotionEvent event) {

        if (!isEnabled()) {
            return false;
        }

        int pointerIndex;

        final int action = event.getAction();
        switch (action & MotionEvent.ACTION_MASK) {

            case MotionEvent.ACTION_DOWN:
                // Remember where the motion event started
                activePointerId = event.getPointerId(event.getPointerCount() - 1);
                pointerIndex = event.findPointerIndex(activePointerId);
                downMotionX = event.getX(pointerIndex);

                pressedThumb = evalPressedThumb(downMotionX);

                // Only handle thumb presses.
                if (pressedThumb == null) {
                    return super.onTouchEvent(event);
                }

                setPressed(true);
                invalidate();
                onStartTrackingTouch();
                trackTouchEvent(event);
                attemptClaimDrag();

                break;
            case MotionEvent.ACTION_MOVE:
                if (pressedThumb != null) {

                    if (isDragging) {
                        trackTouchEvent(event);
                    } else {
                        // Scroll to follow the motion event
                        pointerIndex = event.findPointerIndex(activePointerId);
                        final float x = event.getX(pointerIndex);

                        if (Math.abs(x - downMotionX) > scaledTouchSlop) {
                            setPressed(true);
                            invalidate();
                            onStartTrackingTouch();
                            trackTouchEvent(event);
                            attemptClaimDrag();
                        }
                    }

                    if (notifyWhileDragging && listener != null) {
                        listener.onRangeSeekBarValuesChanged(this, getSelectedMinValue(), getSelectedMaxValue());
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                if (isDragging) {
                    trackTouchEvent(event);
                    onStopTrackingTouch();
                    setPressed(false);
                } else {
                    // Touch up when we never crossed the touch slop threshold
                    // should be interpreted as a tap-seek to that location.
                    onStartTrackingTouch();
                    trackTouchEvent(event);
                    onStopTrackingTouch();
                }

                pressedThumb = null;
                invalidate();
                if (listener != null) {
                    listener.onRangeSeekBarValuesChanged(this, getSelectedMinValue(), getSelectedMaxValue());
                }
                break;
            case MotionEvent.ACTION_POINTER_DOWN: {
                final int index = event.getPointerCount() - 1;
                // final int index = ev.getActionIndex();
                downMotionX = event.getX(index);
                activePointerId = event.getPointerId(index);
                invalidate();
                break;
            }
            case MotionEvent.ACTION_POINTER_UP:
                onSecondaryPointerUp(event);
                invalidate();
                break;
            case MotionEvent.ACTION_CANCEL:
                if (isDragging) {
                    onStopTrackingTouch();
                    setPressed(false);
                }
                invalidate(); // see above explanation
                break;
        }
        return true;
    }
542331
function (event) {
          var obj = event;
          if (event.targetTouches !== undefined) {
            obj = event.targetTouches.item(0);
          } else if (event.originalEvent !== undefined && event.originalEvent.targetTouches !== undefined) {
            obj = event.originalEvent.targetTouches.item(0);
          }
          return obj;
        }
1083241
function(event) {
		
		var self = this,
			ok = true;
		
		if (self.__state != 'stable' && self.__state != 'appearing') {
			
			// if a timeout is not already running
			if (!self.__timeouts.open) {
				
				self._trigger({
					type: 'start',
					event: event,
					stop: function() {
						ok = false;
					}
				});
				
				if (ok) {
					
					var delay = (event.type.indexOf('touch') == 0) ?
						self.__options.delayTouch :
						self.__options.delay;
					
					if (delay[0]) {
						
						self.__timeouts.open = setTimeout(function() {
							
							self.__timeouts.open = null;
							
							// open only if the pointer (mouse or touch) is still over the origin.
							// The check on the "meaningful event" can only be made here, after some
							// time has passed (to know if the touch was a swipe or not)
							if (self.__pointerIsOverOrigin && self._touchIsMeaningfulEvent(event)) {
								
								// signal that we go on
								self._trigger('startend');
								
								self._open(event);
							}
							else {
								// signal that we cancel
								self._trigger('startcancel');
							}
						}, delay[0]);
					}
					else {
						// signal that we go on
						self._trigger('startend');
						
						self._open(event);
					}
				}
			}
		}
		
		return self;
	}
1374405
function( event ) {
			// SAP MODIFICATION: if jQuery event is created programatically there's no originalEvent property. Therefore the existence of event.originalEvent needs to be checked.
			var data = event.originalEvent && event.originalEvent.touches ?
					event.originalEvent.touches[ 0 ] : event;
			return {
						time: ( new Date() ).getTime(),
						coords: [ data.pageX, data.pageY ],
						origin: $( event.target )
					};
		}
37912
function touchcancelHandler(event) {

  if (Object.keys(gestures).length == 2) {
    var elements = []
    for (var p in gestures) {
      elements.push(gestures[p].element)
    }
    fireEvent(getCommonAncestor(elements[0], elements[1]), 'dualtouchend', {
      touches: slice.call(event.touches),
      touchEvent: event
    })
  }

  for (var i = 0; i < event.changedTouches.length; i++) {
    var touch = event.changedTouches[i]
    var id = touch.identifier
    var gesture = gestures[id]

    if (!gesture) {
      continue
    }

    if (gesture.pressingHandler) {
      clearTimeout(gesture.pressingHandler)
      gesture.pressingHandler = null
    }

    if (gesture.status === 'panning') {
      fireEvent(gesture.element, 'panend', {
        touch: touch,
        touches: event.touches,
        changedTouches: event.changedTouches,
        touchEvent: event
      })
    }
    if (gesture.status === 'pressing') {
      fireEvent(gesture.element, 'pressend', {
        touch: touch,
        touchEvent: event
      })
    }
    delete gestures[id]
  }

  if (Object.keys(gestures).length === 0) {
    docEl.removeEventListener('touchmove', touchmoveHandler, false)
    docEl.removeEventListener('touchend', touchendHandler, false)
    docEl.removeEventListener('touchcancel', touchcancelHandler, false)
  }
}
1036401
function (event) {

          var touchInvalid = false;
          if (event.touches !== undefined && event.touches.length > 1) {
            touchInvalid = true;
          } else if (event.originalEvent !== undefined &&
            event.originalEvent.touches !== undefined && event.originalEvent.touches.length > 1) {
            touchInvalid = true;
          }
          return touchInvalid;
        }
1223464
function (evt) {
                var event = new ariaDomEvent(evt);

                connectMouseEvents(this);

                if (evt.type === "touchstart") {
                    // The position of touch events is not determined correctly by clientX/Y
                    var elementPosition = ariaTouchEvent.getPositions(event);
                    event.clientX = elementPosition[0].x;
                    event.clientY = elementPosition[0].y;
                }

                if (this._detectDrag(event)) {
                    event.preventDefault(true);
                }

                event.$dispose();
                return false;
            }
266373
function getY(event) {
  let originalEvent = event.originalEvent;
  let touches = originalEvent && originalEvent.changedTouches;
  let touch = touches && touches[0];

  if (touch) {
    return touch.screenY;
  } else {
    return event.pageY;
  }
}
218294
private void postTouchEvent(MonocleWindow window,
                                View view,
                                TouchState newState) {
        int count = countEvents(newState);
        switch (count) {
            case 0:
                postNoPoints(view);
                break;
            case 1:
                if (state.getPointCount() == 1) {
                    // There is one point and it already existed
                    TouchState.Point oldPoint = state.getPoint(0);
                    TouchState.Point newPoint = newState.getPointForID(
                            oldPoint.id);
                    if (newPoint != null) {
                        if (newPoint.x == oldPoint.x
                                && newPoint.y == oldPoint.y) {
                            postPoint(window, view, TouchEvent.TOUCH_STILL, newPoint);
                        } else {
                            postPoint(window, view, TouchEvent.TOUCH_MOVED, newPoint);
                        }
                    } else {
                        postPoint(window, view, TouchEvent.TOUCH_RELEASED, oldPoint);
                    }
                } else {
                    // There is one point and it is newly pressed
                    postPoint(window, view, TouchEvent.TOUCH_PRESSED, newState.getPoint(0));
                }
                break;
            default: {
                int[] states = new int[count];
                int[] ids = new int[count];
                int[] xs = new int[count];
                int[] ys = new int[count];
                for (int i = 0; i < state.getPointCount(); i++) {
                    TouchState.Point oldPoint = state.getPoint(i);
                    TouchState.Point newPoint = newState.getPointForID(
                            oldPoint.id);
                    if (newPoint != null) {
                        ids[i] = newPoint.id;
                        xs[i] = newPoint.x;
                        ys[i] = newPoint.y;
                        if (newPoint.x == oldPoint.x
                                && newPoint.y == oldPoint.y) {
                            states[i] = TouchEvent.TOUCH_STILL;
                        } else {
                            states[i] = TouchEvent.TOUCH_MOVED;
                        }
                    } else {
                        states[i] = TouchEvent.TOUCH_RELEASED;
                        ids[i] = oldPoint.id;
                        xs[i] = oldPoint.x;
                        ys[i] = oldPoint.y;
                    }
                }
                // Once we have dealt with updates to old points, all that are left
                // are new points.
                for (int i = 0, j = state.getPointCount();
                        i < newState.getPointCount(); i++) {
                    TouchState.Point newPoint = newState.getPoint(i);
                    TouchState.Point oldPoint = state.getPointForID(
                            newPoint.id);
                    if (oldPoint == null) {
                        states[j] = TouchEvent.TOUCH_PRESSED;
                        ids[j] = newPoint.id;
                        xs[j] = newPoint.x;
                        ys[j] = newPoint.y;
                        j++;
                    }
                }
                postPoints(window, view, states, ids, xs, ys);
            }
        }
    }