Home | History | Annotate | Download | only in widget
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package androidx.emoji.widget;
     17 
     18 import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
     19 
     20 import android.text.Editable;
     21 import android.view.inputmethod.EditorInfo;
     22 import android.view.inputmethod.InputConnection;
     23 import android.view.inputmethod.InputConnectionWrapper;
     24 import android.widget.TextView;
     25 
     26 import androidx.annotation.NonNull;
     27 import androidx.annotation.RequiresApi;
     28 import androidx.annotation.RestrictTo;
     29 import androidx.emoji.text.EmojiCompat;
     30 
     31 /**
     32  * InputConnectionWrapper for EditText delete operations. Keyboard does not have knowledge about
     33  * emojis and therefore might send commands to delete a part of the emoji sequence which creates
     34  * invalid codeunits/getCodepointAt in the text.
     35  * <p/>
     36  * This class tries to correctly delete an emoji checking if there is an emoji span.
     37  *
     38  * @hide
     39  */
     40 @RestrictTo(LIBRARY_GROUP)
     41 @RequiresApi(19)
     42 final class EmojiInputConnection extends InputConnectionWrapper {
     43     private final TextView mTextView;
     44 
     45     EmojiInputConnection(
     46             @NonNull final TextView textView,
     47             @NonNull final InputConnection inputConnection,
     48             @NonNull final EditorInfo outAttrs) {
     49         super(inputConnection, false);
     50         mTextView = textView;
     51         EmojiCompat.get().updateEditorInfoAttrs(outAttrs);
     52     }
     53 
     54     @Override
     55     public boolean deleteSurroundingText(final int beforeLength, final int afterLength) {
     56         final boolean result = EmojiCompat.handleDeleteSurroundingText(this, getEditable(),
     57                 beforeLength, afterLength, false /*inCodePoints*/);
     58         return result || super.deleteSurroundingText(beforeLength, afterLength);
     59     }
     60 
     61     @Override
     62     public boolean deleteSurroundingTextInCodePoints(final int beforeLength,
     63             final int afterLength) {
     64         final boolean result = EmojiCompat.handleDeleteSurroundingText(this, getEditable(),
     65                 beforeLength, afterLength, true /*inCodePoints*/);
     66         return result || super.deleteSurroundingTextInCodePoints(beforeLength, afterLength);
     67     }
     68 
     69     private Editable getEditable() {
     70         return mTextView.getEditableText();
     71     }
     72 }
     73