Esempio n. 1
0
		public override bool onTouchEvent(android.view.MotionEvent @event)
		{
			if ((@event.getAction() == android.view.MotionEvent.ACTION_CANCEL) || (@event.getAction
				() == android.view.MotionEvent.ACTION_UP))
			{
				mIsInLongpress = false;
			}
			return base.onTouchEvent(@event);
		}
Esempio n. 2
0
		public virtual bool onKeyOther(android.widget.TextView widget, android.text.Spannable
			 text, android.view.KeyEvent @event)
		{
			int movementMetaState = getMovementMetaState(text, @event);
			int keyCode = @event.getKeyCode();
			if (keyCode != android.view.KeyEvent.KEYCODE_UNKNOWN && @event.getAction() == android.view.KeyEvent
				.ACTION_MULTIPLE)
			{
				int repeat = @event.getRepeatCount();
				bool handled = false;
				{
					for (int i = 0; i < repeat; i++)
					{
						if (!handleMovementKey(widget, text, keyCode, movementMetaState, @event))
						{
							break;
						}
						handled = true;
					}
				}
				if (handled)
				{
					android.text.method.MetaKeyKeyListener.adjustMetaAfterKeypress(text);
					android.text.method.MetaKeyKeyListener.resetLockedMeta(text);
				}
				return handled;
			}
			return false;
		}
Esempio n. 3
0
		public override void onReceive(android.content.Context context, android.content.Intent
			 intent)
		{
			// BEGIN_INCLUDE(onReceive)
			// Protect against rogue update broadcasts (not really a security issue,
			// just filter bad broacasts out so subclasses are less likely to crash).
			string action = intent.getAction();
			if (android.appwidget.AppWidgetManager.ACTION_APPWIDGET_UPDATE.Equals(action))
			{
				android.os.Bundle extras = intent.getExtras();
				if (extras != null)
				{
					int[] appWidgetIds = extras.getIntArray(android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_IDS
						);
					if (appWidgetIds != null && appWidgetIds.Length > 0)
					{
						this.onUpdate(context, android.appwidget.AppWidgetManager.getInstance(context), appWidgetIds
							);
					}
				}
			}
			else
			{
				if (android.appwidget.AppWidgetManager.ACTION_APPWIDGET_DELETED.Equals(action))
				{
					android.os.Bundle extras = intent.getExtras();
					if (extras != null && extras.containsKey(android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID
						))
					{
						int appWidgetId = extras.getInt(android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID
							);
						this.onDeleted(context, new int[] { appWidgetId });
					}
				}
				else
				{
					if (android.appwidget.AppWidgetManager.ACTION_APPWIDGET_ENABLED.Equals(action))
					{
						this.onEnabled(context);
					}
					else
					{
						if (android.appwidget.AppWidgetManager.ACTION_APPWIDGET_DISABLED.Equals(action))
						{
							this.onDisabled(context);
						}
					}
				}
			}
		}
Esempio n. 4
0
		public virtual bool onKey(android.content.DialogInterface dialog, int keyCode, android.view.KeyEvent
			 @event)
		{
			if (keyCode == android.view.KeyEvent.KEYCODE_MENU || keyCode == android.view.KeyEvent
				.KEYCODE_BACK)
			{
				if (@event.getAction() == android.view.KeyEvent.ACTION_DOWN && @event.getRepeatCount
					() == 0)
				{
					android.view.Window win = mDialog.getWindow();
					if (win != null)
					{
						android.view.View decor = win.getDecorView();
						if (decor != null)
						{
							android.view.KeyEvent.DispatcherState ds = decor.getKeyDispatcherState();
							if (ds != null)
							{
								ds.startTracking(@event, this);
								return true;
							}
						}
					}
				}
				else
				{
					if (@event.getAction() == android.view.KeyEvent.ACTION_UP && [email protected]())
					{
						android.view.Window win = mDialog.getWindow();
						if (win != null)
						{
							android.view.View decor = win.getDecorView();
							if (decor != null)
							{
								android.view.KeyEvent.DispatcherState ds = decor.getKeyDispatcherState();
								if (ds != null && ds.isTracking(@event))
								{
									mMenu.close(true);
									dialog.dismiss();
									return true;
								}
							}
						}
					}
				}
			}
			// Menu shortcut matching
			return mMenu.performShortcut(keyCode, @event, 0);
		}
Esempio n. 5
0
			public override void onReceive(android.content.Context context, android.content.Intent
				 intent)
			{
				string action = intent.getAction();
				if (android.content.Intent.ACTION_SCREEN_OFF.Equals(action))
				{
					this._enclosing.mUserPresent = false;
					this._enclosing.updateRunning();
				}
				else
				{
					if (android.content.Intent.ACTION_USER_PRESENT.Equals(action))
					{
						this._enclosing.mUserPresent = true;
						this._enclosing.updateRunning(false);
					}
				}
			}
Esempio n. 6
0
		protected internal override bool handleMovementKey(android.widget.TextView widget
			, android.text.Spannable buffer, int keyCode, int movementMetaState, android.view.KeyEvent
			 @event)
		{
			switch (keyCode)
			{
				case android.view.KeyEvent.KEYCODE_DPAD_CENTER:
				{
					if (android.view.KeyEvent.metaStateHasNoModifiers(movementMetaState))
					{
						if (@event.getAction() == android.view.KeyEvent.ACTION_DOWN && @event.getRepeatCount
							() == 0 && android.text.method.MetaKeyKeyListener.getMetaState(buffer, android.text.method.MetaKeyKeyListener
							.META_SELECTING) != 0)
						{
							return widget.showContextMenu();
						}
					}
					break;
				}
			}
			return base.handleMovementKey(widget, buffer, keyCode, movementMetaState, @event);
		}
