Example #1
0
		private bool backspaceOrForwardDelete(android.view.View view, android.text.Editable
			 content, int keyCode, android.view.KeyEvent @event, bool isForwardDelete)
		{
			// Ensure the key event does not have modifiers except ALT or SHIFT.
			if (!android.view.KeyEvent.metaStateHasNoModifiers(@event.getMetaState() & ~(android.view.KeyEvent
				.META_SHIFT_MASK | android.view.KeyEvent.META_ALT_MASK)))
			{
				return false;
			}
			// If there is a current selection, delete it.
			if (deleteSelection(view, content))
			{
				return true;
			}
			// Alt+Backspace or Alt+ForwardDelete deletes the current line, if possible.
			if (@event.isAltPressed() || getMetaState(content, META_ALT_ON) == 1)
			{
				if (deleteLine(view, content))
				{
					return true;
				}
			}
			// Delete a character.
			int start = android.text.Selection.getSelectionEnd(content);
			int end;
			if (isForwardDelete || @event.isShiftPressed() || getMetaState(content, META_SHIFT_ON
				) == 1)
			{
				end = android.text.TextUtils.getOffsetAfter(content, start);
			}
			else
			{
				end = android.text.TextUtils.getOffsetBefore(content, start);
			}
			if (start != end)
			{
				content.delete(System.Math.Min(start, end), System.Math.Max(start, end));
				return true;
			}
			return false;
		}
