diff options
Diffstat (limited to 'java/src/com/android/inputmethod/compat')
11 files changed, 323 insertions, 118 deletions
diff --git a/java/src/com/android/inputmethod/compat/BuildCompatUtils.java b/java/src/com/android/inputmethod/compat/BuildCompatUtils.java index 7d1717bd1..5d56f12ae 100644 --- a/java/src/com/android/inputmethod/compat/BuildCompatUtils.java +++ b/java/src/com/android/inputmethod/compat/BuildCompatUtils.java @@ -33,11 +33,4 @@ public final class BuildCompatUtils { public static final int EFFECTIVE_SDK_INT = IS_RELEASE_BUILD ? Build.VERSION.SDK_INT : Build.VERSION.SDK_INT + 1; - - /** - * API version for L-release. - */ - // TODO: Substitute this constant reference with Build.VERSION_CODES.L* once the *next* version - // becomes available. - public static final int VERSION_CODES_LXX = 21; } diff --git a/java/src/com/android/inputmethod/compat/CharacterCompat.java b/java/src/com/android/inputmethod/compat/CharacterCompat.java new file mode 100644 index 000000000..609fe1638 --- /dev/null +++ b/java/src/com/android/inputmethod/compat/CharacterCompat.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.compat; + +import java.lang.reflect.Method; + +public final class CharacterCompat { + // Note that Character.isAlphabetic(int), has been introduced in API level 19 + // (Build.VERSION_CODE.KITKAT). + private static final Method METHOD_isAlphabetic = CompatUtils.getMethod( + Character.class, "isAlphabetic", int.class); + + private CharacterCompat() { + // This utility class is not publicly instantiable. + } + + public static boolean isAlphabetic(final int code) { + if (METHOD_isAlphabetic != null) { + return (Boolean)CompatUtils.invoke(null, false, METHOD_isAlphabetic, code); + } + switch (Character.getType(code)) { + case Character.UPPERCASE_LETTER: + case Character.LOWERCASE_LETTER: + case Character.TITLECASE_LETTER: + case Character.MODIFIER_LETTER: + case Character.OTHER_LETTER: + case Character.LETTER_NUMBER: + return true; + default: + return false; + } + } +} diff --git a/java/src/com/android/inputmethod/compat/CompatUtils.java b/java/src/com/android/inputmethod/compat/CompatUtils.java index 6aa2736c1..5db80190c 100644 --- a/java/src/com/android/inputmethod/compat/CompatUtils.java +++ b/java/src/com/android/inputmethod/compat/CompatUtils.java @@ -144,7 +144,7 @@ public final class CompatUtils { public <T> ToObjectMethodWrapper<T> getMethod(final String name, final T defaultValue, final Class<?>... parameterTypes) { - return new ToObjectMethodWrapper<T>(CompatUtils.getMethod(mClass, name, parameterTypes), + return new ToObjectMethodWrapper<>(CompatUtils.getMethod(mClass, name, parameterTypes), defaultValue); } diff --git a/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java b/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java index 5af31795c..01a9e6712 100644 --- a/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java +++ b/java/src/com/android/inputmethod/compat/CursorAnchorInfoCompatWrapper.java @@ -16,13 +16,20 @@ package com.android.inputmethod.compat; +import android.annotation.TargetApi; import android.graphics.Matrix; import android.graphics.RectF; +import android.os.Build; +import android.view.inputmethod.CursorAnchorInfo; -import com.android.inputmethod.annotations.UsedForTesting; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; -@UsedForTesting -public final class CursorAnchorInfoCompatWrapper { +/** + * A wrapper for {@link CursorAnchorInfo}, which has been introduced in API Level 21. You can use + * this wrapper to avoid direct dependency on newly introduced types. + */ +public class CursorAnchorInfoCompatWrapper { /** * The insertion marker or character bounds have at least one visible region. @@ -39,123 +46,140 @@ public final class CursorAnchorInfoCompatWrapper { */ public static final int FLAG_IS_RTL = 0x04; - // Note that CursorAnchorInfo has been introduced in API level XX (Build.VERSION_CODE.LXX). - private static final CompatUtils.ClassWrapper sCursorAnchorInfoClass; - private static final CompatUtils.ToIntMethodWrapper sGetSelectionStartMethod; - private static final CompatUtils.ToIntMethodWrapper sGetSelectionEndMethod; - private static final CompatUtils.ToObjectMethodWrapper<RectF> sGetCharacterBoundsMethod; - private static final CompatUtils.ToIntMethodWrapper sGetCharacterBoundsFlagsMethod; - private static final CompatUtils.ToObjectMethodWrapper<CharSequence> sGetComposingTextMethod; - private static final CompatUtils.ToIntMethodWrapper sGetComposingTextStartMethod; - private static final CompatUtils.ToFloatMethodWrapper sGetInsertionMarkerBaselineMethod; - private static final CompatUtils.ToFloatMethodWrapper sGetInsertionMarkerBottomMethod; - private static final CompatUtils.ToFloatMethodWrapper sGetInsertionMarkerHorizontalMethod; - private static final CompatUtils.ToFloatMethodWrapper sGetInsertionMarkerTopMethod; - private static final CompatUtils.ToObjectMethodWrapper<Matrix> sGetMatrixMethod; - private static final CompatUtils.ToIntMethodWrapper sGetInsertionMarkerFlagsMethod; - - private static int INVALID_TEXT_INDEX = -1; - static { - sCursorAnchorInfoClass = CompatUtils.getClassWrapper( - "android.view.inputmethod.CursorAnchorInfo"); - sGetSelectionStartMethod = sCursorAnchorInfoClass.getPrimitiveMethod( - "getSelectionStart", INVALID_TEXT_INDEX); - sGetSelectionEndMethod = sCursorAnchorInfoClass.getPrimitiveMethod( - "getSelectionEnd", INVALID_TEXT_INDEX); - sGetCharacterBoundsMethod = sCursorAnchorInfoClass.getMethod( - "getCharacterBounds", (RectF)null, int.class); - sGetCharacterBoundsFlagsMethod = sCursorAnchorInfoClass.getPrimitiveMethod( - "getCharacterBoundsFlags", 0, int.class); - sGetComposingTextMethod = sCursorAnchorInfoClass.getMethod( - "getComposingText", (CharSequence)null); - sGetComposingTextStartMethod = sCursorAnchorInfoClass.getPrimitiveMethod( - "getComposingTextStart", INVALID_TEXT_INDEX); - sGetInsertionMarkerBaselineMethod = sCursorAnchorInfoClass.getPrimitiveMethod( - "getInsertionMarkerBaseline", 0.0f); - sGetInsertionMarkerBottomMethod = sCursorAnchorInfoClass.getPrimitiveMethod( - "getInsertionMarkerBottom", 0.0f); - sGetInsertionMarkerHorizontalMethod = sCursorAnchorInfoClass.getPrimitiveMethod( - "getInsertionMarkerHorizontal", 0.0f); - sGetInsertionMarkerTopMethod = sCursorAnchorInfoClass.getPrimitiveMethod( - "getInsertionMarkerTop", 0.0f); - sGetMatrixMethod = sCursorAnchorInfoClass.getMethod("getMatrix", (Matrix)null); - sGetInsertionMarkerFlagsMethod = sCursorAnchorInfoClass.getPrimitiveMethod( - "getInsertionMarkerFlags", 0); - } - - @UsedForTesting - public boolean isAvailable() { - return sCursorAnchorInfoClass.exists() && mInstance != null; - } - - private Object mInstance; - - private CursorAnchorInfoCompatWrapper(final Object instance) { - mInstance = instance; + CursorAnchorInfoCompatWrapper() { + // This class is not publicly instantiable. } - @UsedForTesting - public static CursorAnchorInfoCompatWrapper fromObject(final Object instance) { - if (!sCursorAnchorInfoClass.exists()) { - return new CursorAnchorInfoCompatWrapper(null); + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + @Nullable + public static CursorAnchorInfoCompatWrapper wrap(@Nullable final CursorAnchorInfo instance) { + if (BuildCompatUtils.EFFECTIVE_SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + return null; } - return new CursorAnchorInfoCompatWrapper(instance); - } - - private static final class FakeHolder { - static CursorAnchorInfoCompatWrapper sInstance = new CursorAnchorInfoCompatWrapper(null); - } - - @UsedForTesting - public static CursorAnchorInfoCompatWrapper getFake() { - return FakeHolder.sInstance; + if (instance == null) { + return null; + } + return new RealWrapper(instance); } public int getSelectionStart() { - return sGetSelectionStartMethod.invoke(mInstance); + throw new UnsupportedOperationException("not supported."); } public int getSelectionEnd() { - return sGetSelectionEndMethod.invoke(mInstance); + throw new UnsupportedOperationException("not supported."); } public CharSequence getComposingText() { - return sGetComposingTextMethod.invoke(mInstance); + throw new UnsupportedOperationException("not supported."); } public int getComposingTextStart() { - return sGetComposingTextStartMethod.invoke(mInstance); + throw new UnsupportedOperationException("not supported."); } public Matrix getMatrix() { - return sGetMatrixMethod.invoke(mInstance); + throw new UnsupportedOperationException("not supported."); } + @SuppressWarnings("unused") public RectF getCharacterBounds(final int index) { - return sGetCharacterBoundsMethod.invoke(mInstance, index); + throw new UnsupportedOperationException("not supported."); } + @SuppressWarnings("unused") public int getCharacterBoundsFlags(final int index) { - return sGetCharacterBoundsFlagsMethod.invoke(mInstance, index); + throw new UnsupportedOperationException("not supported."); } public float getInsertionMarkerBaseline() { - return sGetInsertionMarkerBaselineMethod.invoke(mInstance); + throw new UnsupportedOperationException("not supported."); } public float getInsertionMarkerBottom() { - return sGetInsertionMarkerBottomMethod.invoke(mInstance); + throw new UnsupportedOperationException("not supported."); } public float getInsertionMarkerHorizontal() { - return sGetInsertionMarkerHorizontalMethod.invoke(mInstance); + throw new UnsupportedOperationException("not supported."); } public float getInsertionMarkerTop() { - return sGetInsertionMarkerTopMethod.invoke(mInstance); + throw new UnsupportedOperationException("not supported."); } public int getInsertionMarkerFlags() { - return sGetInsertionMarkerFlagsMethod.invoke(mInstance); + throw new UnsupportedOperationException("not supported."); + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + private static final class RealWrapper extends CursorAnchorInfoCompatWrapper { + + @Nonnull + private final CursorAnchorInfo mInstance; + + public RealWrapper(@Nonnull final CursorAnchorInfo info) { + mInstance = info; + } + + @Override + public int getSelectionStart() { + return mInstance.getSelectionStart(); + } + + @Override + public int getSelectionEnd() { + return mInstance.getSelectionEnd(); + } + + @Override + public CharSequence getComposingText() { + return mInstance.getComposingText(); + } + + @Override + public int getComposingTextStart() { + return mInstance.getComposingTextStart(); + } + + @Override + public Matrix getMatrix() { + return mInstance.getMatrix(); + } + + @Override + public RectF getCharacterBounds(final int index) { + return mInstance.getCharacterBounds(index); + } + + @Override + public int getCharacterBoundsFlags(final int index) { + return mInstance.getCharacterBoundsFlags(index); + } + + @Override + public float getInsertionMarkerBaseline() { + return mInstance.getInsertionMarkerBaseline(); + } + + @Override + public float getInsertionMarkerBottom() { + return mInstance.getInsertionMarkerBottom(); + } + + @Override + public float getInsertionMarkerHorizontal() { + return mInstance.getInsertionMarkerHorizontal(); + } + + @Override + public float getInsertionMarkerTop() { + return mInstance.getInsertionMarkerTop(); + } + + @Override + public int getInsertionMarkerFlags() { + return mInstance.getInsertionMarkerFlags(); + } } } diff --git a/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatUtils.java b/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatUtils.java index 365867257..3a27c5739 100644 --- a/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatUtils.java +++ b/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatUtils.java @@ -20,7 +20,8 @@ import android.os.Build; import android.view.inputmethod.InputMethodSubtype; import com.android.inputmethod.annotations.UsedForTesting; -import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.RichInputMethodSubtype; +import com.android.inputmethod.latin.common.Constants; import java.lang.reflect.Constructor; import java.lang.reflect.Method; @@ -51,6 +52,7 @@ public final class InputMethodSubtypeCompatUtils { // This utility class is not publicly instantiable. } + @SuppressWarnings("deprecation") public static InputMethodSubtype newInputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue, boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype, int id) { @@ -64,6 +66,10 @@ public final class InputMethodSubtypeCompatUtils { overridesImplicitlyEnabledSubtype, id); } + public static boolean isAsciiCapable(final RichInputMethodSubtype subtype) { + return isAsciiCapable(subtype.getRawSubtype()); + } + public static boolean isAsciiCapable(final InputMethodSubtype subtype) { return isAsciiCapableWithAPI(subtype) || subtype.containsExtraValueKey(Constants.Subtype.ExtraValue.ASCII_CAPABLE); diff --git a/java/src/com/android/inputmethod/compat/LocaleSpanCompatUtils.java b/java/src/com/android/inputmethod/compat/LocaleSpanCompatUtils.java index f411f181b..58e5a36b6 100644 --- a/java/src/com/android/inputmethod/compat/LocaleSpanCompatUtils.java +++ b/java/src/com/android/inputmethod/compat/LocaleSpanCompatUtils.java @@ -17,6 +17,7 @@ package com.android.inputmethod.compat; import android.text.Spannable; +import android.text.Spanned; import android.text.style.LocaleSpan; import android.util.Log; @@ -127,13 +128,13 @@ public final class LocaleSpanCompatUtils { final int spanFlag = spannable.getSpanFlags(existingLocaleSpan); if (spanStart < newStart) { newStart = spanStart; - isStartExclusive = ((spanFlag & Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) == - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + isStartExclusive = ((spanFlag & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) == + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } if (newEnd < spanEnd) { newEnd = spanEnd; - isEndExclusive = ((spanFlag & Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) == - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + isEndExclusive = ((spanFlag & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) == + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } existingLocaleSpansToBeMerged.add(existingLocaleSpan); } @@ -201,24 +202,17 @@ public final class LocaleSpanCompatUtils { private static int getSpanFlag(final int originalFlag, final boolean isStartExclusive, final boolean isEndExclusive) { - return (originalFlag & ~Spannable.SPAN_POINT_MARK_MASK) | + return (originalFlag & ~Spanned.SPAN_POINT_MARK_MASK) | getSpanPointMarkFlag(isStartExclusive, isEndExclusive); } private static int getSpanPointMarkFlag(final boolean isStartExclusive, final boolean isEndExclusive) { if (isStartExclusive) { - if (isEndExclusive) { - return Spannable.SPAN_EXCLUSIVE_EXCLUSIVE; - } else { - return Spannable.SPAN_EXCLUSIVE_INCLUSIVE; - } - } else { - if (isEndExclusive) { - return Spannable.SPAN_INCLUSIVE_EXCLUSIVE; - } else { - return Spannable.SPAN_INCLUSIVE_INCLUSIVE; - } + return isEndExclusive ? Spanned.SPAN_EXCLUSIVE_EXCLUSIVE + : Spanned.SPAN_EXCLUSIVE_INCLUSIVE; } + return isEndExclusive ? Spanned.SPAN_INCLUSIVE_EXCLUSIVE + : Spanned.SPAN_INCLUSIVE_INCLUSIVE; } } diff --git a/java/src/com/android/inputmethod/compat/NotificationCompatUtils.java b/java/src/com/android/inputmethod/compat/NotificationCompatUtils.java index eb180071e..70ab972c5 100644 --- a/java/src/com/android/inputmethod/compat/NotificationCompatUtils.java +++ b/java/src/com/android/inputmethod/compat/NotificationCompatUtils.java @@ -71,13 +71,13 @@ public class NotificationCompatUtils { CompatUtils.invoke(builder, null, METHOD_setPriority, PRIORITY_LOW); } + @SuppressWarnings("deprecation") public static Notification build(final Notification.Builder builder) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { // #build was added in API level 16, JELLY_BEAN return (Notification) CompatUtils.invoke(builder, null, METHOD_build); - } else { - // #getNotification was deprecated in API level 16, JELLY_BEAN - return builder.getNotification(); } + // #getNotification was deprecated in API level 16, JELLY_BEAN + return builder.getNotification(); } } diff --git a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java index c33c01552..d3e24e342 100644 --- a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java +++ b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java @@ -23,13 +23,18 @@ import android.text.Spanned; import android.text.TextUtils; import android.text.style.SuggestionSpan; +import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.SuggestedWords; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; -import com.android.inputmethod.latin.define.DebugFlags; import com.android.inputmethod.latin.SuggestionSpanPickedNotificationReceiver; +import com.android.inputmethod.latin.define.DebugFlags; +import com.android.inputmethod.latin.utils.LocaleUtils; import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.Locale; + +import javax.annotation.Nullable; public final class SuggestionSpanUtils { // Note that SuggestionSpan.FLAG_AUTO_CORRECTION has been introduced @@ -51,12 +56,14 @@ public final class SuggestionSpanUtils { // This utility class is not publicly instantiable. } + @UsedForTesting public static CharSequence getTextWithAutoCorrectionIndicatorUnderline( final Context context, final String text) { if (TextUtils.isEmpty(text) || OBJ_FLAG_AUTO_CORRECTION == null) { return text; } final Spannable spannable = new SpannableString(text); + // TODO: Set locale if it is feasible. final SuggestionSpan suggestionSpan = new SuggestionSpan(context, null /* locale */, new String[] {} /* suggestions */, OBJ_FLAG_AUTO_CORRECTION, SuggestionSpanPickedNotificationReceiver.class); @@ -65,6 +72,7 @@ public final class SuggestionSpanUtils { return spannable; } + @UsedForTesting public static CharSequence getTextWithSuggestionSpan(final Context context, final String pickedWord, final SuggestedWords suggestedWords) { if (TextUtils.isEmpty(pickedWord) || suggestedWords.isEmpty() @@ -86,6 +94,7 @@ public final class SuggestionSpanUtils { suggestionsList.add(word.toString()); } } + // TODO: Set locale if it is feasible. final SuggestionSpan suggestionSpan = new SuggestionSpan(context, null /* locale */, suggestionsList.toArray(new String[suggestionsList.size()]), 0 /* flags */, SuggestionSpanPickedNotificationReceiver.class); @@ -93,4 +102,28 @@ public final class SuggestionSpanUtils { spannable.setSpan(suggestionSpan, 0, pickedWord.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); return spannable; } + + /** + * Returns first {@link Locale} found in the given array of {@link SuggestionSpan}. + * @param suggestionSpans the array of {@link SuggestionSpan} to be examined. + * @return the first {@link Locale} found in {@code suggestionSpans}. {@code null} when not + * found. + */ + @UsedForTesting + @Nullable + public static Locale findFirstLocaleFromSuggestionSpans( + final SuggestionSpan[] suggestionSpans) { + for (final SuggestionSpan suggestionSpan : suggestionSpans) { + final String localeString = suggestionSpan.getLocale(); + if (TextUtils.isEmpty(localeString)) { + continue; + } + final Locale locale = LocaleUtils.constructLocaleFromString(localeString); + if (locale == null) { + continue; + } + return locale; + } + return null; + } } diff --git a/java/src/com/android/inputmethod/compat/ViewCompatUtils.java b/java/src/com/android/inputmethod/compat/ViewCompatUtils.java index 0f00be133..16260ab6a 100644 --- a/java/src/com/android/inputmethod/compat/ViewCompatUtils.java +++ b/java/src/com/android/inputmethod/compat/ViewCompatUtils.java @@ -31,9 +31,6 @@ public final class ViewCompatUtils { private static final Method METHOD_setPaddingRelative = CompatUtils.getMethod( View.class, "setPaddingRelative", int.class, int.class, int.class, int.class); - // Note that View.setElevation(float) has been introduced in API level 21. - private static final Method METHOD_setElevation = CompatUtils.getMethod( - View.class, "setElevation", float.class); // Note that View.setTextAlignment(int) has been introduced in API level 17. private static final Method METHOD_setTextAlignment = CompatUtils.getMethod( View.class, "setTextAlignment", int.class); @@ -58,10 +55,6 @@ public final class ViewCompatUtils { CompatUtils.invoke(view, null, METHOD_setPaddingRelative, start, top, end, bottom); } - public static void setElevation(final View view, final float elevation) { - CompatUtils.invoke(view, null, METHOD_setElevation, elevation); - } - // These TEXT_ALIGNMENT_* constants have been introduced in API 17. public static final int TEXT_ALIGNMENT_INHERIT = 0; public static final int TEXT_ALIGNMENT_GRAVITY = 1; diff --git a/java/src/com/android/inputmethod/compat/ViewOutlineProviderCompatUtils.java b/java/src/com/android/inputmethod/compat/ViewOutlineProviderCompatUtils.java new file mode 100644 index 000000000..0c8e5b77d --- /dev/null +++ b/java/src/com/android/inputmethod/compat/ViewOutlineProviderCompatUtils.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.compat; + +import android.inputmethodservice.InputMethodService; +import android.os.Build; +import android.view.View; + +public class ViewOutlineProviderCompatUtils { + private ViewOutlineProviderCompatUtils() { + // This utility class is not publicly instantiable. + } + + public interface InsetsUpdater { + public void setInsets(final InputMethodService.Insets insets); + } + + private static final InsetsUpdater EMPTY_INSETS_UPDATER = new InsetsUpdater() { + @Override + public void setInsets(final InputMethodService.Insets insets) {} + }; + + public static InsetsUpdater setInsetsOutlineProvider(final View view) { + if (BuildCompatUtils.EFFECTIVE_SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + return EMPTY_INSETS_UPDATER; + } + return ViewOutlineProviderCompatUtilsLXX.setInsetsOutlineProvider(view); + } +} diff --git a/java/src/com/android/inputmethod/compat/ViewOutlineProviderCompatUtilsLXX.java b/java/src/com/android/inputmethod/compat/ViewOutlineProviderCompatUtilsLXX.java new file mode 100644 index 000000000..5bbb5ce99 --- /dev/null +++ b/java/src/com/android/inputmethod/compat/ViewOutlineProviderCompatUtilsLXX.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.compat; + +import android.annotation.TargetApi; +import android.graphics.Outline; +import android.inputmethodservice.InputMethodService; +import android.os.Build; +import android.view.View; +import android.view.ViewOutlineProvider; + +import com.android.inputmethod.compat.ViewOutlineProviderCompatUtils.InsetsUpdater; + +@TargetApi(Build.VERSION_CODES.LOLLIPOP) +class ViewOutlineProviderCompatUtilsLXX { + private ViewOutlineProviderCompatUtilsLXX() { + // This utility class is not publicly instantiable. + } + + static InsetsUpdater setInsetsOutlineProvider(final View view) { + final InsetsOutlineProvider provider = new InsetsOutlineProvider(view); + view.setOutlineProvider(provider); + return provider; + } + + private static class InsetsOutlineProvider extends ViewOutlineProvider + implements InsetsUpdater { + private final View mView; + private static final int NO_DATA = -1; + private int mLastVisibleTopInsets = NO_DATA; + + public InsetsOutlineProvider(final View view) { + mView = view; + view.setOutlineProvider(this); + } + + @Override + public void setInsets(final InputMethodService.Insets insets) { + final int visibleTopInsets = insets.visibleTopInsets; + if (mLastVisibleTopInsets != visibleTopInsets) { + mLastVisibleTopInsets = visibleTopInsets; + mView.invalidateOutline(); + } + } + + @Override + public void getOutline(final View view, final Outline outline) { + if (mLastVisibleTopInsets == NO_DATA) { + // Call default implementation. + ViewOutlineProvider.BACKGROUND.getOutline(view, outline); + return; + } + // TODO: Revisit this when floating/resize keyboard is supported. + outline.setRect( + view.getLeft(), mLastVisibleTopInsets, view.getRight(), view.getBottom()); + } + } +} |