Esempio n. 7
0
		private bool onContainerKey(android.view.KeyEvent @event)
		{
			int keyCode = @event.getKeyCode();
			if (isInterestingKey(keyCode))
			{
				if (keyCode == android.view.KeyEvent.KEYCODE_BACK)
				{
					if (@event.getAction() == android.view.KeyEvent.ACTION_DOWN && @event.getRepeatCount
						() == 0)
					{
						if (mOwnerView != null)
						{
							android.view.KeyEvent.DispatcherState ds = mOwnerView.getKeyDispatcherState();
							if (ds != null)
							{
								ds.startTracking(@event, this);
							}
						}
						return true;
					}
					else
					{
						if (@event.getAction() == android.view.KeyEvent.ACTION_UP && @event.isTracking() 
							&& [email protected]())
						{
							setVisible(false);
							return true;
						}
					}
				}
				else
				{
					dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT);
				}
				// Let the container handle the key
				return false;
			}
			else
			{
				android.view.ViewRootImpl viewRoot = getOwnerViewRootImpl();
				if (viewRoot != null)
				{
					viewRoot.dispatchKey(@event);
				}
				// We gave the key to the owner, don't let the container handle this key
				return true;
			}
		}
Esempio n. 8
0
		/// <summary>
		/// Transforms a motion event into the coordinate space of a particular child view,
		/// filters out irrelevant pointer ids, and overrides its action if necessary.
		/// </summary>
		/// <remarks>
		/// Transforms a motion event into the coordinate space of a particular child view,
		/// filters out irrelevant pointer ids, and overrides its action if necessary.
		/// If child is null, assumes the MotionEvent will be sent to this ViewGroup instead.
		/// </remarks>
		private bool dispatchTransformedTouchEvent(android.view.MotionEvent @event, bool 
			cancel, android.view.View child, int desiredPointerIdBits)
		{
			bool handled;
			// Canceling motions is a special case.  We don't need to perform any transformations
			// or filtering.  The important part is the action, not the contents.
			int oldAction = @event.getAction();
			if (cancel || oldAction == android.view.MotionEvent.ACTION_CANCEL)
			{
				@event.setAction(android.view.MotionEvent.ACTION_CANCEL);
				if (child == null)
				{
					handled = base.dispatchTouchEvent(@event);
				}
				else
				{
					handled = child.dispatchTouchEvent(@event);
				}
				@event.setAction(oldAction);
				return handled;
			}
			// Calculate the number of pointers to deliver.
			int oldPointerIdBits = @event.getPointerIdBits();
			int newPointerIdBits = oldPointerIdBits & desiredPointerIdBits;
			// If for some reason we ended up in an inconsistent state where it looks like we
			// might produce a motion event with no pointers in it, then drop the event.
			if (newPointerIdBits == 0)
			{
				return false;
			}
			// If the number of pointers is the same and we don't need to perform any fancy
			// irreversible transformations, then we can reuse the motion event for this
			// dispatch as long as we are careful to revert any changes we make.
			// Otherwise we need to make a copy.
			android.view.MotionEvent transformedEvent;
			if (newPointerIdBits == oldPointerIdBits)
			{
				if (child == null || child.hasIdentityMatrix())
				{
					if (child == null)
					{
						handled = base.dispatchTouchEvent(@event);
					}
					else
					{
						float offsetX = mScrollX - child.mLeft;
						float offsetY = mScrollY - child.mTop;
						@event.offsetLocation(offsetX, offsetY);
						handled = child.dispatchTouchEvent(@event);
						@event.offsetLocation(-offsetX, -offsetY);
					}
					return handled;
				}
				transformedEvent = android.view.MotionEvent.obtain(@event);
			}
			else
			{
				transformedEvent = @event.split(newPointerIdBits);
			}
			// Perform any necessary transformations and dispatch.
			if (child == null)
			{
				handled = base.dispatchTouchEvent(transformedEvent);
			}
			else
			{
				float offsetX = mScrollX - child.mLeft;
				float offsetY = mScrollY - child.mTop;
				transformedEvent.offsetLocation(offsetX, offsetY);
				if (!child.hasIdentityMatrix())
				{
					transformedEvent.transform(child.getInverseMatrix());
				}
				handled = child.dispatchTouchEvent(transformedEvent);
			}
			// Done.
			transformedEvent.recycle();
			return handled;
		}
Esempio n. 9
0
			public override void onReceive(android.content.Context context, android.content.Intent
				 intent)
			{
				if (intent.getAction().Equals(android.content.Intent.ACTION_TIMEZONE_CHANGED))
				{
					string tz = intent.getStringExtra("time-zone");
					this._enclosing.mCalendar = new android.text.format.Time(java.util.TimeZone.getTimeZone
						(tz).getID());
				}
				this._enclosing.onTimeChanged();
				this._enclosing.invalidate();
			}
Esempio n. 10
0
		public override bool onTouchEvent(android.view.MotionEvent @event)
		{
			if (!mIsUserSeekable || !isEnabled())
			{
				return false;
			}
			switch (@event.getAction())
			{
				case android.view.MotionEvent.ACTION_DOWN:
				{
					if (isInScrollingContainer())
					{
						mTouchDownX = @event.getX();
					}
					else
					{
						setPressed(true);
						if (mThumb != null)
						{
							invalidate(mThumb.getBounds());
						}
						// This may be within the padding region
						onStartTrackingTouch();
						trackTouchEvent(@event);
						attemptClaimDrag();
					}
					break;
				}

				case android.view.MotionEvent.ACTION_MOVE:
				{
					if (mIsDragging)
					{
						trackTouchEvent(@event);
					}
					else
					{
						float x = @event.getX();
						if (System.Math.Abs(x - mTouchDownX) > mScaledTouchSlop)
						{
							setPressed(true);
							if (mThumb != null)
							{
								invalidate(mThumb.getBounds());
							}
							// This may be within the padding region
							onStartTrackingTouch();
							trackTouchEvent(@event);
							attemptClaimDrag();
						}
					}
					break;
				}

				case android.view.MotionEvent.ACTION_UP:
				{
					if (mIsDragging)
					{
						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();
					}
					// ProgressBar doesn't know to repaint the thumb drawable
					// in its inactive state when the touch stops (because the
					// value has not apparently changed)
					invalidate();
					break;
				}

				case android.view.MotionEvent.ACTION_CANCEL:
				{
					if (mIsDragging)
					{
						onStopTrackingTouch();
						setPressed(false);
					}
					invalidate();
					// see above explanation
					break;
				}
			}
			return true;
		}