Example #2
0
		public override bool onKeyDown(android.view.View view, android.text.Editable content
			, int keyCode, android.view.KeyEvent @event)
		{
			int selStart;
			int selEnd;
			int pref = 0;
			if (view != null)
			{
				pref = android.text.method.TextKeyListener.getInstance().getPrefs(view.getContext
					());
			}
			{
				int a = android.text.Selection.getSelectionStart(content);
				int b = android.text.Selection.getSelectionEnd(content);
				selStart = System.Math.Min(a, b);
				selEnd = System.Math.Max(a, b);
				if (selStart < 0 || selEnd < 0)
				{
					selStart = selEnd = 0;
					android.text.Selection.setSelection(content, 0, 0);
				}
			}
			int activeStart = content.getSpanStart(android.text.method.TextKeyListener.ACTIVE
				);
			int activeEnd = content.getSpanEnd(android.text.method.TextKeyListener.ACTIVE);
			// QWERTY keyboard normal case
			int i = @event.getUnicodeChar(@event.getMetaState() | getMetaState(content));
			if (!mFullKeyboard)
			{
				int count = @event.getRepeatCount();
				if (count > 0 && selStart == selEnd && selStart > 0)
				{
					char c = content[selStart - 1];
					if (c == i || c == Sharpen.CharHelper.ToUpper(i) && view != null)
					{
						if (showCharacterPicker(view, content, c, false, count))
						{
							resetMetaState(content);
							return true;
						}
					}
				}
			}
			if (i == android.view.KeyCharacterMap.PICKER_DIALOG_INPUT)
			{
				if (view != null)
				{
					showCharacterPicker(view, content, android.view.KeyCharacterMap.PICKER_DIALOG_INPUT
						, true, 1);
				}
				resetMetaState(content);
				return true;
			}
			if (i == android.view.KeyCharacterMap.HEX_INPUT)
			{
				int start;
				if (selStart == selEnd)
				{
					start = selEnd;
					while (start > 0 && selEnd - start < 4 && Sharpen.CharHelper.Digit(content[start 
						- 1], 16) >= 0)
					{
						start--;
					}
				}
				else
				{
					start = selStart;
				}
				int ch = -1;
				try
				{
					string hex = android.text.TextUtils.substring(content, start, selEnd);
					ch = System.Convert.ToInt32(hex, 16);
				}
				catch (System.ArgumentException)
				{
				}
				if (ch >= 0)
				{
					selStart = start;
					android.text.Selection.setSelection(content, selStart, selEnd);
					i = ch;
				}
				else
				{
					i = 0;
				}
			}
			if (i != 0)
			{
				bool dead = false;
				if ((i & android.view.KeyCharacterMap.COMBINING_ACCENT) != 0)
				{
					dead = true;
					i = i & android.view.KeyCharacterMap.COMBINING_ACCENT_MASK;
				}
				if (activeStart == selStart && activeEnd == selEnd)
				{
					bool replace = false;
					if (selEnd - selStart - 1 == 0)
					{
						char accent = content[selStart];
						int composed = android.view.KeyEvent.getDeadChar(accent, i);
						if (composed != 0)
						{
							i = composed;
							replace = true;
						}
					}
					if (!replace)
					{
						android.text.Selection.setSelection(content, selEnd);
						content.removeSpan(android.text.method.TextKeyListener.ACTIVE);
						selStart = selEnd;
					}
				}
				if ((pref & android.text.method.TextKeyListener.AUTO_CAP) != 0 && Sharpen.CharHelper.IsLower
					(i) && android.text.method.TextKeyListener.shouldCap(mAutoCap, content, selStart
					))
				{
					int where = content.getSpanEnd(android.text.method.TextKeyListener.CAPPED);
					int flags = content.getSpanFlags(android.text.method.TextKeyListener.CAPPED);
					if (where == selStart && (((flags >> 16) & unchecked((int)(0xFFFF))) == i))
					{
						content.removeSpan(android.text.method.TextKeyListener.CAPPED);
					}
					else
					{
						flags = i << 16;
						i = Sharpen.CharHelper.ToUpper(i);
						if (selStart == 0)
						{
							content.setSpan(android.text.method.TextKeyListener.CAPPED, 0, 0, android.text.SpannedClass.SPAN_MARK_MARK
								 | flags);
						}
						else
						{
							content.setSpan(android.text.method.TextKeyListener.CAPPED, selStart - 1, selStart
								, android.text.SpannedClass.SPAN_EXCLUSIVE_EXCLUSIVE | flags);
						}
					}
				}
				if (selStart != selEnd)
				{
					android.text.Selection.setSelection(content, selEnd);
				}
				content.setSpan(OLD_SEL_START, selStart, selStart, android.text.SpannedClass.SPAN_MARK_MARK
					);
				content.replace(selStart, selEnd, java.lang.CharSequenceProxy.Wrap(((char)i).ToString
					()));
				int oldStart = content.getSpanStart(OLD_SEL_START);
				selEnd = android.text.Selection.getSelectionEnd(content);
				if (oldStart < selEnd)
				{
					content.setSpan(android.text.method.TextKeyListener.LAST_TYPED, oldStart, selEnd, 
						android.text.SpannedClass.SPAN_EXCLUSIVE_EXCLUSIVE);
					if (dead)
					{
						android.text.Selection.setSelection(content, oldStart, selEnd);
						content.setSpan(android.text.method.TextKeyListener.ACTIVE, oldStart, selEnd, android.text.SpannedClass.SPAN_EXCLUSIVE_EXCLUSIVE
							);
					}
				}
				adjustMetaAfterKeypress(content);
				// potentially do autotext replacement if the character
				// that was typed was an autotext terminator
				if ((pref & android.text.method.TextKeyListener.AUTO_TEXT) != 0 && mAutoText && (
					i == ' ' || i == '\t' || i == '\n' || i == ',' || i == '.' || i == '!' || i == '?'
					 || i == '"' || Sharpen.CharHelper.GetType(i) == Sharpen.CharHelper.END_PUNCTUATION
					) && content.getSpanEnd(android.text.method.TextKeyListener.INHIBIT_REPLACEMENT)
					 != oldStart)
				{
					int x;
					for (x = oldStart; x > 0; x--)
					{
						char c = content[x - 1];
						if (c != '\'' && !System.Char.IsLetter(c))
						{
							break;
						}
					}
					string rep = getReplacement(content, x, oldStart, view);
					if (rep != null)
					{
						android.text.method.QwertyKeyListener.Replaced[] repl = content.getSpans<android.text.method.QwertyKeyListener
							.Replaced>(0, content.Length);
						{
							for (int a = 0; a < repl.Length; a++)
							{
								content.removeSpan(repl[a]);
							}
						}
						char[] orig = new char[oldStart - x];
						android.text.TextUtils.getChars(content, x, oldStart, orig, 0);
						content.setSpan(new android.text.method.QwertyKeyListener.Replaced(orig), x, oldStart
							, android.text.SpannedClass.SPAN_EXCLUSIVE_EXCLUSIVE);
						content.replace(x, oldStart, java.lang.CharSequenceProxy.Wrap(rep));
					}
				}
				// Replace two spaces by a period and a space.
				if ((pref & android.text.method.TextKeyListener.AUTO_PERIOD) != 0 && mAutoText)
				{
					selEnd = android.text.Selection.getSelectionEnd(content);
					if (selEnd - 3 >= 0)
					{
						if (content[selEnd - 1] == ' ' && content[selEnd - 2] == ' ')
						{
							char c = content[selEnd - 3];
							{
								for (int j = selEnd - 3; j > 0; j--)
								{
									if (c == '"' || Sharpen.CharHelper.GetType(c) == Sharpen.CharHelper.END_PUNCTUATION)
									{
										c = content[j - 1];
									}
									else
									{
										break;
									}
								}
							}
							if (System.Char.IsLetter(c) || System.Char.IsDigit(c))
							{
								content.replace(selEnd - 2, selEnd - 1, java.lang.CharSequenceProxy.Wrap("."));
							}
						}
					}
				}
				return true;
			}
			else
			{
				if (keyCode == android.view.KeyEvent.KEYCODE_DEL && (@event.hasNoModifiers() || @event
					.hasModifiers(android.view.KeyEvent.META_ALT_ON)) && selStart == selEnd)
				{
					// special backspace case for undoing autotext
					int consider = 1;
					// if backspacing over the last typed character,
					// it undoes the autotext prior to that character
					// (unless the character typed was newline, in which
					// case this behavior would be confusing)
					if (content.getSpanEnd(android.text.method.TextKeyListener.LAST_TYPED) == selStart)
					{
						if (content[selStart - 1] != '\n')
						{
							consider = 2;
						}
					}
					android.text.method.QwertyKeyListener.Replaced[] repl = content.getSpans<android.text.method.QwertyKeyListener
						.Replaced>(selStart - consider, selStart);
					if (repl.Length > 0)
					{
						int st = content.getSpanStart(repl[0]);
						int en = content.getSpanEnd(repl[0]);
						string old = new string(repl[0].mText);
						content.removeSpan(repl[0]);
						// only cancel the autocomplete if the cursor is at the end of
						// the replaced span (or after it, because the user is
						// backspacing over the space after the word, not the word
						// itself).
						if (selStart >= en)
						{
							content.setSpan(android.text.method.TextKeyListener.INHIBIT_REPLACEMENT, en, en, 
								android.text.SpannedClass.SPAN_POINT_POINT);
							content.replace(st, en, java.lang.CharSequenceProxy.Wrap(old));
							en = content.getSpanStart(android.text.method.TextKeyListener.INHIBIT_REPLACEMENT
								);
							if (en - 1 >= 0)
							{
								content.setSpan(android.text.method.TextKeyListener.INHIBIT_REPLACEMENT, en - 1, 
									en, android.text.SpannedClass.SPAN_EXCLUSIVE_EXCLUSIVE);
							}
							else
							{
								content.removeSpan(android.text.method.TextKeyListener.INHIBIT_REPLACEMENT);
							}
							adjustMetaAfterKeypress(content);
						}
						else
						{
							adjustMetaAfterKeypress(content);
							return base.onKeyDown(view, content, keyCode, @event);
						}
						return true;
					}
				}
			}
			return base.onKeyDown(view, content, keyCode, @event);
		}
		/// <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();
			}
		}
