summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.xml36
-rw-r--r--core/java/android/text/method/BaseKeyListener.java67
-rw-r--r--core/java/android/text/method/BaseMovementMethod.java306
-rw-r--r--core/java/android/text/method/MovementMethod.java1
-rw-r--r--core/java/android/text/method/ScrollingMovementMethod.java155
-rw-r--r--core/java/android/widget/TextView.java16
-rw-r--r--core/jni/android_view_InputChannel.cpp18
7 files changed, 406 insertions, 193 deletions
diff --git a/api/current.xml b/api/current.xml
index 90b46ff7cec4..6adf8aa2c861 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -198789,6 +198789,23 @@
<parameter name="buffer" type="android.text.Spannable">
</parameter>
</method>
+<method name="onGenericMotionEvent"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="text" type="android.text.Spannable">
+</parameter>
+<parameter name="event" type="android.view.MotionEvent">
+</parameter>
+</method>
<method name="onKeyDown"
return="boolean"
abstract="false"
@@ -199862,6 +199879,23 @@
<parameter name="text" type="android.text.Spannable">
</parameter>
</method>
+<method name="onGenericMotionEvent"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="text" type="android.text.Spannable">
+</parameter>
+<parameter name="event" type="android.view.MotionEvent">
+</parameter>
+</method>
<method name="onKeyDown"
return="boolean"
abstract="true"
@@ -266599,7 +266633,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="t" type="T">
+<parameter name="arg0" type="T">
</parameter>
</method>
</interface>
diff --git a/core/java/android/text/method/BaseKeyListener.java b/core/java/android/text/method/BaseKeyListener.java
index 191c250aa6b6..7e29dc76e401 100644
--- a/core/java/android/text/method/BaseKeyListener.java
+++ b/core/java/android/text/method/BaseKeyListener.java
@@ -33,23 +33,6 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener
implements KeyListener {
/* package */ static final Object OLD_SEL_START = new NoCopySpan.Concrete();
- private static final int MODIFIER_NONE = 0;
- private static final int MODIFIER_ALT = 1;
- private static final int MODIFIER_INVALID = 2;
-
- private static int getModifier(Editable content, KeyEvent event) {
- if (event.hasModifiers(KeyEvent.META_ALT_ON)) {
- return MODIFIER_ALT;
- }
- if (!event.hasNoModifiers()) {
- return MODIFIER_INVALID;
- }
- if (getMetaState(content, META_ALT_ON) == 1) {
- return MODIFIER_ALT;
- }
- return MODIFIER_NONE;
- }
-
/**
* Performs the action that happens when you press the {@link KeyEvent#KEYCODE_DEL} key in
* a {@link TextView}. If there is a selection, deletes the selection; otherwise,
@@ -59,27 +42,7 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener
* @return true if anything was deleted; false otherwise.
*/
public boolean backspace(View view, Editable content, int keyCode, KeyEvent event) {
- int modifier = getModifier(content, event);
- if (modifier == MODIFIER_INVALID) {
- return false;
- }
-
- if (deleteSelection(view, content)) {
- return true;
- }
-
- if (modifier == MODIFIER_ALT && deleteLine(view, content)) {
- return true;
- }
-
- final int start = Selection.getSelectionEnd(content);
- final int end = TextUtils.getOffsetBefore(content, start);
- if (start != end) {
- content.delete(Math.min(start, end), Math.max(start, end));
- return true;
- }
-
- return false;
+ return backspaceOrForwardDelete(view, content, keyCode, event, false);
}
/**
@@ -91,26 +54,42 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener
* @return true if anything was deleted; false otherwise.
*/
public boolean forwardDelete(View view, Editable content, int keyCode, KeyEvent event) {
- int modifier = getModifier(content, event);
- if (modifier == MODIFIER_INVALID) {
+ return backspaceOrForwardDelete(view, content, keyCode, event, true);
+ }
+
+ private boolean backspaceOrForwardDelete(View view, Editable content, int keyCode,
+ KeyEvent event, boolean isForwardDelete) {
+ // Ensure the key event does not have modifiers except ALT or SHIFT.
+ if (!KeyEvent.metaStateHasNoModifiers(event.getMetaState()
+ & ~(KeyEvent.META_SHIFT_MASK | KeyEvent.META_ALT_MASK))) {
return false;
}
+ // If there is a current selection, delete it.
if (deleteSelection(view, content)) {
return true;
}
- if (modifier == MODIFIER_ALT && deleteLine(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.
final int start = Selection.getSelectionEnd(content);
- final int end = TextUtils.getOffsetAfter(content, start);
+ final int end;
+ if (isForwardDelete || event.isShiftPressed()
+ || getMetaState(content, META_SHIFT_ON) == 1) {
+ end = TextUtils.getOffsetAfter(content, start);
+ } else {
+ end = TextUtils.getOffsetBefore(content, start);
+ }
if (start != end) {
content.delete(Math.min(start, end), Math.max(start, end));
return true;
}
-
return false;
}
diff --git a/core/java/android/text/method/BaseMovementMethod.java b/core/java/android/text/method/BaseMovementMethod.java
index 2be18d674816..94c6ed08c1e1 100644
--- a/core/java/android/text/method/BaseMovementMethod.java
+++ b/core/java/android/text/method/BaseMovementMethod.java
@@ -18,6 +18,7 @@ package android.text.method;
import android.text.Layout;
import android.text.Spannable;
+import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.widget.TextView;
@@ -88,6 +89,39 @@ public class BaseMovementMethod implements MovementMethod {
return false;
}
+ @Override
+ public boolean onGenericMotionEvent(TextView widget, Spannable text, MotionEvent event) {
+ if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_SCROLL: {
+ final float vscroll;
+ final float hscroll;
+ if ((event.getMetaState() & KeyEvent.META_SHIFT_ON) != 0) {
+ vscroll = 0;
+ hscroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
+ } else {
+ vscroll = -event.getAxisValue(MotionEvent.AXIS_VSCROLL);
+ hscroll = event.getAxisValue(MotionEvent.AXIS_HSCROLL);
+ }
+
+ boolean handled = false;
+ if (hscroll < 0) {
+ handled |= scrollLeft(widget, text, (int)Math.ceil(-hscroll));
+ } else if (hscroll > 0) {
+ handled |= scrollRight(widget, text, (int)Math.ceil(hscroll));
+ }
+ if (vscroll < 0) {
+ handled |= scrollUp(widget, text, (int)Math.ceil(-vscroll));
+ } else if (vscroll > 0) {
+ handled |= scrollDown(widget, text, (int)Math.ceil(vscroll));
+ }
+ return handled;
+ }
+ }
+ }
+ return false;
+ }
+
/**
* Gets the meta state used for movement using the modifiers tracked by the text
* buffer as well as those present in the key event.
@@ -342,4 +376,276 @@ public class BaseMovementMethod implements MovementMethod {
protected boolean end(TextView widget, Spannable buffer) {
return false;
}
+
+ private int getTopLine(TextView widget) {
+ return widget.getLayout().getLineForVertical(widget.getScrollY());
+ }
+
+ private int getBottomLine(TextView widget) {
+ return widget.getLayout().getLineForVertical(widget.getScrollY() + getInnerHeight(widget));
+ }
+
+ private int getInnerWidth(TextView widget) {
+ return widget.getWidth() - widget.getTotalPaddingLeft() - widget.getTotalPaddingRight();
+ }
+
+ private int getInnerHeight(TextView widget) {
+ return widget.getHeight() - widget.getTotalPaddingTop() - widget.getTotalPaddingBottom();
+ }
+
+ private int getCharacterWidth(TextView widget) {
+ return (int) Math.ceil(widget.getPaint().getFontSpacing());
+ }
+
+ private int getScrollBoundsLeft(TextView widget) {
+ final Layout layout = widget.getLayout();
+ final int topLine = getTopLine(widget);
+ final int bottomLine = getBottomLine(widget);
+ if (topLine > bottomLine) {
+ return 0;
+ }
+ int left = Integer.MAX_VALUE;
+ for (int line = topLine; line <= bottomLine; line++) {
+ final int lineLeft = (int) Math.floor(layout.getLineLeft(line));
+ if (lineLeft < left) {
+ left = lineLeft;
+ }
+ }
+ return left;
+ }
+
+ private int getScrollBoundsRight(TextView widget) {
+ final Layout layout = widget.getLayout();
+ final int topLine = getTopLine(widget);
+ final int bottomLine = getBottomLine(widget);
+ if (topLine > bottomLine) {
+ return 0;
+ }
+ int right = Integer.MIN_VALUE;
+ for (int line = topLine; line <= bottomLine; line++) {
+ final int lineRight = (int) Math.ceil(layout.getLineRight(line));
+ if (lineRight > right) {
+ right = lineRight;
+ }
+ }
+ return right;
+ }
+
+ /**
+ * Performs a scroll left action.
+ * Scrolls left by the specified number of characters.
+ *
+ * @param widget The text view.
+ * @param buffer The text buffer.
+ * @param amount The number of characters to scroll by. Must be at least 1.
+ * @return True if the event was handled.
+ * @hide
+ */
+ protected boolean scrollLeft(TextView widget, Spannable buffer, int amount) {
+ final int minScrollX = getScrollBoundsLeft(widget);
+ int scrollX = widget.getScrollX();
+ if (scrollX > minScrollX) {
+ scrollX = Math.max(scrollX - getCharacterWidth(widget) * amount, minScrollX);
+ widget.scrollTo(scrollX, widget.getScrollY());
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Performs a scroll right action.
+ * Scrolls right by the specified number of characters.
+ *
+ * @param widget The text view.
+ * @param buffer The text buffer.
+ * @param amount The number of characters to scroll by. Must be at least 1.
+ * @return True if the event was handled.
+ * @hide
+ */
+ protected boolean scrollRight(TextView widget, Spannable buffer, int amount) {
+ final int maxScrollX = getScrollBoundsRight(widget) - getInnerWidth(widget);
+ int scrollX = widget.getScrollX();
+ if (scrollX < maxScrollX) {
+ scrollX = Math.min(scrollX + getCharacterWidth(widget) * amount, maxScrollX);
+ widget.scrollTo(scrollX, widget.getScrollY());
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Performs a scroll up action.
+ * Scrolls up by the specified number of lines.
+ *
+ * @param widget The text view.
+ * @param buffer The text buffer.
+ * @param amount The number of lines to scroll by. Must be at least 1.
+ * @return True if the event was handled.
+ * @hide
+ */
+ protected boolean scrollUp(TextView widget, Spannable buffer, int amount) {
+ final Layout layout = widget.getLayout();
+ final int top = widget.getScrollY();
+ int topLine = layout.getLineForVertical(top);
+ if (layout.getLineTop(topLine) == top) {
+ // If the top line is partially visible, bring it all the way
+ // into view; otherwise, bring the previous line into view.
+ topLine -= 1;
+ }
+ if (topLine >= 0) {
+ topLine = Math.max(topLine - amount + 1, 0);
+ Touch.scrollTo(widget, layout, widget.getScrollX(), layout.getLineTop(topLine));
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Performs a scroll down action.
+ * Scrolls down by the specified number of lines.
+ *
+ * @param widget The text view.
+ * @param buffer The text buffer.
+ * @param amount The number of lines to scroll by. Must be at least 1.
+ * @return True if the event was handled.
+ * @hide
+ */
+ protected boolean scrollDown(TextView widget, Spannable buffer, int amount) {
+ final Layout layout = widget.getLayout();
+ final int innerHeight = getInnerHeight(widget);
+ final int bottom = widget.getScrollY() + innerHeight;
+ int bottomLine = layout.getLineForVertical(bottom);
+ if (layout.getLineTop(bottomLine + 1) < bottom + 1) {
+ // Less than a pixel of this line is out of view,
+ // so we must have tried to make it entirely in view
+ // and now want the next line to be in view instead.
+ bottomLine += 1;
+ }
+ final int limit = layout.getLineCount() - 1;
+ if (bottomLine <= limit) {
+ bottomLine = Math.min(bottomLine + amount - 1, limit);
+ Touch.scrollTo(widget, layout, widget.getScrollX(),
+ layout.getLineTop(bottomLine + 1) - innerHeight);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Performs a scroll page up action.
+ * Scrolls up by one page.
+ *
+ * @param widget The text view.
+ * @param buffer The text buffer.
+ * @return True if the event was handled.
+ * @hide
+ */
+ protected boolean scrollPageUp(TextView widget, Spannable buffer) {
+ final Layout layout = widget.getLayout();
+ final int top = widget.getScrollY() - getInnerHeight(widget);
+ int topLine = layout.getLineForVertical(top);
+ if (topLine >= 0) {
+ Touch.scrollTo(widget, layout, widget.getScrollX(), layout.getLineTop(topLine));
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Performs a scroll page up action.
+ * Scrolls down by one page.
+ *
+ * @param widget The text view.
+ * @param buffer The text buffer.
+ * @return True if the event was handled.
+ * @hide
+ */
+ protected boolean scrollPageDown(TextView widget, Spannable buffer) {
+ final Layout layout = widget.getLayout();
+ final int innerHeight = getInnerHeight(widget);
+ final int bottom = widget.getScrollY() + innerHeight + innerHeight;
+ int bottomLine = layout.getLineForVertical(bottom);
+ if (bottomLine <= layout.getLineCount() - 1) {
+ Touch.scrollTo(widget, layout, widget.getScrollX(),
+ layout.getLineTop(bottomLine + 1) - innerHeight);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Performs a scroll to top action.
+ * Scrolls to the top of the document.
+ *
+ * @param widget The text view.
+ * @param buffer The text buffer.
+ * @return True if the event was handled.
+ * @hide
+ */
+ protected boolean scrollTop(TextView widget, Spannable buffer) {
+ final Layout layout = widget.getLayout();
+ if (getTopLine(widget) >= 0) {
+ Touch.scrollTo(widget, layout, widget.getScrollX(), layout.getLineTop(0));
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Performs a scroll to bottom action.
+ * Scrolls to the bottom of the document.
+ *
+ * @param widget The text view.
+ * @param buffer The text buffer.
+ * @return True if the event was handled.
+ * @hide
+ */
+ protected boolean scrollBottom(TextView widget, Spannable buffer) {
+ final Layout layout = widget.getLayout();
+ final int lineCount = layout.getLineCount();
+ if (getBottomLine(widget) <= lineCount - 1) {
+ Touch.scrollTo(widget, layout, widget.getScrollX(),
+ layout.getLineTop(lineCount) - getInnerHeight(widget));
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Performs a scroll to line start action.
+ * Scrolls to the start of the line.
+ *
+ * @param widget The text view.
+ * @param buffer The text buffer.
+ * @return True if the event was handled.
+ * @hide
+ */
+ protected boolean scrollLineStart(TextView widget, Spannable buffer) {
+ final int minScrollX = getScrollBoundsLeft(widget);
+ int scrollX = widget.getScrollX();
+ if (scrollX > minScrollX) {
+ widget.scrollTo(minScrollX, widget.getScrollY());
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Performs a scroll to line end action.
+ * Scrolls to the end of the line.
+ *
+ * @param widget The text view.
+ * @param buffer The text buffer.
+ * @return True if the event was handled.
+ * @hide
+ */
+ protected boolean scrollLineEnd(TextView widget, Spannable buffer) {
+ final int maxScrollX = getScrollBoundsRight(widget) - getInnerWidth(widget);
+ int scrollX = widget.getScrollX();
+ if (scrollX < maxScrollX) {
+ widget.scrollTo(maxScrollX, widget.getScrollY());
+ return true;
+ }
+ return false;
+ }
}
diff --git a/core/java/android/text/method/MovementMethod.java b/core/java/android/text/method/MovementMethod.java
index 91676766d2c4..01979fdb5cd4 100644
--- a/core/java/android/text/method/MovementMethod.java
+++ b/core/java/android/text/method/MovementMethod.java
@@ -47,6 +47,7 @@ public interface MovementMethod {
public void onTakeFocus(TextView widget, Spannable text, int direction);
public boolean onTrackballEvent(TextView widget, Spannable text, MotionEvent event);
public boolean onTouchEvent(TextView widget, Spannable text, MotionEvent event);
+ public boolean onGenericMotionEvent(TextView widget, Spannable text, MotionEvent event);
/**
* Returns true if this movement method allows arbitrary selection
diff --git a/core/java/android/text/method/ScrollingMovementMethod.java b/core/java/android/text/method/ScrollingMovementMethod.java
index 194ecc128eae..b9f5d5f447e3 100644
--- a/core/java/android/text/method/ScrollingMovementMethod.java
+++ b/core/java/android/text/method/ScrollingMovementMethod.java
@@ -25,189 +25,54 @@ import android.view.View;
* A movement method that interprets movement keys by scrolling the text buffer.
*/
public class ScrollingMovementMethod extends BaseMovementMethod implements MovementMethod {
- private int getTopLine(TextView widget) {
- return widget.getLayout().getLineForVertical(widget.getScrollY());
- }
-
- private int getBottomLine(TextView widget) {
- return widget.getLayout().getLineForVertical(widget.getScrollY() + getInnerHeight(widget));
- }
-
- private int getInnerWidth(TextView widget) {
- return widget.getWidth() - widget.getTotalPaddingLeft() - widget.getTotalPaddingRight();
- }
-
- private int getInnerHeight(TextView widget) {
- return widget.getHeight() - widget.getTotalPaddingTop() - widget.getTotalPaddingBottom();
- }
-
- private int getCharacterWidth(TextView widget) {
- return (int) Math.ceil(widget.getPaint().getFontSpacing());
- }
-
- private int getScrollBoundsLeft(TextView widget) {
- final Layout layout = widget.getLayout();
- final int topLine = getTopLine(widget);
- final int bottomLine = getBottomLine(widget);
- if (topLine > bottomLine) {
- return 0;
- }
- int left = Integer.MAX_VALUE;
- for (int line = topLine; line <= bottomLine; line++) {
- final int lineLeft = (int) Math.floor(layout.getLineLeft(line));
- if (lineLeft < left) {
- left = lineLeft;
- }
- }
- return left;
- }
-
- private int getScrollBoundsRight(TextView widget) {
- final Layout layout = widget.getLayout();
- final int topLine = getTopLine(widget);
- final int bottomLine = getBottomLine(widget);
- if (topLine > bottomLine) {
- return 0;
- }
- int right = Integer.MIN_VALUE;
- for (int line = topLine; line <= bottomLine; line++) {
- final int lineRight = (int) Math.ceil(layout.getLineRight(line));
- if (lineRight > right) {
- right = lineRight;
- }
- }
- return right;
- }
-
@Override
protected boolean left(TextView widget, Spannable buffer) {
- final int minScrollX = getScrollBoundsLeft(widget);
- int scrollX = widget.getScrollX();
- if (scrollX > minScrollX) {
- scrollX = Math.max(scrollX - getCharacterWidth(widget), minScrollX);
- widget.scrollTo(scrollX, widget.getScrollY());
- return true;
- }
- return false;
+ return scrollLeft(widget, buffer, 1);
}
@Override
protected boolean right(TextView widget, Spannable buffer) {
- final int maxScrollX = getScrollBoundsRight(widget) - getInnerWidth(widget);
- int scrollX = widget.getScrollX();
- if (scrollX < maxScrollX) {
- scrollX = Math.min(scrollX + getCharacterWidth(widget), maxScrollX);
- widget.scrollTo(scrollX, widget.getScrollY());
- return true;
- }
- return false;
+ return scrollRight(widget, buffer, 1);
}
@Override
protected boolean up(TextView widget, Spannable buffer) {
- final Layout layout = widget.getLayout();
- final int top = widget.getScrollY();
- int topLine = layout.getLineForVertical(top);
- if (layout.getLineTop(topLine) == top) {
- // If the top line is partially visible, bring it all the way
- // into view; otherwise, bring the previous line into view.
- topLine -= 1;
- }
- if (topLine >= 0) {
- Touch.scrollTo(widget, layout, widget.getScrollX(), layout.getLineTop(topLine));
- return true;
- }
- return false;
+ return scrollUp(widget, buffer, 1);
}
@Override
protected boolean down(TextView widget, Spannable buffer) {
- final Layout layout = widget.getLayout();
- final int innerHeight = getInnerHeight(widget);
- final int bottom = widget.getScrollY() + innerHeight;
- int bottomLine = layout.getLineForVertical(bottom);
- if (layout.getLineTop(bottomLine + 1) < bottom + 1) {
- // Less than a pixel of this line is out of view,
- // so we must have tried to make it entirely in view
- // and now want the next line to be in view instead.
- bottomLine += 1;
- }
- if (bottomLine <= layout.getLineCount() - 1) {
- Touch.scrollTo(widget, layout, widget.getScrollX(),
- layout.getLineTop(bottomLine + 1) - innerHeight);
- return true;
- }
- return false;
+ return scrollDown(widget, buffer, 1);
}
@Override
protected boolean pageUp(TextView widget, Spannable buffer) {
- final Layout layout = widget.getLayout();
- final int top = widget.getScrollY() - getInnerHeight(widget);
- int topLine = layout.getLineForVertical(top);
- if (topLine >= 0) {
- Touch.scrollTo(widget, layout, widget.getScrollX(), layout.getLineTop(topLine));
- return true;
- }
- return false;
+ return scrollPageUp(widget, buffer);
}
@Override
protected boolean pageDown(TextView widget, Spannable buffer) {
- final Layout layout = widget.getLayout();
- final int innerHeight = getInnerHeight(widget);
- final int bottom = widget.getScrollY() + innerHeight + innerHeight;
- int bottomLine = layout.getLineForVertical(bottom);
- if (bottomLine <= layout.getLineCount() - 1) {
- Touch.scrollTo(widget, layout, widget.getScrollX(),
- layout.getLineTop(bottomLine + 1) - innerHeight);
- return true;
- }
- return false;
+ return scrollPageDown(widget, buffer);
}
@Override
protected boolean top(TextView widget, Spannable buffer) {
- final Layout layout = widget.getLayout();
- if (getTopLine(widget) >= 0) {
- Touch.scrollTo(widget, layout, widget.getScrollX(), layout.getLineTop(0));
- return true;
- }
- return false;
+ return scrollTop(widget, buffer);
}
@Override
protected boolean bottom(TextView widget, Spannable buffer) {
- final Layout layout = widget.getLayout();
- final int lineCount = layout.getLineCount();
- if (getBottomLine(widget) <= lineCount - 1) {
- Touch.scrollTo(widget, layout, widget.getScrollX(),
- layout.getLineTop(lineCount) - getInnerHeight(widget));
- return true;
- }
- return false;
+ return scrollBottom(widget, buffer);
}
@Override
protected boolean lineStart(TextView widget, Spannable buffer) {
- final int minScrollX = getScrollBoundsLeft(widget);
- int scrollX = widget.getScrollX();
- if (scrollX > minScrollX) {
- widget.scrollTo(minScrollX, widget.getScrollY());
- return true;
- }
- return false;
+ return scrollLineStart(widget, buffer);
}
@Override
protected boolean lineEnd(TextView widget, Spannable buffer) {
- final int maxScrollX = getScrollBoundsRight(widget) - getInnerWidth(widget);
- int scrollX = widget.getScrollX();
- if (scrollX < maxScrollX) {
- widget.scrollTo(maxScrollX, widget.getScrollY());
- return true;
- }
- return false;
+ return scrollLineEnd(widget, buffer);
}
@Override
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 11e05e5d9c23..33d1225e5181 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -7389,6 +7389,22 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return superResult;
}
+ @Override
+ public boolean onGenericMotionEvent(MotionEvent event) {
+ if (mMovement != null && mText instanceof Spannable && mLayout != null) {
+ try {
+ if (mMovement.onGenericMotionEvent(this, (Spannable) mText, event)) {
+ return true;
+ }
+ } catch (AbstractMethodError ex) {
+ // onGenericMotionEvent was added to the MovementMethod interface in API 12.
+ // Ignore its absence in case third party applications implemented the
+ // interface directly.
+ }
+ }
+ return super.onGenericMotionEvent(event);
+ }
+
private void prepareCursorControllers() {
boolean windowSupportsHandles = false;
diff --git a/core/jni/android_view_InputChannel.cpp b/core/jni/android_view_InputChannel.cpp
index 4a4393ae2dd1..0c2801cab7ba 100644
--- a/core/jni/android_view_InputChannel.cpp
+++ b/core/jni/android_view_InputChannel.cpp
@@ -186,9 +186,21 @@ static void android_view_InputChannel_nativeReadFromParcel(JNIEnv* env, jobject
bool isInitialized = parcel->readInt32();
if (isInitialized) {
String8 name = parcel->readString8();
- int32_t ashmemFd = dup(parcel->readFileDescriptor());
- int32_t receivePipeFd = dup(parcel->readFileDescriptor());
- int32_t sendPipeFd = dup(parcel->readFileDescriptor());
+ int32_t parcelAshmemFd = parcel->readFileDescriptor();
+ int32_t ashmemFd = dup(parcelAshmemFd);
+ if (ashmemFd < 0) {
+ LOGE("Error %d dup ashmem fd %d.", errno, parcelAshmemFd);
+ }
+ int32_t parcelReceivePipeFd = parcel->readFileDescriptor();
+ int32_t receivePipeFd = dup(parcelReceivePipeFd);
+ if (receivePipeFd < 0) {
+ LOGE("Error %d dup receive pipe fd %d.", errno, parcelReceivePipeFd);
+ }
+ int32_t parcelSendPipeFd = parcel->readFileDescriptor();
+ int32_t sendPipeFd = dup(parcelSendPipeFd);
+ if (sendPipeFd < 0) {
+ LOGE("Error %d dup send pipe fd %d.", errno, parcelSendPipeFd);
+ }
if (ashmemFd < 0 || receivePipeFd < 0 || sendPipeFd < 0) {
if (ashmemFd >= 0) ::close(ashmemFd);
if (receivePipeFd >= 0) ::close(receivePipeFd);