Esempio n. 11
0
			public override bool dispatchKeyEvent(android.view.KeyEvent @event)
			{
				if (@event.getKeyCode() == android.view.KeyEvent.KEYCODE_BACK)
				{
					if (this.getKeyDispatcherState() == null)
					{
						return base.dispatchKeyEvent(@event);
					}
					if (@event.getAction() == android.view.KeyEvent.ACTION_DOWN && @event.getRepeatCount
						() == 0)
					{
						android.view.KeyEvent.DispatcherState state = this.getKeyDispatcherState();
						if (state != null)
						{
							state.startTracking(@event, this);
						}
						return true;
					}
					else
					{
						if (@event.getAction() == android.view.KeyEvent.ACTION_UP)
						{
							android.view.KeyEvent.DispatcherState state = this.getKeyDispatcherState();
							if (state != null && state.isTracking(@event) && [email protected]())
							{
								this._enclosing.dismiss();
								return true;
							}
						}
					}
					return base.dispatchKeyEvent(@event);
				}
				else
				{
					return base.dispatchKeyEvent(@event);
				}
			}
Esempio n. 12
0
		/// <summary>Filter pre-IME key events.</summary>
		/// <remarks>
		/// Filter pre-IME key events. By forwarding
		/// <see cref="android.view.View.onKeyPreIme(int, android.view.KeyEvent)">android.view.View.onKeyPreIme(int, android.view.KeyEvent)
		/// 	</see>
		/// events to this function, views using ListPopupWindow can have it dismiss the popup
		/// when the back key is pressed.
		/// </remarks>
		/// <param name="keyCode">keyCode param passed to the host view's onKeyPreIme</param>
		/// <param name="event">event param passed to the host view's onKeyPreIme</param>
		/// <returns>true if the event was handled, false if it was ignored.</returns>
		/// <seealso cref="setModal(bool)">setModal(bool)</seealso>
		public virtual bool onKeyPreIme(int keyCode, android.view.KeyEvent @event)
		{
			if (keyCode == android.view.KeyEvent.KEYCODE_BACK && isShowing())
			{
				// special case for the back key, we do not even try to send it
				// to the drop down list but instead, consume it immediately
				android.view.View anchorView = mDropDownAnchorView;
				if (@event.getAction() == android.view.KeyEvent.ACTION_DOWN && @event.getRepeatCount
					() == 0)
				{
					android.view.KeyEvent.DispatcherState state = anchorView.getKeyDispatcherState();
					if (state != null)
					{
						state.startTracking(@event, this);
					}
					return true;
				}
				else
				{
					if (@event.getAction() == android.view.KeyEvent.ACTION_UP)
					{
						android.view.KeyEvent.DispatcherState state = anchorView.getKeyDispatcherState();
						if (state != null)
						{
							state.handleUpEvent(@event);
						}
						if (@event.isTracking() && [email protected]())
						{
							dismiss();
							return true;
						}
					}
				}
			}
			return false;
		}