Example #7
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);
		}
Example #8
0
		internal virtual [email protected] findItemWithShortcutForKey
			(int keyCode, android.view.KeyEvent @event)
		{
			// Get all items that can be associated directly or indirectly with the keyCode
			java.util.ArrayList<[email protected]> items = mTempShortcutItemList;
			items.clear();
			findItemsWithShortcutForKey(items, keyCode, @event);
			if (items.isEmpty())
			{
				return null;
			}
			int metaState = @event.getMetaState();
			android.view.KeyCharacterMap.KeyData possibleChars = new android.view.KeyCharacterMap
				.KeyData();
			// Get the chars associated with the keyCode (i.e using any chording combo)
			@event.getKeyData(possibleChars);
			// If we have only one element, we can safely returns it
			int size_1 = items.size();
			if (size_1 == 1)
			{
				return items.get(0);
			}
			bool qwerty = isQwertyMode();
			{
				// If we found more than one item associated with the key,
				// we have to return the exact match
				for (int i = 0; i < size_1; i++)
				{
					[email protected] item = items.get(i);
					char shortcutChar = qwerty ? item.getAlphabeticShortcut() : item.getNumericShortcut
						();
					if ((shortcutChar == possibleChars.meta[0] && (metaState & android.view.KeyEvent.
						META_ALT_ON) == 0) || (shortcutChar == possibleChars.meta[2] && (metaState & android.view.KeyEvent
						.META_ALT_ON) != 0) || (qwerty && shortcutChar == '\b' && keyCode == android.view.KeyEvent
						.KEYCODE_DEL))
					{
						return item;
					}
				}
			}
			return null;
		}
