示例#1
0
			public void recycle()
			{
				lock (sRecycleLock)
				{
					if (sRecycledCount < MAX_RECYCLED)
					{
						next = sRecycleBin;
						sRecycleBin = this;
						sRecycledCount += 1;
					}
					else
					{
						next = null;
					}
					child = null;
				}
			}
示例#2
0
			// all ones
			// The touched child view.
			// The combined bit mask of pointer ids for all pointers captured by the target.
			// The next target in the target list.
			public static android.view.ViewGroup.TouchTarget obtain(android.view.View child, 
				int pointerIdBits)
			{
				android.view.ViewGroup.TouchTarget target;
				lock (sRecycleLock)
				{
					if (sRecycleBin == null)
					{
						target = new android.view.ViewGroup.TouchTarget();
					}
					else
					{
						target = sRecycleBin;
						sRecycleBin = target.next;
						sRecycledCount--;
						target.next = null;
					}
				}
				target.child = child;
				target.pointerIdBits = pointerIdBits;
				return target;
			}
示例#3
0
		/// <summary>Removes the pointer ids from consideration.</summary>
		/// <remarks>Removes the pointer ids from consideration.</remarks>
		private void removePointersFromTouchTargets(int pointerIdBits)
		{
			android.view.ViewGroup.TouchTarget predecessor = null;
			android.view.ViewGroup.TouchTarget target = mFirstTouchTarget;
			while (target != null)
			{
				android.view.ViewGroup.TouchTarget next = target.next;
				if ((target.pointerIdBits & pointerIdBits) != 0)
				{
					target.pointerIdBits &= ~pointerIdBits;
					if (target.pointerIdBits == 0)
					{
						if (predecessor == null)
						{
							mFirstTouchTarget = next;
						}
						else
						{
							predecessor.next = next;
						}
						target.recycle();
						target = next;
						continue;
					}
				}
				predecessor = target;
				target = next;
			}
		}
示例#4
0
		/// <summary>Adds a touch target for specified child to the beginning of the list.</summary>
		/// <remarks>
		/// Adds a touch target for specified child to the beginning of the list.
		/// Assumes the target child is not already present.
		/// </remarks>
		private android.view.ViewGroup.TouchTarget addTouchTarget(android.view.View child
			, int pointerIdBits)
		{
			android.view.ViewGroup.TouchTarget target = android.view.ViewGroup.TouchTarget.obtain
				(child, pointerIdBits);
			target.next = mFirstTouchTarget;
			mFirstTouchTarget = target;
			return target;
		}
示例#5
0
		/// <summary>Clears all touch targets.</summary>
		/// <remarks>Clears all touch targets.</remarks>
		private void clearTouchTargets()
		{
			android.view.ViewGroup.TouchTarget target = mFirstTouchTarget;
			if (target != null)
			{
				do
				{
					android.view.ViewGroup.TouchTarget next = target.next;
					target.recycle();
					target = next;
				}
				while (target != null);
				mFirstTouchTarget = null;
			}
		}
