182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir/* 282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * Copyright (C) 2017 The Android Open Source Project 382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * 482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * Licensed under the Apache License, Version 2.0 (the "License"); 582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * you may not use this file except in compliance with the License. 682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * You may obtain a copy of the License at 782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * 882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * http://www.apache.org/licenses/LICENSE-2.0 982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * 1082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * Unless required by applicable law or agreed to in writing, software 1182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * distributed under the License is distributed on an "AS IS" BASIS, 1282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * See the License for the specific language governing permissions and 1482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * limitations under the License. 1582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir */ 1682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirpackage android.support.text.emoji.util; 1782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 1868e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinirimport android.app.Instrumentation; 1968e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinirimport android.text.Selection; 2068e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinirimport android.text.Spannable; 2168e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinirimport android.text.method.QwertyKeyListener; 2268e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinirimport android.text.method.TextKeyListener; 2382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport android.view.KeyEvent; 2468e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinirimport android.view.inputmethod.EditorInfo; 25f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport android.view.inputmethod.InputConnection; 2668e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinirimport android.widget.TextView; 2768e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir 2868e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinirimport java.util.concurrent.CountDownLatch; 2982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 3082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir/** 3182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * Utility class for KeyEvents 3282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir */ 3382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirpublic class KeyboardUtil { 3482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private static final int ALT = KeyEvent.META_ALT_ON | KeyEvent.META_ALT_LEFT_ON; 3582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private static final int CTRL = KeyEvent.META_CTRL_ON | KeyEvent.META_CTRL_LEFT_ON; 3682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private static final int SHIFT = KeyEvent.META_SHIFT_ON | KeyEvent.META_SHIFT_LEFT_ON; 3782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private static final int FN = KeyEvent.META_FUNCTION_ON; 3882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 3982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public static KeyEvent zero() { 4082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return keyEvent(KeyEvent.KEYCODE_0); 4182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 4282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 4382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public static KeyEvent del() { 4482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return keyEvent(KeyEvent.KEYCODE_DEL); 4582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 4682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 4782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public static KeyEvent altDel() { 4882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return keyEvent(KeyEvent.KEYCODE_DEL, ALT); 4982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 5082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 5182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public static KeyEvent ctrlDel() { 5282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return keyEvent(KeyEvent.KEYCODE_DEL, CTRL); 5382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 5482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 5582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public static KeyEvent shiftDel() { 5682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return keyEvent(KeyEvent.KEYCODE_DEL, SHIFT); 5782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 5882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 5982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public static KeyEvent fnDel() { 6082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return keyEvent(KeyEvent.KEYCODE_DEL, FN); 6182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 6282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 6382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public static KeyEvent forwardDel() { 6482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return keyEvent(KeyEvent.KEYCODE_FORWARD_DEL); 6582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 6682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 6782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public static KeyEvent keyEvent(int keycode, int metaState) { 6882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir final long currentTime = System.currentTimeMillis(); 6982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return new KeyEvent(currentTime, currentTime, KeyEvent.ACTION_DOWN, keycode, 0, metaState); 7082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 7182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 7282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public static KeyEvent keyEvent(int keycode) { 7382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir final long currentTime = System.currentTimeMillis(); 7482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return new KeyEvent(currentTime, currentTime, KeyEvent.ACTION_DOWN, keycode, 0); 7582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 76f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 7768e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir public static void setComposingTextInBatch(final Instrumentation instrumentation, 7868e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir final InputConnection inputConnection, final CharSequence text) 7968e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir throws InterruptedException { 8068e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir final CountDownLatch latch = new CountDownLatch(1); 8168e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir instrumentation.runOnMainSync(new Runnable() { 8268e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir @Override 8368e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir public void run() { 8468e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir inputConnection.beginBatchEdit(); 8568e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir inputConnection.setComposingText(text, 1); 8668e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir inputConnection.endBatchEdit(); 8768e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir latch.countDown(); 8868e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir } 8968e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir }); 9068e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir 9168e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir latch.await(); 9268e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir instrumentation.waitForIdleSync(); 9368e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir } 9468e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir 9568e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir public static void deleteSurroundingText(final Instrumentation instrumentation, 9668e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir final InputConnection inputConnection, final int before, final int after) 9768e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir throws InterruptedException { 9868e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir final CountDownLatch latch = new CountDownLatch(1); 9968e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir instrumentation.runOnMainSync(new Runnable() { 10068e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir @Override 10168e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir public void run() { 10268e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir inputConnection.beginBatchEdit(); 10368e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir inputConnection.deleteSurroundingText(before, after); 10468e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir inputConnection.endBatchEdit(); 10568e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir latch.countDown(); 10668e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir } 10768e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir }); 10868e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir latch.await(); 10968e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir instrumentation.waitForIdleSync(); 11068e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir } 11168e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir 11268e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir public static void setSelection(Instrumentation instrumentation, final Spannable spannable, 11368e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir final int start) throws InterruptedException { 11468e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir setSelection(instrumentation, spannable, start, start); 11568e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir } 11668e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir 11768e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir public static void setSelection(Instrumentation instrumentation, final Spannable spannable, 11868e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir final int start, final int end) throws InterruptedException { 11968e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir final CountDownLatch latch = new CountDownLatch(1); 12068e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir instrumentation.runOnMainSync(new Runnable() { 12168e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir @Override 12268e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir public void run() { 12368e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir Selection.setSelection(spannable, start, end); 12468e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir latch.countDown(); 12568e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir } 12668e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir }); 12768e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir latch.await(); 12868e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir instrumentation.waitForIdleSync(); 129f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir } 130f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 13168e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir public static InputConnection initTextViewForSimulatedIme(Instrumentation instrumentation, 13268e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir final TextView textView) throws InterruptedException { 13368e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir final CountDownLatch latch = new CountDownLatch(1); 13468e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir instrumentation.runOnMainSync(new Runnable() { 13568e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir @Override 13668e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir public void run() { 13768e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir textView.setKeyListener( 13868e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir QwertyKeyListener.getInstance(false, TextKeyListener.Capitalize.NONE)); 13968e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir textView.setText("", TextView.BufferType.EDITABLE); 14068e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir latch.countDown(); 14168e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir } 14268e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir }); 14368e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir latch.await(); 14468e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir instrumentation.waitForIdleSync(); 14568e7d24c66fb57ae9c2fa538a1cb0b9116673c25Siyamed Sinir return textView.onCreateInputConnection(new EditorInfo()); 146f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir } 14782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir} 148