Esempio n. 13
0
		/// <summary>React to the user typing while in the suggestions list.</summary>
		/// <remarks>
		/// React to the user typing while in the suggestions list. First, check for
		/// action keys. If not handled, try refocusing regular characters into the
		/// EditText.
		/// </remarks>
		private bool onSuggestionsKey(android.view.View v, int keyCode, android.view.KeyEvent
			 @event)
		{
			// guard against possible race conditions (late arrival after dismiss)
			if (mSearchable == null)
			{
				return false;
			}
			if (mSuggestionsAdapter == null)
			{
				return false;
			}
			if (@event.getAction() == android.view.KeyEvent.ACTION_DOWN && @event.hasNoModifiers
				())
			{
				// First, check for enter or search (both of which we'll treat as a
				// "click")
				if (keyCode == android.view.KeyEvent.KEYCODE_ENTER || keyCode == android.view.KeyEvent
					.KEYCODE_SEARCH || keyCode == android.view.KeyEvent.KEYCODE_TAB)
				{
					int position = mQueryTextView.getListSelection();
					return onItemClicked(position, android.view.KeyEvent.KEYCODE_UNKNOWN, null);
				}
				// Next, check for left/right moves, which we use to "return" the
				// user to the edit view
				if (keyCode == android.view.KeyEvent.KEYCODE_DPAD_LEFT || keyCode == android.view.KeyEvent
					.KEYCODE_DPAD_RIGHT)
				{
					// give "focus" to text editor, with cursor at the beginning if
					// left key, at end if right key
					// TODO: Reverse left/right for right-to-left languages, e.g.
					// Arabic
					int selPoint = (keyCode == android.view.KeyEvent.KEYCODE_DPAD_LEFT) ? 0 : mQueryTextView
						.length();
					mQueryTextView.setSelection(selPoint);
					mQueryTextView.setListSelection(0);
					mQueryTextView.clearListSelection();
					mQueryTextView.ensureImeVisible(true);
					return true;
				}
				// Next, check for an "up and out" move
				if (keyCode == android.view.KeyEvent.KEYCODE_DPAD_UP && 0 == mQueryTextView.getListSelection
					())
				{
					// TODO: restoreUserQuery();
					// let ACTV complete the move
					return false;
				}
				// Next, check for an "action key"
				android.app.SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode
					);
				if ((actionKey != null) && ((actionKey.getSuggestActionMsg() != null) || (actionKey
					.getSuggestActionMsgColumn() != null)))
				{
					// launch suggestion using action key column
					int position = mQueryTextView.getListSelection();
					if (position != android.widget.AdapterView.INVALID_POSITION)
					{
						android.database.Cursor c = mSuggestionsAdapter.getCursor();
						if (c.moveToPosition(position))
						{
							string actionMsg = getActionKeyMessage(c, actionKey);
							if (actionMsg != null && (actionMsg.Length > 0))
							{
								return onItemClicked(position, keyCode, actionMsg);
							}
						}
					}
				}
			}
			return false;
		}
		/// <summary>Checks a generic motion event.</summary>
		/// <remarks>Checks a generic motion event.</remarks>
		/// <param name="event">The event.</param>
		/// <param name="nestingLevel">
		/// The nesting level: 0 if called from the base class,
		/// or 1 from a subclass.  If the event was already checked by this consistency verifier
		/// at a higher nesting level, it will not be checked again.  Used to handle the situation
		/// where a subclass dispatching method delegates to its superclass's dispatching method
		/// and both dispatching methods call into the consistency verifier.
		/// </param>
		public void onGenericMotionEvent(android.view.MotionEvent @event, int nestingLevel
			)
		{
			if (!startEvent(@event, nestingLevel, EVENT_TYPE_GENERIC_MOTION))
			{
				return;
			}
			try
			{
				ensureMetaStateIsNormalized(@event.getMetaState());
				int action = @event.getAction();
				int source = @event.getSource();
				if ((source & android.view.InputDevice.SOURCE_CLASS_POINTER) != 0)
				{
					switch (action)
					{
						case android.view.MotionEvent.ACTION_HOVER_ENTER:
						{
							ensurePointerCountIsOneForThisAction(@event);
							mHoverEntered = true;
							break;
						}

						case android.view.MotionEvent.ACTION_HOVER_MOVE:
						{
							ensurePointerCountIsOneForThisAction(@event);
							break;
						}

						case android.view.MotionEvent.ACTION_HOVER_EXIT:
						{
							ensurePointerCountIsOneForThisAction(@event);
							if (!mHoverEntered)
							{
								problem("ACTION_HOVER_EXIT without prior ACTION_HOVER_ENTER");
							}
							mHoverEntered = false;
							break;
						}

						case android.view.MotionEvent.ACTION_SCROLL:
						{
							ensureHistorySizeIsZeroForThisAction(@event);
							ensurePointerCountIsOneForThisAction(@event);
							break;
						}

						default:
						{
							problem("Invalid action for generic pointer event.");
							break;
						}
					}
				}
				else
				{
					if ((source & android.view.InputDevice.SOURCE_CLASS_JOYSTICK) != 0)
					{
						switch (action)
						{
							case android.view.MotionEvent.ACTION_MOVE:
							{
								ensurePointerCountIsOneForThisAction(@event);
								break;
							}

							default:
							{
								problem("Invalid action for generic joystick event.");
								break;
							}
						}
					}
				}
			}
			finally
			{
				finishEvent();
			}
		}
		/// <summary>Checks a touch event.</summary>
		/// <remarks>Checks a touch event.</remarks>
		/// <param name="event">The event.</param>
		/// <param name="nestingLevel">
		/// The nesting level: 0 if called from the base class,
		/// or 1 from a subclass.  If the event was already checked by this consistency verifier
		/// at a higher nesting level, it will not be checked again.  Used to handle the situation
		/// where a subclass dispatching method delegates to its superclass's dispatching method
		/// and both dispatching methods call into the consistency verifier.
		/// </param>
		public void onTouchEvent(android.view.MotionEvent @event, int nestingLevel)
		{
			if (!startEvent(@event, nestingLevel, EVENT_TYPE_TOUCH))
			{
				return;
			}
			int action = @event.getAction();
			bool newStream = action == android.view.MotionEvent.ACTION_DOWN || action == android.view.MotionEvent
				.ACTION_CANCEL;
			if (newStream && (mTouchEventStreamIsTainted || mTouchEventStreamUnhandled))
			{
				mTouchEventStreamIsTainted = false;
				mTouchEventStreamUnhandled = false;
				mTouchEventStreamPointers = 0;
			}
			if (mTouchEventStreamIsTainted)
			{
				@event.setTainted(true);
			}
			try
			{
				ensureMetaStateIsNormalized(@event.getMetaState());
				int deviceId = @event.getDeviceId();
				int source = @event.getSource();
				if (!newStream && mTouchEventStreamDeviceId != -1 && (mTouchEventStreamDeviceId !=
					 deviceId || mTouchEventStreamSource != source))
				{
					problem("Touch event stream contains events from multiple sources: " + "previous device id "
						 + mTouchEventStreamDeviceId + ", previous source " + Sharpen.Util.IntToHexString
						(mTouchEventStreamSource) + ", new device id " + deviceId + ", new source " + Sharpen.Util.IntToHexString
						(source));
				}
				mTouchEventStreamDeviceId = deviceId;
				mTouchEventStreamSource = source;
				int pointerCount = @event.getPointerCount();
				if ((source & android.view.InputDevice.SOURCE_CLASS_POINTER) != 0)
				{
					switch (action)
					{
						case android.view.MotionEvent.ACTION_DOWN:
						{
							if (mTouchEventStreamPointers != 0)
							{
								problem("ACTION_DOWN but pointers are already down.  " + "Probably missing ACTION_UP from previous gesture."
									);
							}
							ensureHistorySizeIsZeroForThisAction(@event);
							ensurePointerCountIsOneForThisAction(@event);
							mTouchEventStreamPointers = 1 << @event.getPointerId(0);
							break;
						}

						case android.view.MotionEvent.ACTION_UP:
						{
							ensureHistorySizeIsZeroForThisAction(@event);
							ensurePointerCountIsOneForThisAction(@event);
							mTouchEventStreamPointers = 0;
							mTouchEventStreamIsTainted = false;
							break;
						}

						case android.view.MotionEvent.ACTION_MOVE:
						{
							int expectedPointerCount = Sharpen.Util.IntGetBitCount(mTouchEventStreamPointers);
							if (pointerCount != expectedPointerCount)
							{
								problem("ACTION_MOVE contained " + pointerCount + " pointers but there are currently "
									 + expectedPointerCount + " pointers down.");
								mTouchEventStreamIsTainted = true;
							}
							break;
						}

						case android.view.MotionEvent.ACTION_CANCEL:
						{
							mTouchEventStreamPointers = 0;
							mTouchEventStreamIsTainted = false;
							break;
						}

						case android.view.MotionEvent.ACTION_OUTSIDE:
						{
							if (mTouchEventStreamPointers != 0)
							{
								problem("ACTION_OUTSIDE but pointers are still down.");
							}
							ensureHistorySizeIsZeroForThisAction(@event);
							ensurePointerCountIsOneForThisAction(@event);
							mTouchEventStreamIsTainted = false;
							break;
						}

						default:
						{
							int actionMasked = @event.getActionMasked();
							int actionIndex = @event.getActionIndex();
							if (actionMasked == android.view.MotionEvent.ACTION_POINTER_DOWN)
							{
								if (mTouchEventStreamPointers == 0)
								{
									problem("ACTION_POINTER_DOWN but no other pointers were down.");
									mTouchEventStreamIsTainted = true;
								}
								if (actionIndex < 0 || actionIndex >= pointerCount)
								{
									problem("ACTION_POINTER_DOWN index is " + actionIndex + " but the pointer count is "
										 + pointerCount + ".");
									mTouchEventStreamIsTainted = true;
								}
								else
								{
									int id = @event.getPointerId(actionIndex);
									int idBit = 1 << id;
									if ((mTouchEventStreamPointers & idBit) != 0)
									{
										problem("ACTION_POINTER_DOWN specified pointer id " + id + " which is already down."
											);
										mTouchEventStreamIsTainted = true;
									}
									else
									{
										mTouchEventStreamPointers |= idBit;
									}
								}
								ensureHistorySizeIsZeroForThisAction(@event);
							}
							else
							{
								if (actionMasked == android.view.MotionEvent.ACTION_POINTER_UP)
								{
									if (actionIndex < 0 || actionIndex >= pointerCount)
									{
										problem("ACTION_POINTER_UP index is " + actionIndex + " but the pointer count is "
											 + pointerCount + ".");
										mTouchEventStreamIsTainted = true;
									}
									else
									{
										int id = @event.getPointerId(actionIndex);
										int idBit = 1 << id;
										if ((mTouchEventStreamPointers & idBit) == 0)
										{
											problem("ACTION_POINTER_UP specified pointer id " + id + " which is not currently down."
												);
											mTouchEventStreamIsTainted = true;
										}
										else
										{
											mTouchEventStreamPointers &= ~idBit;
										}
									}
									ensureHistorySizeIsZeroForThisAction(@event);
								}
								else
								{
									problem("Invalid action " + android.view.MotionEvent.actionToString(action) + " for touch event."
										);
								}
							}
							break;
						}
					}
				}
				else
				{
					problem("Source was not SOURCE_CLASS_POINTER.");
				}
			}
			finally
			{
				finishEvent();
			}
		}
		/// <summary>Checks a trackball event.</summary>
		/// <remarks>Checks a trackball event.</remarks>
		/// <param name="event">The event.</param>
		/// <param name="nestingLevel">
		/// The nesting level: 0 if called from the base class,
		/// or 1 from a subclass.  If the event was already checked by this consistency verifier
		/// at a higher nesting level, it will not be checked again.  Used to handle the situation
		/// where a subclass dispatching method delegates to its superclass's dispatching method
		/// and both dispatching methods call into the consistency verifier.
		/// </param>
		public void onTrackballEvent(android.view.MotionEvent @event, int nestingLevel)
		{
			if (!startEvent(@event, nestingLevel, EVENT_TYPE_TRACKBALL))
			{
				return;
			}
			try
			{
				ensureMetaStateIsNormalized(@event.getMetaState());
				int action = @event.getAction();
				int source = @event.getSource();
				if ((source & android.view.InputDevice.SOURCE_CLASS_TRACKBALL) != 0)
				{
					switch (action)
					{
						case android.view.MotionEvent.ACTION_DOWN:
						{
							if (mTrackballDown && !mTrackballUnhandled)
							{
								problem("ACTION_DOWN but trackball is already down.");
							}
							else
							{
								mTrackballDown = true;
								mTrackballUnhandled = false;
							}
							ensureHistorySizeIsZeroForThisAction(@event);
							ensurePointerCountIsOneForThisAction(@event);
							break;
						}

						case android.view.MotionEvent.ACTION_UP:
						{
							if (!mTrackballDown)
							{
								problem("ACTION_UP but trackball is not down.");
							}
							else
							{
								mTrackballDown = false;
								mTrackballUnhandled = false;
							}
							ensureHistorySizeIsZeroForThisAction(@event);
							ensurePointerCountIsOneForThisAction(@event);
							break;
						}

						case android.view.MotionEvent.ACTION_MOVE:
						{
							ensurePointerCountIsOneForThisAction(@event);
							break;
						}

						default:
						{
							problem("Invalid action " + android.view.MotionEvent.actionToString(action) + " for trackball event."
								);
							break;
						}
					}
					if (mTrackballDown && @event.getPressure() <= 0)
					{
						problem("Trackball is down but pressure is not greater than 0.");
					}
					else
					{
						if (!mTrackballDown && @event.getPressure() != 0)
						{
							problem("Trackball is up but pressure is not equal to 0.");
						}
					}
				}
				else
				{
					problem("Source was not SOURCE_CLASS_TRACKBALL.");
				}
			}
			finally
			{
				finishEvent();
			}
		}
		/// <summary>Checks a key event.</summary>
		/// <remarks>Checks a key event.</remarks>
		/// <param name="event">The event.</param>
		/// <param name="nestingLevel">
		/// The nesting level: 0 if called from the base class,
		/// or 1 from a subclass.  If the event was already checked by this consistency verifier
		/// at a higher nesting level, it will not be checked again.  Used to handle the situation
		/// where a subclass dispatching method delegates to its superclass's dispatching method
		/// and both dispatching methods call into the consistency verifier.
		/// </param>
		public void onKeyEvent(android.view.KeyEvent @event, int nestingLevel)
		{
			if (!startEvent(@event, nestingLevel, EVENT_TYPE_KEY))
			{
				return;
			}
			try
			{
				ensureMetaStateIsNormalized(@event.getMetaState());
				int action = @event.getAction();
				int deviceId = @event.getDeviceId();
				int source = @event.getSource();
				int keyCode = @event.getKeyCode();
				switch (action)
				{
					case android.view.KeyEvent.ACTION_DOWN:
					{
						android.view.InputEventConsistencyVerifier.KeyState state = findKeyState(deviceId
							, source, keyCode, false);
						if (state != null)
						{
							// If the key is already down, ensure it is a repeat.
							// We don't perform this check when processing raw device input
							// because the input dispatcher itself is responsible for setting
							// the key repeat count before it delivers input events.
							if (state.unhandled)
							{
								state.unhandled = false;
							}
							else
							{
								if ((mFlags & FLAG_RAW_DEVICE_INPUT) == 0 && @event.getRepeatCount() == 0)
								{
									problem("ACTION_DOWN but key is already down and this event " + "is not a key repeat."
										);
								}
							}
						}
						else
						{
							addKeyState(deviceId, source, keyCode);
						}
						break;
					}

					case android.view.KeyEvent.ACTION_UP:
					{
						android.view.InputEventConsistencyVerifier.KeyState state = findKeyState(deviceId
							, source, keyCode, true);
						if (state == null)
						{
							problem("ACTION_UP but key was not down.");
						}
						else
						{
							state.recycle();
						}
						break;
					}

					case android.view.KeyEvent.ACTION_MULTIPLE:
					{
						break;
					}

					default:
					{
						problem("Invalid action " + android.view.KeyEvent.actionToString(action) + " for key event."
							);
						break;
					}
				}
			}
			finally
			{
				finishEvent();
			}
		}