示例#6
0
		public override bool dispatchTouchEvent(android.view.MotionEvent ev)
		{
			if (mInputEventConsistencyVerifier != null)
			{
				mInputEventConsistencyVerifier.onTouchEvent(ev, 1);
			}
			bool handled = false;
			if (onFilterTouchEventForSecurity(ev))
			{
				int action = ev.getAction();
				int actionMasked = action & android.view.MotionEvent.ACTION_MASK;
				// Handle an initial down.
				if (actionMasked == android.view.MotionEvent.ACTION_DOWN)
				{
					// Throw away all previous state when starting a new touch gesture.
					// The framework may have dropped the up or cancel event for the previous gesture
					// due to an app switch, ANR, or some other state change.
					cancelAndClearTouchTargets(ev);
					resetTouchState();
				}
				// Check for interception.
				bool intercepted;
				if (actionMasked == android.view.MotionEvent.ACTION_DOWN || mFirstTouchTarget != 
					null)
				{
					bool disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
					if (!disallowIntercept)
					{
						intercepted = onInterceptTouchEvent(ev);
						ev.setAction(action);
					}
					else
					{
						// restore action in case it was changed
						intercepted = false;
					}
				}
				else
				{
					// There are no touch targets and this action is not an initial down
					// so this view group continues to intercept touches.
					intercepted = true;
				}
				// Check for cancelation.
				bool canceled = resetCancelNextUpFlag(this) || actionMasked == android.view.MotionEvent
					.ACTION_CANCEL;
				// Update list of touch targets for pointer down, if needed.
				bool split = (mGroupFlags & FLAG_SPLIT_MOTION_EVENTS) != 0;
				android.view.ViewGroup.TouchTarget newTouchTarget = null;
				bool alreadyDispatchedToNewTouchTarget = false;
				if (!canceled && !intercepted)
				{
					if (actionMasked == android.view.MotionEvent.ACTION_DOWN || (split && actionMasked
						 == android.view.MotionEvent.ACTION_POINTER_DOWN) || actionMasked == android.view.MotionEvent
						.ACTION_HOVER_MOVE)
					{
						int actionIndex = ev.getActionIndex();
						// always 0 for down
						int idBitsToAssign = split ? 1 << ev.getPointerId(actionIndex) : android.view.ViewGroup
							.TouchTarget.ALL_POINTER_IDS;
						// Clean up earlier touch targets for this pointer id in case they
						// have become out of sync.
						removePointersFromTouchTargets(idBitsToAssign);
						int childrenCount = mChildrenCount;
						if (childrenCount != 0)
						{
							// Find a child that can receive the event.
							// Scan children from front to back.
							android.view.View[] children = mChildren;
							float x = ev.getX(actionIndex);
							float y = ev.getY(actionIndex);
							{
								for (int i = childrenCount - 1; i >= 0; i--)
								{
									android.view.View child = children[i];
									if (!canViewReceivePointerEvents(child) || !isTransformedTouchPointInView(x, y, child
										, null))
									{
										continue;
									}
									newTouchTarget = getTouchTarget(child);
									if (newTouchTarget != null)
									{
										// Child is already receiving touch within its bounds.
										// Give it the new pointer in addition to the ones it is handling.
										newTouchTarget.pointerIdBits |= idBitsToAssign;
										break;
									}
									resetCancelNextUpFlag(child);
									if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign))
									{
										// Child wants to receive touch within its bounds.
										mLastTouchDownTime = ev.getDownTime();
										mLastTouchDownIndex = i;
										mLastTouchDownX = ev.getX();
										mLastTouchDownY = ev.getY();
										newTouchTarget = addTouchTarget(child, idBitsToAssign);
										alreadyDispatchedToNewTouchTarget = true;
										break;
									}
								}
							}
						}
						if (newTouchTarget == null && mFirstTouchTarget != null)
						{
							// Did not find a child to receive the event.
							// Assign the pointer to the least recently added target.
							newTouchTarget = mFirstTouchTarget;
							while (newTouchTarget.next != null)
							{
								newTouchTarget = newTouchTarget.next;
							}
							newTouchTarget.pointerIdBits |= idBitsToAssign;
						}
					}
				}
				// Dispatch to touch targets.
				if (mFirstTouchTarget == null)
				{
					// No touch targets so treat this as an ordinary view.
					handled = dispatchTransformedTouchEvent(ev, canceled, null, android.view.ViewGroup
						.TouchTarget.ALL_POINTER_IDS);
				}
				else
				{
					// Dispatch to touch targets, excluding the new touch target if we already
					// dispatched to it.  Cancel touch targets if necessary.
					android.view.ViewGroup.TouchTarget predecessor = null;
					android.view.ViewGroup.TouchTarget target = mFirstTouchTarget;
					while (target != null)
					{
						android.view.ViewGroup.TouchTarget next = target.next;
						if (alreadyDispatchedToNewTouchTarget && target == newTouchTarget)
						{
							handled = true;
						}
						else
						{
							bool cancelChild = resetCancelNextUpFlag(target.child) || intercepted;
							if (dispatchTransformedTouchEvent(ev, cancelChild, target.child, target.pointerIdBits
								))
							{
								handled = true;
							}
							if (cancelChild)
							{
								if (predecessor == null)
								{
									mFirstTouchTarget = next;
								}
								else
								{
									predecessor.next = next;
								}
								target.recycle();
								target = next;
								continue;
							}
						}
						predecessor = target;
						target = next;
					}
				}
				// Update list of touch targets for pointer up or cancel, if needed.
				if (canceled || actionMasked == android.view.MotionEvent.ACTION_UP || actionMasked
					 == android.view.MotionEvent.ACTION_HOVER_MOVE)
				{
					resetTouchState();
				}
				else
				{
					if (split && actionMasked == android.view.MotionEvent.ACTION_POINTER_UP)
					{
						int actionIndex = ev.getActionIndex();
						int idBitsToRemove = 1 << ev.getPointerId(actionIndex);
						removePointersFromTouchTargets(idBitsToRemove);
					}
				}
			}
			if (!handled && mInputEventConsistencyVerifier != null)
			{
				mInputEventConsistencyVerifier.onUnhandledEvent(ev, 1);
			}
			return handled;
		}