Example #9
0
		internal virtual void findItemsWithShortcutForKey(java.util.List<[email protected]
			> items, int keyCode, android.view.KeyEvent @event)
		{
			bool qwerty = isQwertyMode();
			int metaState = @event.getMetaState();
			android.view.KeyCharacterMap.KeyData possibleChars = new android.view.KeyCharacterMap
				.KeyData();
			// Get the chars associated with the keyCode (i.e using any chording combo)
			bool isKeyCodeMapped = @event.getKeyData(possibleChars);
			// The delete key is not mapped to '\b' so we treat it specially
			if (!isKeyCodeMapped && (keyCode != android.view.KeyEvent.KEYCODE_DEL))
			{
				return;
			}
			// Look for an item whose shortcut is this key.
			int N = mItems.size();
			{
				for (int i = 0; i < N; i++)
				{
					[email protected] item = mItems.get(i);
					if (item.hasSubMenu())
					{
						(([email protected])item.getSubMenu()).findItemsWithShortcutForKey
							(items, keyCode, @event);
					}
					char shortcutChar = qwerty ? item.getAlphabeticShortcut() : item.getNumericShortcut
						();
					if (((metaState & (android.view.KeyEvent.META_SHIFT_ON | android.view.KeyEvent.META_SYM_ON
						)) == 0) && (shortcutChar != 0) && (shortcutChar == possibleChars.meta[0] || shortcutChar
						 == possibleChars.meta[2] || (qwerty && shortcutChar == '\b' && keyCode == android.view.KeyEvent
						.KEYCODE_DEL)) && item.isEnabled())
					{
						items.add(item);
					}
				}
			}
		}
Example #10
0
		public virtual bool onGenericMotionEvent(android.widget.TextView widget, android.text.Spannable
			 text, android.view.MotionEvent @event)
		{
			if ((@event.getSource() & android.view.InputDevice.SOURCE_CLASS_POINTER) != 0)
			{
				switch (@event.getAction())
				{
					case android.view.MotionEvent.ACTION_SCROLL:
					{
						float vscroll;
						float hscroll;
						if ((@event.getMetaState() & android.view.KeyEvent.META_SHIFT_ON) != 0)
						{
							vscroll = 0;
							hscroll = @event.getAxisValue(android.view.MotionEvent.AXIS_VSCROLL);
						}
						else
						{
							vscroll = [email protected](android.view.MotionEvent.AXIS_VSCROLL);
							hscroll = @event.getAxisValue(android.view.MotionEvent.AXIS_HSCROLL);
						}
						bool handled = false;
						if (hscroll < 0)
						{
							handled |= scrollLeft(widget, text, (int)System.Math.Ceiling(-hscroll));
						}
						else
						{
							if (hscroll > 0)
							{
								handled |= scrollRight(widget, text, (int)System.Math.Ceiling(hscroll));
							}
						}
						if (vscroll < 0)
						{
							handled |= scrollUp(widget, text, (int)System.Math.Ceiling(-vscroll));
						}
						else
						{
							if (vscroll > 0)
							{
								handled |= scrollDown(widget, text, (int)System.Math.Ceiling(vscroll));
							}
						}
						return handled;
					}
				}
			}
			return false;
		}
Example #11
0
		/// <summary>
		/// Gets the meta state used for movement using the modifiers tracked by the text
		/// buffer as well as those present in the key event.
		/// </summary>
		/// <remarks>
		/// Gets the meta state used for movement using the modifiers tracked by the text
		/// buffer as well as those present in the key event.
		/// The movement meta state excludes the state of locked modifiers or the SHIFT key
		/// since they are not used by movement actions (but they may be used for selection).
		/// </remarks>
		/// <param name="buffer">The text buffer.</param>
		/// <param name="event">The key event.</param>
		/// <returns>The keyboard meta states used for movement.</returns>
		protected internal virtual int getMovementMetaState(android.text.Spannable buffer
			, android.view.KeyEvent @event)
		{
			// We ignore locked modifiers and SHIFT.
			int metaState = (@event.getMetaState() | android.text.method.MetaKeyKeyListener.getMetaState
				(buffer)) & ~(android.text.method.MetaKeyKeyListener.META_ALT_LOCKED | android.text.method.MetaKeyKeyListener
				.META_SYM_LOCKED);
			return android.view.KeyEvent.normalizeMetaState(metaState) & ~android.view.KeyEvent
				.META_SHIFT_MASK;
		}