Esempio n. 18
0
		public override bool onTouchEvent(android.view.MotionEvent @event)
		{
			// Give everything to the gesture detector
			bool retValue = mGestureDetector.onTouchEvent(@event);
			int action = @event.getAction();
			if (action == android.view.MotionEvent.ACTION_UP)
			{
				// Helper method for lifted finger
				onUp();
			}
			else
			{
				if (action == android.view.MotionEvent.ACTION_CANCEL)
				{
					onCancel();
				}
			}
			return retValue;
		}
Esempio n. 19
0
		public virtual bool dispatchTouchEvent(android.view.MotionEvent ev)
		{
			if (ev.getAction() == android.view.MotionEvent.ACTION_DOWN)
			{
				onUserInteraction();
			}
			if (getWindow().superDispatchTouchEvent(ev))
			{
				return true;
			}
			return onTouchEvent(ev);
		}
Esempio n. 20
0
		public virtual bool onTouch(android.view.View v, android.view.MotionEvent @event)
		{
			int action = @event.getAction();
			if (@event.getPointerCount() > 1)
			{
				// ZoomButtonsController doesn't handle mutitouch. Give up control.
				return false;
			}
			if (mReleaseTouchListenerOnUp)
			{
				// The controls were dismissed but we need to throw away all events until the up
				if (action == android.view.MotionEvent.ACTION_UP || action == android.view.MotionEvent
					.ACTION_CANCEL)
				{
					mOwnerView.setOnTouchListener(null);
					setTouchTargetView(null);
					mReleaseTouchListenerOnUp = false;
				}
				// Eat this event
				return true;
			}
			dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT);
			android.view.View targetView = mTouchTargetView;
			switch (action)
			{
				case android.view.MotionEvent.ACTION_DOWN:
				{
					targetView = findViewForTouch((int)@event.getRawX(), (int)@event.getRawY());
					setTouchTargetView(targetView);
					break;
				}

				case android.view.MotionEvent.ACTION_UP:
				case android.view.MotionEvent.ACTION_CANCEL:
				{
					setTouchTargetView(null);
					break;
				}
			}
			if (targetView != null)
			{
				// The upperleft corner of the target view in raw coordinates
				int targetViewRawX = mContainerRawLocation[0] + mTouchTargetWindowLocation[0];
				int targetViewRawY = mContainerRawLocation[1] + mTouchTargetWindowLocation[1];
				android.view.MotionEvent containerEvent = android.view.MotionEvent.obtain(@event);
				// Convert the motion event into the target view's coordinates (from
				// owner view's coordinates)
				containerEvent.offsetLocation(mOwnerViewRawLocation[0] - targetViewRawX, mOwnerViewRawLocation
					[1] - targetViewRawY);
				// These are floats because we need to potentially offset away this exact amount
				float containerX = containerEvent.getX();
				float containerY = containerEvent.getY();
				if (containerX < 0 && containerX > -ZOOM_CONTROLS_TOUCH_PADDING)
				{
					containerEvent.offsetLocation(-containerX, 0);
				}
				if (containerY < 0 && containerY > -ZOOM_CONTROLS_TOUCH_PADDING)
				{
					containerEvent.offsetLocation(0, -containerY);
				}
				bool retValue = targetView.dispatchTouchEvent(containerEvent);
				containerEvent.recycle();
				return retValue;
			}
			else
			{
				return false;
			}
		}
