summaryrefslogtreecommitdiff
path: root/data/patches/gnuzilla-bug-1034167-2.patch
diff options
context:
space:
mode:
Diffstat (limited to 'data/patches/gnuzilla-bug-1034167-2.patch')
-rw-r--r--data/patches/gnuzilla-bug-1034167-2.patch1205
1 files changed, 1205 insertions, 0 deletions
diff --git a/data/patches/gnuzilla-bug-1034167-2.patch b/data/patches/gnuzilla-bug-1034167-2.patch
new file mode 100644
index 0000000..3df67a0
--- /dev/null
+++ b/data/patches/gnuzilla-bug-1034167-2.patch
@@ -0,0 +1,1205 @@
+# HG changeset patch
+# User Lucas Rocha <lucasr@mozilla.com>
+
+Bug 1034167 - Part 1: Update TwoWayView from upstream (r=mfinkle)
+
+diff --git a/mobile/android/base/resources/values/attrs.xml b/mobile/android/base/resources/values/attrs.xml
+index 0c27b87..7140292 100644
+--- a/mobile/android/base/resources/values/attrs.xml
++++ b/mobile/android/base/resources/values/attrs.xml
+@@ -117,91 +117,20 @@
+
+ <declare-styleable name="LightweightTheme">
+ <attr name="state_light" format="boolean"/>
+ <attr name="state_dark" format="boolean"/>
+ <attr name="autoUpdateTheme" format="boolean"/>
+ </declare-styleable>
+
+ <declare-styleable name="TwoWayView">
+- <!-- Imported from View -->
+- <attr name="android:id"/>
+- <attr name="android:tag"/>
+- <attr name="android:scrollX"/>
+- <attr name="android:scrollY"/>
+- <attr name="android:background"/>
+- <attr name="android:padding"/>
+- <attr name="android:paddingLeft"/>
+- <attr name="android:paddingTop"/>
+- <attr name="android:paddingRight"/>
+- <attr name="android:paddingBottom"/>
+- <attr name="android:paddingStart"/>
+- <attr name="android:paddingEnd"/>
+- <attr name="android:focusable"/>
+- <attr name="android:focusableInTouchMode"/>
+- <attr name="android:visibility"/>
+- <attr name="android:fitsSystemWindows"/>
+- <attr name="android:scrollbars"/>
+- <attr name="android:scrollbarStyle"/>
+- <attr name="android:isScrollContainer"/>
+- <attr name="android:fadeScrollbars"/>
+- <attr name="android:scrollbarFadeDuration"/>
+- <attr name="android:scrollbarDefaultDelayBeforeFade"/>
+- <attr name="android:scrollbarSize"/>
+- <attr name="android:scrollbarThumbHorizontal"/>
+- <attr name="android:scrollbarThumbVertical"/>
+- <attr name="android:scrollbarTrackHorizontal"/>
+- <attr name="android:scrollbarTrackVertical"/>
+- <attr name="android:scrollbarAlwaysDrawHorizontalTrack"/>
+- <attr name="android:scrollbarAlwaysDrawVerticalTrack"/>
+- <attr name="android:fadingEdge"/>
+- <attr name="android:requiresFadingEdge"/>
+- <attr name="android:fadingEdgeLength"/>
+- <attr name="android:nextFocusLeft"/>
+- <attr name="android:nextFocusRight"/>
+- <attr name="android:nextFocusUp"/>
+- <attr name="android:nextFocusDown"/>
+- <attr name="android:nextFocusForward"/>
+- <attr name="android:clickable"/>
+- <attr name="android:longClickable"/>
+- <attr name="android:saveEnabled"/>
+- <attr name="android:filterTouchesWhenObscured"/>
+- <attr name="android:drawingCacheQuality"/>
+- <attr name="android:keepScreenOn"/>
+- <attr name="android:duplicateParentState"/>
+- <attr name="android:minHeight"/>
+- <attr name="android:minWidth"/>
+- <attr name="android:soundEffectsEnabled"/>
+- <attr name="android:hapticFeedbackEnabled"/>
+- <attr name="android:contentDescription"/>
+- <attr name="android:onClick"/>
+- <attr name="android:overScrollMode"/>
+- <attr name="android:alpha"/>
+- <attr name="android:translationX"/>
+- <attr name="android:translationY"/>
+- <attr name="android:transformPivotX"/>
+- <attr name="android:transformPivotY"/>
+- <attr name="android:rotation"/>
+- <attr name="android:rotationX"/>
+- <attr name="android:rotationY"/>
+- <attr name="android:scaleX"/>
+- <attr name="android:scaleY"/>
+- <attr name="android:verticalScrollbarPosition"/>
+- <attr name="android:layerType"/>
+- <attr name="android:layoutDirection"/>
+- <attr name="android:textDirection"/>
+- <attr name="android:textAlignment"/>
+-
+- <!-- Imported from Android -->
+ <attr name="android:orientation"/>
+-
+- <!-- Imported from AbsListView -->
+ <attr name="android:choiceMode"/>
+- <attr name="android:drawSelectorOnTop"/>
+ <attr name="android:listSelector"/>
++ <attr name="android:drawSelectorOnTop"/>
+ </declare-styleable>
+
+ <declare-styleable name="HomeListView">
+ <!-- Draws a divider on top of the list, if true. Defaults to false. -->
+ <attr name="topDivider" format="boolean"/>
+ </declare-styleable>
+
+ <declare-styleable name="HomePagerTabStrip">
+--- a/mobile/android/base/widget/TwoWayView.java 2015-01-06 05:07:55.000000000 +0000
++++ b/mobile/android/base/widget/TwoWayView.java 2015-02-23 19:46:01.737065730 +0000
+@@ -23,6 +23,9 @@
+
+ import org.mozilla.gecko.R;
+
++import java.util.ArrayList;
++import java.util.List;
++
+ import android.annotation.TargetApi;
+ import android.content.Context;
+ import android.content.res.TypedArray;
+@@ -67,8 +70,7 @@
+ import android.widget.ListAdapter;
+ import android.widget.Scroller;
+
+-import java.util.ArrayList;
+-import java.util.List;
++import static android.os.Build.VERSION_CODES.HONEYCOMB;
+
+ /*
+ * Implementation Notes:
+@@ -136,8 +138,8 @@
+
+ public static enum Orientation {
+ HORIZONTAL,
+- VERTICAL;
+- };
++ VERTICAL
++ }
+
+ private ListAdapter mAdapter;
+
+@@ -266,7 +268,7 @@
+ * Callback method to be invoked while the list view or grid view is being scrolled. If the
+ * view is being scrolled, this method will be called before the next frame of the scroll is
+ * rendered. In particular, it will be called before any calls to
+- * {@link Adapter#getView(int, View, ViewGroup)}.
++ * {@link android.widget.Adapter#getView(int, View, ViewGroup)}.
+ *
+ * @param view The view whose scroll state is being reported
+ *
+@@ -388,7 +390,6 @@
+ ViewCompat.setOverScrollMode(this, ViewCompat.OVER_SCROLL_IF_CONTENT_SCROLLS);
+
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TwoWayView, defStyle, 0);
+- initializeScrollbars(a);
+
+ mDrawSelectorOnTop = a.getBoolean(
+ R.styleable.TwoWayView_android_drawSelectorOnTop, false);
+@@ -409,19 +410,16 @@
+ }
+
+ a.recycle();
+-
+- updateScrollbarsDirection();
+ }
+
+ public void setOrientation(Orientation orientation) {
+- final boolean isVertical = (orientation.compareTo(Orientation.VERTICAL) == 0);
++ final boolean isVertical = (orientation == Orientation.VERTICAL);
+ if (mIsVertical == isVertical) {
+ return;
+ }
+
+ mIsVertical = isVertical;
+
+- updateScrollbarsDirection();
+ resetState();
+ mRecycler.clear();
+
+@@ -441,6 +439,7 @@
+ requestLayout();
+ }
+
++ @SuppressWarnings("unused")
+ public int getItemMargin() {
+ return mItemMargin;
+ }
+@@ -451,6 +450,7 @@
+ *
+ * @param itemsCanFocus true if items can get focus, false otherwise
+ */
++ @SuppressWarnings("unused")
+ public void setItemsCanFocus(boolean itemsCanFocus) {
+ mItemsCanFocus = itemsCanFocus;
+ if (!itemsCanFocus) {
+@@ -462,6 +462,7 @@
+ * @return Whether the views created by the ListAdapter can contain focusable
+ * items.
+ */
++ @SuppressWarnings("unused")
+ public boolean getItemsCanFocus() {
+ return mItemsCanFocus;
+ }
+@@ -481,7 +482,7 @@
+ * the recycler for later reuse. This listener can be used to free resources
+ * associated to the View.
+ *
+- * @param listener The recycler listener to be notified of views set aside
++ * @param l The recycler listener to be notified of views set aside
+ * in the recycler.
+ *
+ * @see TwoWayView.RecycleBin
+@@ -495,11 +496,12 @@
+ * Controls whether the selection highlight drawable should be drawn on top of the item or
+ * behind it.
+ *
+- * @param onTop If true, the selector will be drawn on the item it is highlighting. The default
+- * is false.
++ * @param drawSelectorOnTop If true, the selector will be drawn on the item it is highlighting.
++ * The default is false.
+ *
+ * @attr ref android.R.styleable#AbsListView_drawSelectorOnTop
+ */
++ @SuppressWarnings("unused")
+ public void setDrawSelectorOnTop(boolean drawSelectorOnTop) {
+ mDrawSelectorOnTop = drawSelectorOnTop;
+ }
+@@ -511,6 +513,7 @@
+ *
+ * @attr ref android.R.styleable#AbsListView_listSelector
+ */
++ @SuppressWarnings("unused")
+ public void setSelector(int resID) {
+ setSelector(getResources().getDrawable(resID));
+ }
+@@ -542,6 +545,7 @@
+ *
+ * @return the drawable used to display the selector
+ */
++ @SuppressWarnings("unused")
+ public Drawable getSelector() {
+ return mSelector;
+ }
+@@ -564,7 +568,7 @@
+
+ /**
+ * Returns the number of items currently selected. This will only be valid
+- * if the choice mode is not {@link #CHOICE_MODE_NONE} (default).
++ * if the choice mode is not {@link ChoiceMode#NONE} (default).
+ *
+ * <p>To determine the specific items that are currently selected, use one of
+ * the <code>getChecked*</code> methods.
+@@ -575,23 +579,24 @@
+ * @see #getCheckedItemPositions()
+ * @see #getCheckedItemIds()
+ */
++ @SuppressWarnings("unused")
+ public int getCheckedItemCount() {
+ return mCheckedItemCount;
+ }
+
+ /**
+ * Returns the checked state of the specified position. The result is only
+- * valid if the choice mode has been set to {@link #CHOICE_MODE_SINGLE}
+- * or {@link #CHOICE_MODE_MULTIPLE}.
++ * valid if the choice mode has been set to {@link ChoiceMode#SINGLE}
++ * or {@link ChoiceMode#MULTIPLE}.
+ *
+ * @param position The item whose checked state to return
+ * @return The item's checked state or <code>false</code> if choice mode
+ * is invalid
+ *
+- * @see #setChoiceMode(int)
++ * @see #setChoiceMode(ChoiceMode)
+ */
+ public boolean isItemChecked(int position) {
+- if (mChoiceMode.compareTo(ChoiceMode.NONE) == 0 && mCheckStates != null) {
++ if (mChoiceMode == ChoiceMode.NONE && mCheckStates != null) {
+ return mCheckStates.get(position);
+ }
+
+@@ -600,16 +605,15 @@
+
+ /**
+ * Returns the currently checked item. The result is only valid if the choice
+- * mode has been set to {@link #CHOICE_MODE_SINGLE}.
++ * mode has been set to {@link ChoiceMode#SINGLE}.
+ *
+ * @return The position of the currently checked item or
+ * {@link #INVALID_POSITION} if nothing is selected
+ *
+- * @see #setChoiceMode(int)
++ * @see #setChoiceMode(ChoiceMode)
+ */
+ public int getCheckedItemPosition() {
+- if (mChoiceMode.compareTo(ChoiceMode.SINGLE) == 0 &&
+- mCheckStates != null && mCheckStates.size() == 1) {
++ if (mChoiceMode == ChoiceMode.SINGLE && mCheckStates != null && mCheckStates.size() == 1) {
+ return mCheckStates.keyAt(0);
+ }
+
+@@ -618,15 +622,15 @@
+
+ /**
+ * Returns the set of checked items in the list. The result is only valid if
+- * the choice mode has not been set to {@link #CHOICE_MODE_NONE}.
++ * the choice mode has not been set to {@link ChoiceMode#NONE}.
+ *
+ * @return A SparseBooleanArray which will return true for each call to
+ * get(int position) where position is a position in the list,
+ * or <code>null</code> if the choice mode is set to
+- * {@link #CHOICE_MODE_NONE}.
++ * {@link ChoiceMode#NONE}.
+ */
+ public SparseBooleanArray getCheckedItemPositions() {
+- if (mChoiceMode.compareTo(ChoiceMode.NONE) != 0) {
++ if (mChoiceMode != ChoiceMode.NONE) {
+ return mCheckStates;
+ }
+
+@@ -635,15 +639,14 @@
+
+ /**
+ * Returns the set of checked items ids. The result is only valid if the
+- * choice mode has not been set to {@link #CHOICE_MODE_NONE} and the adapter
++ * choice mode has not been set to {@link ChoiceMode#NONE} and the adapter
+ * has stable IDs. ({@link ListAdapter#hasStableIds()} == {@code true})
+ *
+ * @return A new array which contains the id of each checked item in the
+ * list.
+ */
+ public long[] getCheckedItemIds() {
+- if (mChoiceMode.compareTo(ChoiceMode.NONE) == 0 ||
+- mCheckedIdStates == null || mAdapter == null) {
++ if (mChoiceMode == ChoiceMode.NONE || mCheckedIdStates == null || mAdapter == null) {
+ return new long[0];
+ }
+
+@@ -660,18 +663,19 @@
+
+ /**
+ * Sets the checked state of the specified position. The is only valid if
+- * the choice mode has been set to {@link #CHOICE_MODE_SINGLE} or
+- * {@link #CHOICE_MODE_MULTIPLE}.
++ * the choice mode has been set to {@link ChoiceMode#SINGLE} or
++ * {@link ChoiceMode#MULTIPLE}.
+ *
+ * @param position The item whose checked state is to be checked
+ * @param value The new checked state for the item
+ */
++ @SuppressWarnings("unused")
+ public void setItemChecked(int position, boolean value) {
+- if (mChoiceMode.compareTo(ChoiceMode.NONE) == 0) {
++ if (mChoiceMode == ChoiceMode.NONE) {
+ return;
+ }
+
+- if (mChoiceMode.compareTo(ChoiceMode.MULTIPLE) == 0) {
++ if (mChoiceMode == ChoiceMode.MULTIPLE) {
+ boolean oldValue = mCheckStates.get(position);
+ mCheckStates.put(position, value);
+
+@@ -729,6 +733,7 @@
+ /**
+ * Clear any choices previously set
+ */
++ @SuppressWarnings("unused")
+ public void clearChoices() {
+ if (mCheckStates != null) {
+ mCheckStates.clear();
+@@ -742,27 +747,28 @@
+ }
+
+ /**
+- * @see #setChoiceMode(int)
++ * @see #setChoiceMode(ChoiceMode)
+ *
+ * @return The current choice mode
+ */
++ @SuppressWarnings("unused")
+ public ChoiceMode getChoiceMode() {
+ return mChoiceMode;
+ }
+
+ /**
+ * Defines the choice behavior for the List. By default, Lists do not have any choice behavior
+- * ({@link #CHOICE_MODE_NONE}). By setting the choiceMode to {@link #CHOICE_MODE_SINGLE}, the
++ * ({@link ChoiceMode#NONE}). By setting the choiceMode to {@link ChoiceMode#SINGLE}, the
+ * List allows up to one item to be in a chosen state. By setting the choiceMode to
+- * {@link #CHOICE_MODE_MULTIPLE}, the list allows any number of items to be chosen.
++ * {@link ChoiceMode#MULTIPLE}, the list allows any number of items to be chosen.
+ *
+- * @param choiceMode One of {@link #CHOICE_MODE_NONE}, {@link #CHOICE_MODE_SINGLE}, or
+- * {@link #CHOICE_MODE_MULTIPLE}
++ * @param choiceMode One of {@link ChoiceMode#NONE}, {@link ChoiceMode#SINGLE}, or
++ * {@link ChoiceMode#MULTIPLE}
+ */
+ public void setChoiceMode(ChoiceMode choiceMode) {
+ mChoiceMode = choiceMode;
+
+- if (mChoiceMode.compareTo(ChoiceMode.NONE) != 0) {
++ if (mChoiceMode != ChoiceMode.NONE) {
+ if (mCheckStates == null) {
+ mCheckStates = new SparseBooleanArray();
+ }
+@@ -813,8 +819,7 @@
+ mHasStableIds = adapter.hasStableIds();
+ mAreAllItemsSelectable = adapter.areAllItemsEnabled();
+
+- if (mChoiceMode.compareTo(ChoiceMode.NONE) != 0 && mHasStableIds &&
+- mCheckedIdStates == null) {
++ if (mChoiceMode != ChoiceMode.NONE && mHasStableIds && mCheckedIdStates == null) {
+ mCheckedIdStates = new LongSparseArray<Integer>();
+ }
+
+@@ -1268,7 +1273,7 @@
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+- if (!mIsAttached) {
++ if (!mIsAttached || mAdapter == null) {
+ return false;
+ }
+
+@@ -1354,7 +1359,7 @@
+ return isClickable() || isLongClickable();
+ }
+
+- if (!mIsAttached) {
++ if (!mIsAttached || mAdapter == null) {
+ return false;
+ }
+
+@@ -1477,7 +1482,7 @@
+ final float x = ev.getX();
+ final float y = ev.getY();
+
+- boolean inList = false;
++ final boolean inList;
+ if (mIsVertical) {
+ inList = x > getPaddingLeft() && x < getWidth() - getPaddingRight();
+ } else {
+@@ -1731,7 +1736,7 @@
+ }
+
+ // TODO: Use some form of smooth scroll instead
+- trackMotionScroll(viewportSize);
++ scrollListItemsBy(viewportSize);
+ return true;
+ }
+ return false;
+@@ -1746,7 +1751,7 @@
+ }
+
+ // TODO: Use some form of smooth scroll instead
+- trackMotionScroll(-viewportSize);
++ scrollListItemsBy(-viewportSize);
+ return true;
+ }
+ return false;
+@@ -2077,7 +2082,7 @@
+ newFocus = FocusFinder.getInstance().findNextFocus(this, oldFocus, direction);
+ } else {
+ if (direction == View.FOCUS_DOWN || direction == View.FOCUS_RIGHT) {
+- final int start = (mIsVertical ? getPaddingTop() : getPaddingLeft());
++ final int start = getStartEdge();
+
+ final int selectedStart;
+ if (selectedView != null) {
+@@ -2088,12 +2093,11 @@
+
+ searchPoint = Math.max(selectedStart, start);
+ } else {
+- final int end = (mIsVertical ? getHeight() - getPaddingBottom() :
+- getWidth() - getPaddingRight());
++ final int end = getEndEdge();
+
+ final int selectedEnd;
+ if (selectedView != null) {
+- selectedEnd = (mIsVertical ? selectedView.getBottom() : selectedView.getRight());
++ selectedEnd = getChildEndEdge(selectedView);
+ } else {
+ selectedEnd = end;
+ }
+@@ -2242,7 +2246,7 @@
+ }
+
+ if (amountToScroll > 0) {
+- trackMotionScroll(direction == View.FOCUS_UP || direction == View.FOCUS_LEFT ?
++ scrollListItemsBy(direction == View.FOCUS_UP || direction == View.FOCUS_LEFT ?
+ amountToScroll : -amountToScroll);
+ needToRedraw = true;
+ }
+@@ -2304,8 +2308,7 @@
+ final int numChildren = getChildCount();
+
+ if (direction == View.FOCUS_DOWN || direction == View.FOCUS_RIGHT) {
+- final int end = (mIsVertical ? getHeight() - getPaddingBottom() :
+- getWidth() - getPaddingRight());
++ final int end = getEndEdge();
+
+ int indexToMakeVisible = numChildren - 1;
+ if (nextSelectedPosition != INVALID_POSITION) {
+@@ -2320,10 +2323,8 @@
+ goalEnd -= getArrowScrollPreviewLength();
+ }
+
+- final int viewToMakeVisibleStart =
+- (mIsVertical ? viewToMakeVisible.getTop() : viewToMakeVisible.getLeft());
+- final int viewToMakeVisibleEnd =
+- (mIsVertical ? viewToMakeVisible.getBottom() : viewToMakeVisible.getRight());
++ final int viewToMakeVisibleStart = getChildStartEdge(viewToMakeVisible);
++ final int viewToMakeVisibleEnd = getChildEndEdge(viewToMakeVisible);
+
+ if (viewToMakeVisibleEnd <= goalEnd) {
+ // Target item is fully visible
+@@ -2339,8 +2340,7 @@
+ int amountToScroll = (viewToMakeVisibleEnd - goalEnd);
+
+ if (mFirstPosition + numChildren == mItemCount) {
+- final View lastChild = getChildAt(numChildren - 1);
+- final int lastChildEnd = (mIsVertical ? lastChild.getBottom() : lastChild.getRight());
++ final int lastChildEnd = getChildEndEdge(getChildAt(numChildren - 1));
+
+ // Last is last in list -> Make sure we don't scroll past it
+ final int max = lastChildEnd - end;
+@@ -2349,7 +2349,7 @@
+
+ return Math.min(amountToScroll, getMaxScrollAmount());
+ } else {
+- final int start = (mIsVertical ? getPaddingTop() : getPaddingLeft());
++ final int start = getStartEdge();
+
+ int indexToMakeVisible = 0;
+ if (nextSelectedPosition != INVALID_POSITION) {
+@@ -2364,10 +2364,8 @@
+ goalStart += getArrowScrollPreviewLength();
+ }
+
+- final int viewToMakeVisibleStart =
+- (mIsVertical ? viewToMakeVisible.getTop() : viewToMakeVisible.getLeft());
+- final int viewToMakeVisibleEnd =
+- (mIsVertical ? viewToMakeVisible.getBottom() : viewToMakeVisible.getRight());
++ final int viewToMakeVisibleStart = getChildStartEdge(viewToMakeVisible);
++ final int viewToMakeVisibleEnd = getChildEndEdge(viewToMakeVisible);
+
+ if (viewToMakeVisibleStart >= goalStart) {
+ // Item is fully visible
+@@ -2383,8 +2381,7 @@
+ int amountToScroll = (goalStart - viewToMakeVisibleStart);
+
+ if (mFirstPosition == 0) {
+- final View firstChild = getChildAt(0);
+- final int firstChildStart = (mIsVertical ? firstChild.getTop() : firstChild.getLeft());
++ final int firstChildStart = getChildStartEdge(getChildAt(0));
+
+ // First is first in list -> make sure we don't scroll past it
+ final int max = start - firstChildStart;
+@@ -2416,7 +2413,7 @@
+ offsetDescendantRectToMyCoords(newFocus, mTempRect);
+
+ if (direction == View.FOCUS_UP || direction == View.FOCUS_LEFT) {
+- final int start = (mIsVertical ? getPaddingTop() : getPaddingLeft());
++ final int start = getStartEdge();
+ final int newFocusStart = (mIsVertical ? mTempRect.top : mTempRect.left);
+
+ if (newFocusStart < start) {
+@@ -2426,8 +2423,7 @@
+ }
+ }
+ } else {
+- final int end = (mIsVertical ? getHeight() - getPaddingBottom() :
+- getWidth() - getPaddingRight());
++ final int end = getEndEdge();
+ final int newFocusEnd = (mIsVertical ? mTempRect.bottom : mTempRect.right);
+
+ if (newFocusEnd > end) {
+@@ -2452,9 +2448,8 @@
+ descendant.getDrawingRect(mTempRect);
+ offsetDescendantRectToMyCoords(descendant, mTempRect);
+
+- final int start = (mIsVertical ? getPaddingTop() : getPaddingLeft());
+- final int end = (mIsVertical ? getHeight() - getPaddingBottom() :
+- getWidth() - getPaddingRight());
++ final int start = getStartEdge();
++ final int end = getEndEdge();
+
+ final int viewStart = (mIsVertical ? mTempRect.top : mTempRect.left);
+ final int viewEnd = (mIsVertical ? mTempRect.bottom : mTempRect.right);
+@@ -2741,7 +2736,7 @@
+ motionViewPrevStart = (mIsVertical ? motionView.getTop() : motionView.getLeft());
+ }
+
+- boolean atEdge = trackMotionScroll(delta);
++ boolean atEdge = scrollListItemsBy(delta);
+
+ motionView = this.getChildAt(motionIndex);
+ if (motionView != null) {
+@@ -2821,7 +2816,7 @@
+ ViewCompat.postInvalidateOnAnimation(this);
+ }
+
+- trackMotionScroll(delta);
++ scrollListItemsBy(delta);
+ mTouchMode = TOUCH_MODE_DRAGGING;
+
+ // We did not scroll the full amount. Treat this essentially like the
+@@ -2901,10 +2896,8 @@
+ }
+
+ for (int i = 0; i < childCount; i++) {
+- View v = getChildAt(i);
+-
+- if ((mIsVertical && motionPos <= v.getBottom()) ||
+- (!mIsVertical && motionPos <= v.getRight())) {
++ final View v = getChildAt(i);
++ if (motionPos <= getChildEndEdge(v)) {
+ return mFirstPosition + i;
+ }
+ }
+@@ -2935,6 +2928,26 @@
+ return vc.getScaledOverscrollDistance();
+ }
+
++ private int getStartEdge() {
++ return (mIsVertical ? getPaddingTop() : getPaddingLeft());
++ }
++
++ private int getEndEdge() {
++ if (mIsVertical) {
++ return (getHeight() - getPaddingBottom());
++ } else {
++ return (getWidth() - getPaddingRight());
++ }
++ }
++
++ private int getChildStartEdge(View child) {
++ return (mIsVertical ? child.getTop() : child.getLeft());
++ }
++
++ private int getChildEndEdge(View child) {
++ return (mIsVertical ? child.getBottom() : child.getRight());
++ }
++
+ private boolean contentFits() {
+ final int childCount = getChildCount();
+ if (childCount == 0) {
+@@ -2948,18 +2961,8 @@
+ View first = getChildAt(0);
+ View last = getChildAt(childCount - 1);
+
+- if (mIsVertical) {
+- return first.getTop() >= getPaddingTop() &&
+- last.getBottom() <= getHeight() - getPaddingBottom();
+- } else {
+- return first.getLeft() >= getPaddingLeft() &&
+- last.getRight() <= getWidth() - getPaddingRight();
+- }
+- }
+-
+- private void updateScrollbarsDirection() {
+- setHorizontalScrollBarEnabled(!mIsVertical);
+- setVerticalScrollBarEnabled(mIsVertical);
++ return (getChildStartEdge(first) >= getStartEdge() &&
++ getChildEndEdge(last) <= getEndEdge());
+ }
+
+ private void triggerCheckForTap() {
+@@ -2997,17 +3000,14 @@
+ removeCallbacks(mPendingCheckForLongPress);
+ }
+
+- boolean trackMotionScroll(int incrementalDelta) {
++ private boolean scrollListItemsBy(int incrementalDelta) {
+ final int childCount = getChildCount();
+ if (childCount == 0) {
+ return true;
+ }
+
+- final View first = getChildAt(0);
+- final int firstStart = (mIsVertical ? first.getTop() : first.getLeft());
+-
+- final View last = getChildAt(childCount - 1);
+- final int lastEnd = (mIsVertical ? last.getBottom() : last.getRight());
++ final int firstStart = getChildStartEdge(getChildAt(0));
++ final int lastEnd = getChildEndEdge(getChildAt(childCount - 1));
+
+ final int paddingTop = getPaddingTop();
+ final int paddingBottom = getPaddingBottom();
+@@ -3017,8 +3017,7 @@
+ final int paddingStart = (mIsVertical ? paddingTop : paddingLeft);
+
+ final int spaceBefore = paddingStart - firstStart;
+- final int end = (mIsVertical ? getHeight() - paddingBottom :
+- getWidth() - paddingRight);
++ final int end = getEndEdge();
+ final int spaceAfter = lastEnd - end;
+
+ final int size;
+@@ -3059,7 +3058,7 @@
+
+ for (int i = 0; i < childCount; i++) {
+ final View child = getChildAt(i);
+- final int childEnd = (mIsVertical ? child.getBottom() : child.getRight());
++ final int childEnd = getChildEndEdge(child);
+
+ if (childEnd >= childrenStart) {
+ break;
+@@ -3073,7 +3072,7 @@
+
+ for (int i = childCount - 1; i >= 0; i--) {
+ final View child = getChildAt(i);
+- final int childStart = (mIsVertical ? child.getTop() : child.getLeft());
++ final int childStart = getChildStartEdge(child);
+
+ if (childStart <= childrenEnd) {
+ break;
+@@ -3140,11 +3139,7 @@
+
+ @TargetApi(5)
+ private boolean awakenScrollbarsInternal() {
+- if (Build.VERSION.SDK_INT >= 5) {
+- return super.awakenScrollBars();
+- } else {
+- return false;
+- }
++ return (Build.VERSION.SDK_INT >= 5) && super.awakenScrollBars();
+ }
+
+ @Override
+@@ -3163,7 +3158,7 @@
+ final int diff = (int) (pos - mLastTouchPos);
+ mLastTouchPos = pos;
+
+- final boolean stopped = trackMotionScroll(diff);
++ final boolean stopped = scrollListItemsBy(diff);
+
+ if (!stopped && !mScroller.isFinished()) {
+ ViewCompat.postInvalidateOnAnimation(this);
+@@ -3210,7 +3205,7 @@
+ }
+
+ final int restoreCount = canvas.save();
+- final int height = getHeight() - getPaddingTop() - getPaddingBottom();
++ final int height = getHeight();
+
+ canvas.translate(0, height);
+ canvas.rotate(270);
+@@ -3226,8 +3221,8 @@
+ }
+
+ final int restoreCount = canvas.save();
+- final int width = getWidth() - getPaddingLeft() - getPaddingRight();
+- final int height = getHeight() - getPaddingTop() - getPaddingBottom();
++ final int width = getWidth();
++ final int height = getHeight();
+
+ if (mIsVertical) {
+ canvas.translate(-width, height);
+@@ -3683,6 +3678,10 @@
+ }
+ }
+
++ public void scrollBy(int offset) {
++ scrollListItemsBy(offset);
++ }
++
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ // Dispatch in the normal way
+@@ -3814,9 +3813,8 @@
+ return;
+ }
+
+- final int start = (mIsVertical ? getPaddingTop() : getPaddingLeft());
+- final int end =
+- (mIsVertical ? getHeight() - getPaddingBottom() : getWidth() - getPaddingRight());
++ final int start = getStartEdge();
++ final int end = getEndEdge();
+
+ int childCount = getChildCount();
+ int index = 0;
+@@ -4084,8 +4082,8 @@
+ int end) {
+ final int selectedPosition = mSelectedPosition;
+
+- final int oldSelectedStart = (mIsVertical ? oldSelected.getTop() : oldSelected.getLeft());
+- final int oldSelectedEnd = (mIsVertical ? oldSelected.getBottom() : oldSelected.getRight());
++ final int oldSelectedStart = getChildStartEdge(oldSelected);
++ final int oldSelectedEnd = getChildEndEdge(oldSelected);
+
+ View selected = null;
+
+@@ -4118,8 +4116,8 @@
+ // Now put the new selection (B) below that
+ selected = makeAndAddView(selectedPosition, oldSelectedEnd + itemMargin, true, true);
+
+- final int selectedStart = (mIsVertical ? selected.getTop() : selected.getLeft());
+- final int selectedEnd = (mIsVertical ? selected.getBottom() : selected.getRight());
++ final int selectedStart = getChildStartEdge(selected);
++ final int selectedEnd = getChildEndEdge(selected);
+
+ // Some of the newly selected item extends below the bottom of the list
+ if (selectedEnd > end) {
+@@ -4178,8 +4176,8 @@
+ selected = makeAndAddView(selectedPosition, oldSelectedStart, false, true);
+ }
+
+- final int selectedStart = (mIsVertical ? selected.getTop() : selected.getLeft());
+- final int selectedEnd = (mIsVertical ? selected.getBottom() : selected.getRight());
++ final int selectedStart = getChildStartEdge(selected);
++ final int selectedEnd = getChildEndEdge(selected);
+
+ // Some of the newly selected item extends above the top of the list
+ if (selectedStart < start) {
+@@ -4210,8 +4208,8 @@
+
+ selected = makeAndAddView(selectedPosition, oldSelectedStart, true, true);
+
+- final int selectedStart = (mIsVertical ? selected.getTop() : selected.getLeft());
+- final int selectedEnd = (mIsVertical ? selected.getBottom() : selected.getRight());
++ final int selectedStart = getChildStartEdge(selected);
++ final int selectedEnd = getChildEndEdge(selected);
+
+ // We're staying still...
+ if (oldSelectedStart < start) {
+@@ -4272,7 +4270,7 @@
+ }
+
+ private void handleDataChanged() {
+- if (mChoiceMode.compareTo(ChoiceMode.NONE) != 0 && mAdapter != null && mAdapter.hasStableIds()) {
++ if (mChoiceMode != ChoiceMode.NONE && mAdapter != null && mAdapter.hasStableIds()) {
+ confirmCheckedPositionsById();
+ }
+
+@@ -4406,9 +4404,8 @@
+ int selectedStart = 0;
+ int selectedPosition;
+
+- final int start = (mIsVertical ? getPaddingTop() : getPaddingLeft());
+- final int end =
+- (mIsVertical ? getHeight() - getPaddingBottom() : getWidth() - getPaddingRight());
++ final int start = getStartEdge();
++ final int end = getEndEdge();
+
+ final int firstPosition = mFirstPosition;
+ final int toPosition = mResurrectToPosition;
+@@ -4445,8 +4442,8 @@
+
+ for (int i = childCount - 1; i >= 0; i--) {
+ final View child = getChildAt(i);
+- final int childStart = (mIsVertical ? child.getTop() : child.getLeft());
+- final int childEnd = (mIsVertical ? child.getBottom() : child.getRight());
++ final int childStart = getChildStartEdge(child);
++ final int childEnd = getChildEndEdge(child);
+
+ if (i == childCount - 1) {
+ selectedStart = childStart;
+@@ -4718,7 +4715,7 @@
+ recycleBin.addScrapView(child, -1);
+ }
+
+- returnedWidth += child.getMeasuredHeight();
++ returnedWidth += child.getMeasuredWidth();
+
+ if (returnedWidth >= maxWidth) {
+ // We went over, figure out which width to return. If returnedWidth > maxWidth,
+@@ -4810,11 +4807,10 @@
+ child.setPressed(isPressed);
+ }
+
+- if (mChoiceMode.compareTo(ChoiceMode.NONE) != 0 && mCheckStates != null) {
++ if (mChoiceMode != ChoiceMode.NONE && mCheckStates != null) {
+ if (child instanceof Checkable) {
+ ((Checkable) child).setChecked(mCheckStates.get(position));
+- } else if (getContext().getApplicationInfo().targetSdkVersion
+- >= Build.VERSION_CODES.HONEYCOMB) {
++ } else if (Build.VERSION.SDK_INT >= HONEYCOMB) {
+ child.setActivated(mCheckStates.get(position));
+ }
+ }
+@@ -4847,26 +4843,17 @@
+
+ if (down) {
+ final int paddingStart = (mIsVertical ? getPaddingTop() : getPaddingLeft());
+-
+- final int lastEnd;
+- if (mIsVertical) {
+- lastEnd = getChildAt(childCount - 1).getBottom();
+- } else {
+- lastEnd = getChildAt(childCount - 1).getRight();
+- }
++ final int lastEnd = getChildEndEdge(getChildAt(childCount - 1));
+
+ final int offset = (childCount > 0 ? lastEnd + mItemMargin : paddingStart);
+ fillAfter(mFirstPosition + childCount, offset);
+ correctTooHigh(getChildCount());
+ } else {
+- final int end;
++ final int end = getEndEdge();
+ final int firstStart;
+-
+ if (mIsVertical) {
+- end = getHeight() - getPaddingBottom();
+ firstStart = getChildAt(0).getTop();
+ } else {
+- end = getWidth() - getPaddingRight();
+ firstStart = getChildAt(0).getLeft();
+ }
+
+@@ -4879,7 +4866,7 @@
+ private View fillBefore(int pos, int nextOffset) {
+ View selectedView = null;
+
+- final int start = (mIsVertical ? getPaddingTop() : getPaddingLeft());
++ final int start = getStartEdge();
+
+ while (nextOffset > start && pos >= 0) {
+ boolean isSelected = (pos == mSelectedPosition);
+@@ -4906,19 +4893,13 @@
+ private View fillAfter(int pos, int nextOffset) {
+ View selectedView = null;
+
+- final int end =
+- (mIsVertical ? getHeight() - getPaddingBottom() : getWidth() - getPaddingRight());
++ final int end = getEndEdge();
+
+ while (nextOffset < end && pos < mItemCount) {
+ boolean selected = (pos == mSelectedPosition);
+
+ View child = makeAndAddView(pos, nextOffset, true, selected);
+-
+- if (mIsVertical) {
+- nextOffset = child.getBottom() + mItemMargin;
+- } else {
+- nextOffset = child.getRight() + mItemMargin;
+- }
++ nextOffset = getChildEndEdge(child) + mItemMargin;
+
+ if (selected) {
+ selectedView = child;
+@@ -4937,25 +4918,13 @@
+ // Possibly changed again in fillBefore if we add rows above this one.
+ mFirstPosition = position;
+
+- final int itemMargin = mItemMargin;
+-
+- final int offsetBefore;
+- if (mIsVertical) {
+- offsetBefore = temp.getTop() - itemMargin;
+- } else {
+- offsetBefore = temp.getLeft() - itemMargin;
+- }
++ final int offsetBefore = getChildStartEdge(temp) + mItemMargin;
+ final View before = fillBefore(position - 1, offsetBefore);
+
+ // This will correct for the top of the first view not touching the top of the list
+ adjustViewsStartOrEnd();
+
+- final int offsetAfter;
+- if (mIsVertical) {
+- offsetAfter = temp.getBottom() + itemMargin;
+- } else {
+- offsetAfter = temp.getRight() + itemMargin;
+- }
++ final int offsetAfter = getChildEndEdge(temp) + mItemMargin;
+ final View after = fillAfter(position + 1, offsetAfter);
+
+ final int childCount = getChildCount();
+@@ -5009,37 +4978,22 @@
+ }
+
+ private void fillBeforeAndAfter(View selected, int position) {
+- final int itemMargin = mItemMargin;
+-
+- final int offsetBefore;
+- if (mIsVertical) {
+- offsetBefore = selected.getTop() - itemMargin;
+- } else {
+- offsetBefore = selected.getLeft() - itemMargin;
+- }
+-
++ final int offsetBefore = getChildStartEdge(selected) + mItemMargin;
+ fillBefore(position - 1, offsetBefore);
+
+ adjustViewsStartOrEnd();
+
+- final int offsetAfter;
+- if (mIsVertical) {
+- offsetAfter = selected.getBottom() + itemMargin;
+- } else {
+- offsetAfter = selected.getRight() + itemMargin;
+- }
+-
++ final int offsetAfter = getChildEndEdge(selected) + mItemMargin;
+ fillAfter(position + 1, offsetAfter);
+ }
+
+ private View fillFromSelection(int selectedTop, int start, int end) {
+ final int selectedPosition = mSelectedPosition;
+- View selected;
+
+- selected = makeAndAddView(selectedPosition, selectedTop, true, true);
++ View selected = makeAndAddView(selectedPosition, selectedTop, true, true);
+
+- final int selectedStart = (mIsVertical ? selected.getTop() : selected.getLeft());
+- final int selectedEnd = (mIsVertical ? selected.getBottom() : selected.getRight());
++ final int selectedStart = getChildStartEdge(selected);
++ final int selectedEnd = getChildEndEdge(selected);
+
+ // Some of the newly selected item extends below the bottom of the list
+ if (selectedEnd > end) {
+@@ -5085,28 +5039,19 @@
+ return;
+ }
+
+- // Get the last child ...
+- final View lastChild = getChildAt(childCount - 1);
+-
+- // ... and its end edge
+- final int lastEnd;
+- if (mIsVertical) {
+- lastEnd = lastChild.getBottom();
+- } else {
+- lastEnd = lastChild.getRight();
+- }
++ // Get the last child end edge
++ final int lastEnd = getChildEndEdge(getChildAt(childCount - 1));
+
+ // This is bottom of our drawable area
+- final int start = (mIsVertical ? getPaddingTop() : getPaddingLeft());
+- final int end =
+- (mIsVertical ? getHeight() - getPaddingBottom() : getWidth() - getPaddingRight());
++ final int start = getStartEdge();
++ final int end = getEndEdge();
+
+ // This is how far the end edge of the last view is from the end of the
+ // drawable area
+ int endOffset = end - lastEnd;
+
+ View firstChild = getChildAt(0);
+- int firstStart = (mIsVertical ? firstChild.getTop() : firstChild.getLeft());
++ int firstStart = getChildStartEdge(firstChild);
+
+ // Make sure we are 1) Too high, and 2) Either there are more rows above the
+ // first row or the first row is scrolled off the top of the drawable area
+@@ -5120,7 +5065,7 @@
+ offsetChildren(endOffset);
+
+ if (mFirstPosition > 0) {
+- firstStart = (mIsVertical ? firstChild.getTop() : firstChild.getLeft());
++ firstStart = getChildStartEdge(firstChild);
+
+ // Fill the gap that was opened above mFirstPosition with more rows, if
+ // possible
+@@ -5142,21 +5087,15 @@
+ final View first = getChildAt(0);
+ final int firstStart = (mIsVertical ? first.getTop() : first.getLeft());
+
+- final int start = (mIsVertical ? getPaddingTop() : getPaddingLeft());
+-
+- final int end;
+- if (mIsVertical) {
+- end = getHeight() - getPaddingBottom();
+- } else {
+- end = getWidth() - getPaddingRight();
+- }
++ final int start = getStartEdge();
++ final int end = getEndEdge();
+
+ // This is how far the start edge of the first view is from the start of the
+ // drawable area
+ int startOffset = firstStart - start;
+
+ View last = getChildAt(childCount - 1);
+- int lastEnd = (mIsVertical ? last.getBottom() : last.getRight());
++ int lastEnd = getChildEndEdge(last);
+
+ int lastPosition = mFirstPosition + childCount - 1;
+
+@@ -5174,7 +5113,7 @@
+ offsetChildren(-startOffset);
+
+ if (lastPosition < mItemCount - 1) {
+- lastEnd = (mIsVertical ? last.getBottom() : last.getRight());
++ lastEnd = getChildEndEdge(last);
+
+ // Fill the gap that was opened below the last position with more rows, if
+ // possible
+@@ -5366,6 +5305,8 @@
+ }
+
+ void resetState() {
++ mScroller.forceFinished(true);
++
+ removeAllViewsInLayout();
+
+ mSelectedStart = 0;
+@@ -5419,7 +5360,7 @@
+ mSyncPosition = mFirstPosition;
+
+ if (child != null) {
+- mSpecificStart = child.getTop();
++ mSpecificStart = (mIsVertical ? child.getTop() : child.getLeft());
+ }
+
+ mSyncMode = SYNC_FIRST_POSITION;
+@@ -5435,16 +5376,13 @@
+ final int firstPos = mFirstPosition;
+ final int count = getChildCount();
+
+- final boolean useActivated = getContext().getApplicationInfo().targetSdkVersion
+- >= Build.VERSION_CODES.HONEYCOMB;
+-
+ for (int i = 0; i < count; i++) {
+ final View child = getChildAt(i);
+ final int position = firstPos + i;
+
+ if (child instanceof Checkable) {
+ ((Checkable) child).setChecked(mCheckStates.get(position));
+- } else if (useActivated) {
++ } else if (Build.VERSION.SDK_INT >= HONEYCOMB) {
+ child.setActivated(mCheckStates.get(position));
+ }
+ }
+@@ -5454,7 +5392,7 @@
+ public boolean performItemClick(View view, int position, long id) {
+ boolean checkedStateChanged = false;
+
+- if (mChoiceMode.compareTo(ChoiceMode.MULTIPLE) == 0) {
++ if (mChoiceMode == ChoiceMode.MULTIPLE) {
+ boolean checked = !mCheckStates.get(position, false);
+ mCheckStates.put(position, checked);
+
+@@ -5473,7 +5411,7 @@
+ }
+
+ checkedStateChanged = true;
+- } else if (mChoiceMode.compareTo(ChoiceMode.SINGLE) == 0) {
++ } else if (mChoiceMode == ChoiceMode.SINGLE) {
+ boolean checked = !mCheckStates.get(position, false);
+ if (checked) {
+ mCheckStates.clear();
+@@ -5699,14 +5637,14 @@
+ super(width, height);
+
+ if (this.width == MATCH_PARENT) {
+- Log.w(LOGTAG, "Constructing LayoutParams with width FILL_PARENT " +
++ Log.w(LOGTAG, "Constructing LayoutParams with width MATCH_PARENT " +
+ "does not make much sense as the view might change orientation. " +
+ "Falling back to WRAP_CONTENT");
+ this.width = WRAP_CONTENT;
+ }
+
+ if (this.height == MATCH_PARENT) {
+- Log.w(LOGTAG, "Constructing LayoutParams with height FILL_PARENT " +
++ Log.w(LOGTAG, "Constructing LayoutParams with height MATCH_PARENT " +
+ "does not make much sense as the view might change orientation. " +
+ "Falling back to WRAP_CONTENT");
+ this.height = WRAP_CONTENT;
+@@ -5735,7 +5673,7 @@
+ super(other);
+
+ if (this.width == MATCH_PARENT) {
+- Log.w(LOGTAG, "Constructing LayoutParams with height MATCH_PARENT - " +
++ Log.w(LOGTAG, "Constructing LayoutParams with width MATCH_PARENT - " +
+ "does not make much sense as the view might change orientation. " +
+ "Falling back to WRAP_CONTENT");
+ this.width = WRAP_CONTENT;
+@@ -5786,11 +5724,8 @@
+ } else {
+ final int typeCount = mViewTypeCount;
+ for (int i = 0; i < typeCount; i++) {
+- final ArrayList<View> scrap = mScrapViews[i];
+- final int scrapCount = scrap.size();
+-
+- for (int j = 0; j < scrapCount; j++) {
+- scrap.get(j).forceLayout();
++ for (View scrap : mScrapViews[i]) {
++ scrap.forceLayout();
+ }
+ }
+ }
+@@ -6120,7 +6055,7 @@
+ // Force one here to make sure that the state of the list matches
+ // the state of the adapter.
+ if (mDataChanged) {
+- onLayout(false, getLeft(), getTop(), getRight(), getBottom());
++ layout(getLeft(), getTop(), getRight(), getBottom());
+ }
+ } else {
+ if (mEmptyView != null) {
+@@ -6525,16 +6460,10 @@
+ return false;
+
+ case AccessibilityNodeInfoCompat.ACTION_CLICK:
+- if (isClickable()) {
+- return performItemClick(host, position, id);
+- }
+- return false;
++ return isClickable() && performItemClick(host, position, id);
+
+ case AccessibilityNodeInfoCompat.ACTION_LONG_CLICK:
+- if (isLongClickable()) {
+- return performLongPress(host, position, id);
+- }
+- return false;
++ return isLongClickable() && performLongPress(host, position, id);
+ }
+
+ return false;