Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2474d33 authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Android (Google) Code Review
Browse files

Merge "Implement better handling of text in assist." into mnc-dev

parents b2f9c284 6f0fdc41
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -5822,6 +5822,8 @@ package android.app.assist {
    method public java.lang.CharSequence getText();
    method public java.lang.CharSequence getText();
    method public int getTextBackgroundColor();
    method public int getTextBackgroundColor();
    method public int getTextColor();
    method public int getTextColor();
    method public int[] getTextLineBaselines();
    method public int[] getTextLineCharOffsets();
    method public int getTextSelectionEnd();
    method public int getTextSelectionEnd();
    method public int getTextSelectionStart();
    method public int getTextSelectionStart();
    method public float getTextSize();
    method public float getTextSize();
@@ -36953,6 +36955,7 @@ package android.view {
    method public abstract void setSelected(boolean);
    method public abstract void setSelected(boolean);
    method public abstract void setText(java.lang.CharSequence);
    method public abstract void setText(java.lang.CharSequence);
    method public abstract void setText(java.lang.CharSequence, int, int);
    method public abstract void setText(java.lang.CharSequence, int, int);
    method public abstract void setTextLines(int[], int[]);
    method public abstract void setTextStyle(float, int, int, int);
    method public abstract void setTextStyle(float, int, int, int);
    method public abstract void setTransformation(android.graphics.Matrix);
    method public abstract void setTransformation(android.graphics.Matrix);
    method public abstract void setVisibility(int);
    method public abstract void setVisibility(int);
+3 −0
Original line number Original line Diff line number Diff line
@@ -5954,6 +5954,8 @@ package android.app.assist {
    method public java.lang.CharSequence getText();
    method public java.lang.CharSequence getText();
    method public int getTextBackgroundColor();
    method public int getTextBackgroundColor();
    method public int getTextColor();
    method public int getTextColor();
    method public int[] getTextLineBaselines();
    method public int[] getTextLineCharOffsets();
    method public int getTextSelectionEnd();
    method public int getTextSelectionEnd();
    method public int getTextSelectionStart();
    method public int getTextSelectionStart();
    method public float getTextSize();
    method public float getTextSize();
@@ -39243,6 +39245,7 @@ package android.view {
    method public abstract void setSelected(boolean);
    method public abstract void setSelected(boolean);
    method public abstract void setText(java.lang.CharSequence);
    method public abstract void setText(java.lang.CharSequence);
    method public abstract void setText(java.lang.CharSequence, int, int);
    method public abstract void setText(java.lang.CharSequence, int, int);
    method public abstract void setTextLines(int[], int[]);
    method public abstract void setTextStyle(float, int, int, int);
    method public abstract void setTextStyle(float, int, int, int);
    method public abstract void setTransformation(android.graphics.Matrix);
    method public abstract void setTransformation(android.graphics.Matrix);
    method public abstract void setVisibility(int);
    method public abstract void setVisibility(int);
+68 −21
Original line number Original line Diff line number Diff line
@@ -61,39 +61,55 @@ public class AssistStructure implements Parcelable {


    final static class ViewNodeText {
    final static class ViewNodeText {
        CharSequence mText;
        CharSequence mText;
        int mTextSelectionStart;
        int mTextSelectionEnd;
        int mTextColor;
        int mTextBackgroundColor;
        float mTextSize;
        float mTextSize;
        int mTextStyle;
        int mTextStyle;
        int mTextColor = ViewNode.TEXT_COLOR_UNDEFINED;
        int mTextBackgroundColor = ViewNode.TEXT_COLOR_UNDEFINED;
        int mTextSelectionStart;
        int mTextSelectionEnd;
        int[] mLineCharOffsets;
        int[] mLineBaselines;
        String mHint;
        String mHint;


        ViewNodeText() {
        ViewNodeText() {
        }
        }


        ViewNodeText(Parcel in) {
        boolean isSimple() {
            return mTextBackgroundColor == ViewNode.TEXT_COLOR_UNDEFINED
                    && mTextSelectionStart == 0 && mTextSelectionEnd == 0
                    && mLineCharOffsets == null && mLineBaselines == null && mHint == null;
        }

        ViewNodeText(Parcel in, boolean simple) {
            mText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
            mText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
            mTextSelectionStart = in.readInt();
            mTextSelectionEnd = in.readInt();
            mTextColor = in.readInt();
            mTextBackgroundColor = in.readInt();
            mTextSize = in.readFloat();
            mTextSize = in.readFloat();
            mTextStyle = in.readInt();
            mTextStyle = in.readInt();
            mTextColor = in.readInt();
            if (!simple) {
                mTextBackgroundColor = in.readInt();
                mTextSelectionStart = in.readInt();
                mTextSelectionEnd = in.readInt();
                mLineCharOffsets = in.createIntArray();
                mLineBaselines = in.createIntArray();
                mHint = in.readString();
                mHint = in.readString();
            }
            }
        }


        void writeToParcel(Parcel out) {
        void writeToParcel(Parcel out, boolean simple) {
            TextUtils.writeToParcel(mText, out, 0);
            TextUtils.writeToParcel(mText, out, 0);
            out.writeInt(mTextSelectionStart);
            out.writeInt(mTextSelectionEnd);
            out.writeInt(mTextColor);
            out.writeInt(mTextBackgroundColor);
            out.writeFloat(mTextSize);
            out.writeFloat(mTextSize);
            out.writeInt(mTextStyle);
            out.writeInt(mTextStyle);
            out.writeInt(mTextColor);
            if (!simple) {
                out.writeInt(mTextBackgroundColor);
                out.writeInt(mTextSelectionStart);
                out.writeInt(mTextSelectionEnd);
                out.writeIntArray(mLineCharOffsets);
                out.writeIntArray(mLineBaselines);
                out.writeString(mHint);
                out.writeString(mHint);
            }
            }
        }
        }
    }


    /**
    /**
     * Describes a window in the assist data.
     * Describes a window in the assist data.
@@ -252,9 +268,10 @@ public class AssistStructure implements Parcelable {
        static final int FLAGS_HAS_LARGE_COORDS = 0x04000000;
        static final int FLAGS_HAS_LARGE_COORDS = 0x04000000;
        static final int FLAGS_HAS_CONTENT_DESCRIPTION = 0x02000000;
        static final int FLAGS_HAS_CONTENT_DESCRIPTION = 0x02000000;
        static final int FLAGS_HAS_TEXT = 0x01000000;
        static final int FLAGS_HAS_TEXT = 0x01000000;
        static final int FLAGS_HAS_EXTRAS = 0x00800000;
        static final int FLAGS_HAS_COMPLEX_TEXT = 0x00800000;
        static final int FLAGS_HAS_ID = 0x00400000;
        static final int FLAGS_HAS_EXTRAS = 0x00400000;
        static final int FLAGS_HAS_CHILDREN = 0x00200000;
        static final int FLAGS_HAS_ID = 0x00200000;
        static final int FLAGS_HAS_CHILDREN = 0x00100000;
        static final int FLAGS_ALL_CONTROL = 0xfff00000;
        static final int FLAGS_ALL_CONTROL = 0xfff00000;


        int mFlags;
        int mFlags;
@@ -316,7 +333,7 @@ public class AssistStructure implements Parcelable {
                mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
                mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
            }
            }
            if ((flags&FLAGS_HAS_TEXT) != 0) {
            if ((flags&FLAGS_HAS_TEXT) != 0) {
                mText = new ViewNodeText(in);
                mText = new ViewNodeText(in, (flags&FLAGS_HAS_COMPLEX_TEXT) == 0);
            }
            }
            if ((flags&FLAGS_HAS_EXTRAS) != 0) {
            if ((flags&FLAGS_HAS_EXTRAS) != 0) {
                mExtras = in.readBundle();
                mExtras = in.readBundle();
@@ -356,6 +373,9 @@ public class AssistStructure implements Parcelable {
            }
            }
            if (mText != null) {
            if (mText != null) {
                flags |= FLAGS_HAS_TEXT;
                flags |= FLAGS_HAS_TEXT;
                if (!mText.isSimple()) {
                    flags |= FLAGS_HAS_COMPLEX_TEXT;
                }
            }
            }
            if (mExtras != null) {
            if (mExtras != null) {
                flags |= FLAGS_HAS_EXTRAS;
                flags |= FLAGS_HAS_EXTRAS;
@@ -403,7 +423,7 @@ public class AssistStructure implements Parcelable {
                TextUtils.writeToParcel(mContentDescription, out, 0);
                TextUtils.writeToParcel(mContentDescription, out, 0);
            }
            }
            if ((flags&FLAGS_HAS_TEXT) != 0) {
            if ((flags&FLAGS_HAS_TEXT) != 0) {
                mText.writeToParcel(out);
                mText.writeToParcel(out, (flags&FLAGS_HAS_COMPLEX_TEXT) == 0);
            }
            }
            if ((flags&FLAGS_HAS_EXTRAS) != 0) {
            if ((flags&FLAGS_HAS_EXTRAS) != 0) {
                out.writeBundle(mExtras);
                out.writeBundle(mExtras);
@@ -702,6 +722,26 @@ public class AssistStructure implements Parcelable {
            return mText != null ? mText.mTextStyle : 0;
            return mText != null ? mText.mTextStyle : 0;
        }
        }


        /**
         * Return per-line offsets into the text returned by {@link #getText()}.  Each entry
         * in the array is a formatted line of text, and the value it contains is the offset
         * into the text string where that line starts.  May return null if there is no line
         * information.
         */
        public int[] getTextLineCharOffsets() {
            return mText != null ? mText.mLineCharOffsets : null;
        }

        /**
         * Return per-line baselines into the text returned by {@link #getText()}.  Each entry
         * in the array is a formatted line of text, and the value it contains is the baseline
         * where that text appears in the view.  May return null if there is no line
         * information.
         */
        public int[] getTextLineBaselines() {
            return mText != null ? mText.mLineBaselines : null;
        }

        /**
        /**
         * Return additional hint text associated with the node; this is typically used with
         * Return additional hint text associated with the node; this is typically used with
         * a node that takes user input, describing to the user what the input means.
         * a node that takes user input, describing to the user what the input means.
@@ -900,6 +940,13 @@ public class AssistStructure implements Parcelable {
            t.mTextStyle = style;
            t.mTextStyle = style;
        }
        }


        @Override
        public void setTextLines(int[] charOffsets, int[] baselines) {
            ViewNodeText t = getNodeText();
            t.mLineCharOffsets = charOffsets;
            t.mLineBaselines = baselines;
        }

        @Override
        @Override
        public void setHint(CharSequence hint) {
        public void setHint(CharSequence hint) {
            getNodeText().mHint = hint != null ? hint.toString() : null;
            getNodeText().mHint = hint != null ? hint.toString() : null;
+11 −0
Original line number Original line Diff line number Diff line
@@ -177,6 +177,17 @@ public abstract class ViewStructure {
     */
     */
    public abstract void setTextStyle(float size, int fgColor, int bgColor, int style);
    public abstract void setTextStyle(float size, int fgColor, int bgColor, int style);


    /**
     * Set line information for test that was previously supplied through
     * {@link #setText(CharSequence)}.  This provides the line breaking of the text as it
     * is shown on screen.  This function takes ownership of the provided arrays; you should
     * not make further modification to them.
     *
     * @param charOffsets The offset in to {@link #setText} where a line starts.
     * @param baselines The baseline where the line is drawn on screen.
     */
    public abstract void setTextLines(int[] charOffsets, int[] baselines);

    /**
    /**
     * Set optional hint text associated with this view; this is for example the text that is
     * Set optional hint text associated with this view; this is for example the text that is
     * shown by an EditText when it is empty to indicate to the user the kind of text to input.
     * shown by an EditText when it is empty to indicate to the user the kind of text to input.
+96 −13
Original line number Original line Diff line number Diff line
@@ -46,7 +46,6 @@ import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Drawable;
import android.inputmethodservice.ExtractEditText;
import android.os.AsyncTask;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcel;
@@ -116,6 +115,7 @@ import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View;
import android.view.ViewParent;
import android.view.ViewStructure;
import android.view.ViewStructure;
import android.view.ViewConfiguration;
import android.view.ViewConfiguration;
import android.view.ViewDebug;
import android.view.ViewDebug;
@@ -5823,6 +5823,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            return super.getBaseline();
            return super.getBaseline();
        }
        }


        return getBaselineOffset() + mLayout.getLineBaseline(0);
    }

    int getBaselineOffset() {
        int voffset = 0;
        int voffset = 0;
        if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != Gravity.TOP) {
        if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != Gravity.TOP) {
            voffset = getVerticalOffset(true);
            voffset = getVerticalOffset(true);
@@ -5832,7 +5836,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            voffset -= getOpticalInsets().top;
            voffset -= getOpticalInsets().top;
        }
        }


        return getExtendedPaddingTop() + voffset + mLayout.getLineBaseline(0);
        return getExtendedPaddingTop() + voffset;
    }
    }


    /**
    /**
@@ -8767,7 +8771,79 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        final boolean isPassword = hasPasswordTransformationMethod()
        final boolean isPassword = hasPasswordTransformationMethod()
                || isPasswordInputType(getInputType());
                || isPasswordInputType(getInputType());
        if (!isPassword) {
        if (!isPassword) {
            if (mLayout == null) {
                assumeLayout();
            }
            Layout layout = mLayout;
            final int lineCount = layout.getLineCount();
            if (lineCount <= 1) {
                // Simple case: this is a single line.
                structure.setText(getText(), getSelectionStart(), getSelectionEnd());
                structure.setText(getText(), getSelectionStart(), getSelectionEnd());
            } else {
                // Complex case: multi-line, could be scrolled or within a scroll container
                // so some lines are not visible.
                final int[] tmpCords = new int[2];
                getLocationInWindow(tmpCords);
                final int topWindowLocation = tmpCords[1];
                View root = this;
                ViewParent viewParent = getParent();
                while (viewParent instanceof View) {
                    root = (View) viewParent;
                    viewParent = root.getParent();
                }
                final int windowHeight = root.getHeight();
                final int topLine;
                final int bottomLine;
                if (topWindowLocation >= 0) {
                    // The top of the view is fully within its window; start text at line 0.
                    topLine = getLineAtCoordinateUnclamped(0);
                    bottomLine = getLineAtCoordinateUnclamped(windowHeight-1);
                } else {
                    // The top of hte window has scrolled off the top of the window; figure out
                    // the starting line for this.
                    topLine = getLineAtCoordinateUnclamped(-topWindowLocation);
                    bottomLine = getLineAtCoordinateUnclamped(windowHeight-1-topWindowLocation);
                }
                // We want to return some contextual lines above/below the lines that are
                // actually visible.
                int expandedTopLine = topLine - (bottomLine-topLine)/2;
                if (expandedTopLine < 0) {
                    expandedTopLine = 0;
                }
                int expandedBottomLine = bottomLine + (bottomLine-topLine)/2;
                if (expandedBottomLine >= lineCount) {
                    expandedBottomLine = lineCount-1;
                }
                // Convert lines into character offsets.
                int expandedTopChar = layout.getLineStart(expandedTopLine);
                int expandedBottomChar = layout.getLineEnd(expandedBottomLine);
                // Take into account selection -- if there is a selection, we need to expand
                // the text we are returning to include that selection.
                final int selStart = getSelectionStart();
                final int selEnd = getSelectionEnd();
                if (selStart < selEnd) {
                    if (selStart < expandedTopChar) {
                        expandedTopChar = selStart;
                    }
                    if (selEnd > expandedBottomChar) {
                        expandedBottomChar = selEnd;
                    }
                }
                // Get the text and trim it to the range we are reporting.
                CharSequence text = getText();
                if (expandedTopChar > 0 || expandedBottomChar < text.length()) {
                    text = text.subSequence(expandedTopChar, expandedBottomChar);
                }
                structure.setText(text, selStart-expandedTopChar, selEnd-expandedTopChar);
                final int[] lineOffsets = new int[bottomLine-topLine+1];
                final int[] lineBaselines = new int[bottomLine-topLine+1];
                final int baselineOffset = getBaselineOffset();
                for (int i=topLine; i<=bottomLine; i++) {
                    lineOffsets[i-topLine] = layout.getLineStart(i);
                    lineBaselines[i-topLine] = layout.getLineBaseline(i) + baselineOffset;
                }
                structure.setTextLines(lineOffsets, lineBaselines);
            }


            // Extract style information that applies to the TextView as a whole.
            // Extract style information that applies to the TextView as a whole.
            int style = 0;
            int style = 0;
@@ -9200,24 +9276,25 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
     * If provided, this ActionMode.Callback will be used to create the ActionMode when text
     * If provided, this ActionMode.Callback will be used to create the ActionMode when text
     * selection is initiated in this View.
     * selection is initiated in this View.
     *
     *
     * The standard implementation populates the menu with a subset of Select All, Cut, Copy,
     * <p>The standard implementation populates the menu with a subset of Select All, Cut, Copy,
     * Paste, Replace and Share actions, depending on what this View supports.
     * Paste, Replace and Share actions, depending on what this View supports.
     *
     *
     * A custom implementation can add new entries in the default menu in its
     * <p>A custom implementation can add new entries in the default menu in its
     * {@link android.view.ActionMode.Callback#onPrepareActionMode(ActionMode, Menu)} method. The
     * {@link android.view.ActionMode.Callback#onPrepareActionMode(ActionMode, android.view.Menu)}
     * default actions can also be removed from the menu using
     * method. The default actions can also be removed from the menu using
     * {@link android.view.Menu#removeItem(int)} and passing {@link android.R.id#selectAll},
     * {@link android.view.Menu#removeItem(int)} and passing {@link android.R.id#selectAll},
     * {@link android.R.id#cut}, {@link android.R.id#copy}, {@link android.R.id#paste},
     * {@link android.R.id#cut}, {@link android.R.id#copy}, {@link android.R.id#paste},
     * {@link android.R.id#replaceText} or {@link android.R.id#shareText} ids as parameters.
     * {@link android.R.id#replaceText} or {@link android.R.id#shareText} ids as parameters.
     *
     *
     * Returning false from
     * <p>Returning false from
     * {@link android.view.ActionMode.Callback#onCreateActionMode(ActionMode, Menu)} will prevent
     * {@link android.view.ActionMode.Callback#onCreateActionMode(ActionMode, android.view.Menu)}
     * the action mode from being started.
     * will prevent the action mode from being started.
     *
     *
     * Action click events should be handled by the custom implementation of
     * <p>Action click events should be handled by the custom implementation of
     * {@link android.view.ActionMode.Callback#onActionItemClicked(ActionMode, MenuItem)}.
     * {@link android.view.ActionMode.Callback#onActionItemClicked(ActionMode,
     * android.view.MenuItem)}.
     *
     *
     * Note that text selection mode is not started when a TextView receives focus and the
     * <p>Note that text selection mode is not started when a TextView receives focus and the
     * {@link android.R.attr#selectAllOnFocus} flag has been set. The content is highlighted in
     * {@link android.R.attr#selectAllOnFocus} flag has been set. The content is highlighted in
     * that case, to allow for quick replacement.
     * that case, to allow for quick replacement.
     */
     */
@@ -9448,6 +9525,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        return getLayout().getLineForVertical((int) y);
        return getLayout().getLineForVertical((int) y);
    }
    }


    int getLineAtCoordinateUnclamped(float y) {
        y -= getTotalPaddingTop();
        y += getScrollY();
        return getLayout().getLineForVertical((int) y);
    }

    int getOffsetAtCoordinate(int line, float x) {
    int getOffsetAtCoordinate(int line, float x) {
        x = convertToLocalHorizontalCoordinate(x);
        x = convertToLocalHorizontalCoordinate(x);
        return getLayout().getOffsetForHorizontal(line, x);
        return getLayout().getOffsetForHorizontal(line, x);
Loading