Esempio n. 21
0
			public bool onKey(android.view.View v, int keyCode, android.view.KeyEvent @event)
			{
				// guard against possible race conditions
				if (this._enclosing.mSearchable == null)
				{
					return false;
				}
				// If a suggestion is selected, handle enter, search key, and action keys
				// as presses on the selected suggestion
				if (this._enclosing.mQueryTextView.isPopupShowing() && this._enclosing.mQueryTextView
					.getListSelection() != android.widget.AdapterView.INVALID_POSITION)
				{
					return this._enclosing.onSuggestionsKey(v, keyCode, @event);
				}
				// If there is text in the query box, handle enter, and action keys
				// The search key is handled by the dialog's onKeyDown().
				if (!this._enclosing.mQueryTextView.isEmpty() && @event.hasNoModifiers())
				{
					if (@event.getAction() == android.view.KeyEvent.ACTION_UP)
					{
						if (keyCode == android.view.KeyEvent.KEYCODE_ENTER)
						{
							v.cancelLongPress();
							// Launch as a regular search.
							this._enclosing.launchQuerySearch(android.view.KeyEvent.KEYCODE_UNKNOWN, null, ((
								android.text.Editable)this._enclosing.mQueryTextView.getText()).ToString());
							return true;
						}
					}
					if (@event.getAction() == android.view.KeyEvent.ACTION_DOWN)
					{
						android.app.SearchableInfo.ActionKeyInfo actionKey = this._enclosing.mSearchable.
							findActionKey(keyCode);
						if ((actionKey != null) && (actionKey.getQueryActionMsg() != null))
						{
							this._enclosing.launchQuerySearch(keyCode, actionKey.getQueryActionMsg(), ((android.text.Editable
								)this._enclosing.mQueryTextView.getText()).ToString());
							return true;
						}
					}
				}
				return false;
			}
		private void ensurePointerCountIsOneForThisAction(android.view.MotionEvent @event
			)
		{
			int pointerCount = @event.getPointerCount();
			if (pointerCount != 1)
			{
				problem("Pointer count is " + pointerCount + " but it should always be 1 for " + 
					android.view.MotionEvent.actionToString(@event.getAction()));
			}
		}
Esempio n. 23
0
			public override bool onKeyPreIme(int keyCode, android.view.KeyEvent @event)
			{
				if (keyCode == android.view.KeyEvent.KEYCODE_BACK)
				{
					// special case for the back key, we do not even try to send it
					// to the drop down list but instead, consume it immediately
					if (@event.getAction() == android.view.KeyEvent.ACTION_DOWN && @event.getRepeatCount
						() == 0)
					{
						android.view.KeyEvent.DispatcherState state = getKeyDispatcherState();
						if (state != null)
						{
							state.startTracking(@event, this);
						}
						return true;
					}
					else
					{
						if (@event.getAction() == android.view.KeyEvent.ACTION_UP)
						{
							android.view.KeyEvent.DispatcherState state = getKeyDispatcherState();
							if (state != null)
							{
								state.handleUpEvent(@event);
							}
							if (@event.isTracking() && [email protected]())
							{
								mSearchView.clearFocus();
								mSearchView.setImeVisibility(false);
								return true;
							}
						}
					}
				}
				return base.onKeyPreIme(keyCode, @event);
			}
		private void ensureHistorySizeIsZeroForThisAction(android.view.MotionEvent @event
			)
		{
			int historySize = @event.getHistorySize();
			if (historySize != 0)
			{
				problem("History size is " + historySize + " but it should always be 0 for " + android.view.MotionEvent
					.actionToString(@event.getAction()));
			}
		}
Esempio n. 25
0
			public virtual bool onTouch(android.view.View v, android.view.MotionEvent @event)
			{
				int action = @event.getAction();
				int x = (int)@event.getX();
				int y = (int)@event.getY();
				if (action == android.view.MotionEvent.ACTION_DOWN && this._enclosing.mPopup != null
					 && this._enclosing.mPopup.isShowing() && (x >= 0 && x < this._enclosing.mPopup.
					getWidth() && y >= 0 && y < this._enclosing.mPopup.getHeight()))
				{
					this._enclosing.mHandler.postDelayed(this._enclosing.mResizePopupRunnable, android.widget.ListPopupWindow
						.EXPAND_LIST_TIMEOUT);
				}
				else
				{
					if (action == android.view.MotionEvent.ACTION_UP)
					{
						this._enclosing.mHandler.removeCallbacks(this._enclosing.mResizePopupRunnable);
					}
				}
				return false;
			}
Esempio n. 26
0
		private void onSecondaryPointerUp(android.view.MotionEvent ev)
		{
			int pointerIndex = (ev.getAction() & android.view.MotionEvent.ACTION_POINTER_INDEX_MASK
				) >> android.view.MotionEvent.ACTION_POINTER_INDEX_SHIFT;
			int pointerId = ev.getPointerId(pointerIndex);
			if (pointerId == mActivePointerId)
			{
				// This was our active pointer going up. Choose a new
				// active pointer and adjust accordingly.
				// TODO: Make this decision more intelligent.
				int newPointerIndex = pointerIndex == 0 ? 1 : 0;
				mLastMotionX = ev.getX(newPointerIndex);
				mActivePointerId = ev.getPointerId(newPointerIndex);
				if (mVelocityTracker != null)
				{
					mVelocityTracker.clear();
				}
			}
		}
Esempio n. 27
0
			public override bool onTouchEvent(android.view.MotionEvent @event)
			{
				int x = (int)@event.getX();
				int y = (int)@event.getY();
				if ((@event.getAction() == android.view.MotionEvent.ACTION_DOWN) && ((x < 0) || (
					x >= this.getWidth()) || (y < 0) || (y >= this.getHeight())))
				{
					this._enclosing.dismiss();
					return true;
				}
				else
				{
					if (@event.getAction() == android.view.MotionEvent.ACTION_OUTSIDE)
					{
						this._enclosing.dismiss();
						return true;
					}
					else
					{
						return base.onTouchEvent(@event);
					}
				}
			}
Esempio n. 28
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;
		}
Esempio n. 29
0
		protected internal override bool dispatchHoverEvent(android.view.MotionEvent @event
			)
		{
			int action = @event.getAction();
			// First check whether the view group wants to intercept the hover event.
			bool interceptHover = onInterceptHoverEvent(@event);
			@event.setAction(action);
			// restore action in case it was changed
			android.view.MotionEvent eventNoHistory = @event;
			bool handled = false;
			// Send events to the hovered children and build a new list of hover targets until
			// one is found that handles the event.
			android.view.ViewGroup.HoverTarget firstOldHoverTarget = mFirstHoverTarget;
			mFirstHoverTarget = null;
			if (!interceptHover && action != android.view.MotionEvent.ACTION_HOVER_EXIT)
			{
				float x = @event.getX();
				float y = @event.getY();
				int childrenCount = mChildrenCount;
				if (childrenCount != 0)
				{
					android.view.View[] children = mChildren;
					android.view.ViewGroup.HoverTarget lastHoverTarget = null;
					{
						for (int i = childrenCount - 1; i >= 0; i--)
						{
							android.view.View child = children[i];
							if (!canViewReceivePointerEvents(child) || !isTransformedTouchPointInView(x, y, child
								, null))
							{
								continue;
							}
							// Obtain a hover target for this child.  Dequeue it from the
							// old hover target list if the child was previously hovered.
							android.view.ViewGroup.HoverTarget hoverTarget = firstOldHoverTarget;
							bool wasHovered;
							{
								for (android.view.ViewGroup.HoverTarget predecessor = null; ; )
								{
									if (hoverTarget == null)
									{
										hoverTarget = android.view.ViewGroup.HoverTarget.obtain(child);
										wasHovered = false;
										break;
									}
									if (hoverTarget.child == child)
									{
										if (predecessor != null)
										{
											predecessor.next = hoverTarget.next;
										}
										else
										{
											firstOldHoverTarget = hoverTarget.next;
										}
										hoverTarget.next = null;
										wasHovered = true;
										break;
									}
									predecessor = hoverTarget;
									hoverTarget = hoverTarget.next;
								}
							}
							// Enqueue the hover target onto the new hover target list.
							if (lastHoverTarget != null)
							{
								lastHoverTarget.next = hoverTarget;
							}
							else
							{
								lastHoverTarget = hoverTarget;
								mFirstHoverTarget = hoverTarget;
							}
							// Dispatch the event to the child.
							if (action == android.view.MotionEvent.ACTION_HOVER_ENTER)
							{
								if (!wasHovered)
								{
									// Send the enter as is.
									handled |= dispatchTransformedGenericPointerEvent(@event, child);
								}
							}
							else
							{
								// enter
								if (action == android.view.MotionEvent.ACTION_HOVER_MOVE)
								{
									if (!wasHovered)
									{
										// Synthesize an enter from a move.
										eventNoHistory = obtainMotionEventNoHistoryOrSelf(eventNoHistory);
										eventNoHistory.setAction(android.view.MotionEvent.ACTION_HOVER_ENTER);
										handled |= dispatchTransformedGenericPointerEvent(eventNoHistory, child);
										// enter
										eventNoHistory.setAction(action);
										handled |= dispatchTransformedGenericPointerEvent(eventNoHistory, child);
									}
									else
									{
										// move
										// Send the move as is.
										handled |= dispatchTransformedGenericPointerEvent(@event, child);
									}
								}
							}
							if (handled)
							{
								break;
							}
						}
					}
				}
			}
			// Send exit events to all previously hovered children that are no longer hovered.
			while (firstOldHoverTarget != null)
			{
				android.view.View child = firstOldHoverTarget.child;
				// Exit the old hovered child.
				if (action == android.view.MotionEvent.ACTION_HOVER_EXIT)
				{
					// Send the exit as is.
					handled |= dispatchTransformedGenericPointerEvent(@event, child);
				}
				else
				{
					// exit
					// Synthesize an exit from a move or enter.
					// Ignore the result because hover focus has moved to a different view.
					if (action == android.view.MotionEvent.ACTION_HOVER_MOVE)
					{
						dispatchTransformedGenericPointerEvent(@event, child);
					}
					// move
					eventNoHistory = obtainMotionEventNoHistoryOrSelf(eventNoHistory);
					eventNoHistory.setAction(android.view.MotionEvent.ACTION_HOVER_EXIT);
					dispatchTransformedGenericPointerEvent(eventNoHistory, child);
					// exit
					eventNoHistory.setAction(action);
				}
				android.view.ViewGroup.HoverTarget nextOldHoverTarget = firstOldHoverTarget.next;
				firstOldHoverTarget.recycle();
				firstOldHoverTarget = nextOldHoverTarget;
			}
			// Send events to the view group itself if no children have handled it.
			bool newHoveredSelf = !handled;
			if (newHoveredSelf == mHoveredSelf)
			{
				if (newHoveredSelf)
				{
					// Send event to the view group as before.
					handled |= base.dispatchHoverEvent(@event);
				}
			}
			else
			{
				if (mHoveredSelf)
				{
					// Exit the view group.
					if (action == android.view.MotionEvent.ACTION_HOVER_EXIT)
					{
						// Send the exit as is.
						handled |= base.dispatchHoverEvent(@event);
					}
					else
					{
						// exit
						// Synthesize an exit from a move or enter.
						// Ignore the result because hover focus is moving to a different view.
						if (action == android.view.MotionEvent.ACTION_HOVER_MOVE)
						{
							base.dispatchHoverEvent(@event);
						}
						// move
						eventNoHistory = obtainMotionEventNoHistoryOrSelf(eventNoHistory);
						eventNoHistory.setAction(android.view.MotionEvent.ACTION_HOVER_EXIT);
						base.dispatchHoverEvent(eventNoHistory);
						// exit
						eventNoHistory.setAction(action);
					}
					mHoveredSelf = false;
				}
				if (newHoveredSelf)
				{
					// Enter the view group.
					if (action == android.view.MotionEvent.ACTION_HOVER_ENTER)
					{
						// Send the enter as is.
						handled |= base.dispatchHoverEvent(@event);
						// enter
						mHoveredSelf = true;
					}
					else
					{
						if (action == android.view.MotionEvent.ACTION_HOVER_MOVE)
						{
							// Synthesize an enter from a move.
							eventNoHistory = obtainMotionEventNoHistoryOrSelf(eventNoHistory);
							eventNoHistory.setAction(android.view.MotionEvent.ACTION_HOVER_ENTER);
							handled |= base.dispatchHoverEvent(eventNoHistory);
							// enter
							eventNoHistory.setAction(action);
							handled |= base.dispatchHoverEvent(eventNoHistory);
							// move
							mHoveredSelf = true;
						}
					}
				}
			}
			// Recycle the copy of the event that we made.
			if (eventNoHistory != @event)
			{
				eventNoHistory.recycle();
			}
			// Done.
			return handled;
		}
Esempio n. 30
0
		public override bool onGenericMotionEvent(android.view.MotionEvent @event)
		{
			if ((@event.getSource() & android.view.InputDevice.SOURCE_CLASS_POINTER) != 0)
			{
				switch (@event.getAction())
				{
					case android.view.MotionEvent.ACTION_SCROLL:
					{
						if (!mIsBeingDragged)
						{
							float hscroll;
							if ((@event.getMetaState() & android.view.KeyEvent.META_SHIFT_ON) != 0)
							{
								hscroll = [email protected](android.view.MotionEvent.AXIS_VSCROLL);
							}
							else
							{
								hscroll = @event.getAxisValue(android.view.MotionEvent.AXIS_HSCROLL);
							}
							if (hscroll != 0)
							{
								int delta = (int)(hscroll * getHorizontalScrollFactor());
								int range = getScrollRange();
								int oldScrollX = mScrollX;
								int newScrollX = oldScrollX + delta;
								if (newScrollX < 0)
								{
									newScrollX = 0;
								}
								else
								{
									if (newScrollX > range)
									{
										newScrollX = range;
									}
								}
								if (newScrollX != oldScrollX)
								{
									base.scrollTo(newScrollX, mScrollY);
									return true;
								}
							}
						}
						break;
					}
				}
			}
			return base.onGenericMotionEvent(@event);
		}