+ * This method must be run on the UI Thread.
+ * @param suggestedWords On-device decoding for the full gesture.
+ */
+ public void onTailBatchInputResultShown(final SuggestedWords suggestedWords) {
+ mGestureConsumer.onImeSuggestionsProcessed(suggestedWords,
+ mInputLogic.getComposingStart(), mInputLogic.getComposingLength());
}
// This method must run on the UI Thread.
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index a7ea2a1c8..62a258b20 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -19,6 +19,7 @@ package com.android.inputmethod.latin;
import android.graphics.Color;
import android.inputmethodservice.InputMethodService;
import android.os.Build;
+import android.os.Bundle;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
@@ -33,6 +34,7 @@ import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import com.android.inputmethod.compat.InputConnectionCompatUtils;
+import com.android.inputmethod.latin.inputlogic.PrivateCommandPerformer;
import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
import com.android.inputmethod.latin.utils.CapsModeUtils;
import com.android.inputmethod.latin.utils.DebugLogUtils;
@@ -52,7 +54,7 @@ import java.util.Arrays;
* all the time to find out what text is in the buffer, when we need it to determine caps mode
* for example.
*/
-public final class RichInputConnection {
+public final class RichInputConnection implements PrivateCommandPerformer {
private static final String TAG = RichInputConnection.class.getSimpleName();
private static final boolean DBG = false;
private static final boolean DEBUG_PREVIOUS_TEXT = false;
@@ -896,6 +898,15 @@ public final class RichInputConnection {
}
}
+ @Override
+ public boolean performPrivateCommand(final String action, final Bundle data) {
+ mIC = mParent.getCurrentInputConnection();
+ if (mIC == null) {
+ return false;
+ }
+ return mIC.performPrivateCommand(action, data);
+ }
+
public int getExpectedSelectionStart() {
return mExpectedSelStart;
}
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index f85b34b5e..157bd1565 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -128,8 +128,7 @@ public final class WordComposer {
* Number of keystrokes in the composing word.
* @return the number of keystrokes
*/
- // This may be made public if need be, but right now it's not used anywhere
- /* package for tests */ int size() {
+ public int size() {
return mCodePointSize;
}
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index b4a1c3e65..1b1d5e7e5 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -2263,6 +2263,47 @@ public final class InputLogic {
mConnection.setComposingText(composingTextToBeSet, newCursorPosition);
}
+ /**
+ * Gets an object allowing private IME commands to be sent to the
+ * underlying editor.
+ * @return An object for sending private commands to the underlying editor.
+ */
+ public PrivateCommandPerformer getPrivateCommandPerformer() {
+ return mConnection;
+ }
+
+ /**
+ * Gets the expected index of the first char of the composing span within the editor's text.
+ * Returns a negative value in case there appears to be no valid composing span.
+ *
+ * @see #getComposingLength()
+ * @see RichInputConnection#hasSelection()
+ * @see RichInputConnection#isCursorPositionKnown()
+ * @see RichInputConnection#getExpectedSelectionStart()
+ * @see RichInputConnection#getExpectedSelectionEnd()
+ * @return The expected index in Java chars of the first char of the composing span.
+ */
+ // TODO: try and see if we can get rid of this method. Ideally the users of this class should
+ // never need to know this.
+ public int getComposingStart() {
+ if (!mConnection.isCursorPositionKnown() || mConnection.hasSelection()) {
+ return -1;
+ }
+ return mConnection.getExpectedSelectionStart() - mWordComposer.size();
+ }
+
+ /**
+ * Gets the expected length in Java chars of the composing span.
+ * May be 0 if there is no valid composing span.
+ * @see #getComposingStart()
+ * @return The expected length of the composing span.
+ */
+ // TODO: try and see if we can get rid of this method. Ideally the users of this class should
+ // never need to know this.
+ public int getComposingLength() {
+ return mWordComposer.size();
+ }
+
//////////////////////////////////////////////////////////////////////////////////////////////
// Following methods are tentatively placed in this class for the integration with
// TextDecorator.
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/PrivateCommandPerformer.java b/java/src/com/android/inputmethod/latin/inputlogic/PrivateCommandPerformer.java
new file mode 100644
index 000000000..42eaa9c82
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/inputlogic/PrivateCommandPerformer.java
@@ -0,0 +1,40 @@
+/*
+ * 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.latin.inputlogic;
+
+import android.os.Bundle;
+
+/**
+ * Provides an interface matching
+ * {@link android.view.inputmethod.InputConnection#performPrivateCommand(String,Bundle)}.
+ */
+public interface PrivateCommandPerformer {
+ /**
+ * API to send private commands from an input method to its connected
+ * editor. This can be used to provide domain-specific features that are
+ * only known between certain input methods and their clients.
+ *
+ * @param action Name of the command to be performed. This must be a scoped
+ * name, i.e. prefixed with a package name you own, so that
+ * different developers will not create conflicting commands.
+ * @param data Any data to include with the command.
+ * @return true if the command was sent (regardless of whether the
+ * associated editor understood it), false if the input connection is no
+ * longer valid.
+ */
+ boolean performPrivateCommand(String action, Bundle data);
+}
diff --git a/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java b/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java
index 61292fc36..fb36b7c50 100644
--- a/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/CollectionUtils.java
@@ -17,6 +17,7 @@
package com.android.inputmethod.latin.utils;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.TreeMap;
@@ -40,4 +41,13 @@ public final class CollectionUtils {
}
return list;
}
+
+ /**
+ * Tests whether c contains no elements, true if c is null or c is empty.
+ * @param c Collection to test.
+ * @return Whether c contains no elements.
+ */
+ public static boolean isNullOrEmpty(final Collection c) {
+ return c == null || c.isEmpty();
+ }
}
diff --git a/tests/src/com/android/inputmethod/latin/touchinputconsumer/NullGestureConsumerTests.java b/tests/src/com/android/inputmethod/latin/touchinputconsumer/NullGestureConsumerTests.java
new file mode 100644
index 000000000..ca1039bd9
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/touchinputconsumer/NullGestureConsumerTests.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.latin.touchinputconsumer;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Tests for GestureConsumer.NULL_GESTURE_CONSUMER.
+ */
+@SmallTest
+public class NullGestureConsumerTests extends AndroidTestCase {
+ /**
+ * Tests that GestureConsumer.NULL_GESTURE_CONSUMER indicates that it won't consume gesture data
+ * and that its methods don't raise exceptions even for invalid data.
+ */
+ public void testNullGestureConsumer() {
+ assertFalse(GestureConsumer.NULL_GESTURE_CONSUMER.willConsume());
+ GestureConsumer.NULL_GESTURE_CONSUMER.onInit(null, null);
+ GestureConsumer.NULL_GESTURE_CONSUMER.onGestureStarted(null, null);
+ GestureConsumer.NULL_GESTURE_CONSUMER.onGestureCanceled();
+ GestureConsumer.NULL_GESTURE_CONSUMER.onGestureCompleted(null);
+ GestureConsumer.NULL_GESTURE_CONSUMER.onImeSuggestionsProcessed(null, -1, -1);
+ }
+
+ /**
+ * Tests that newInstance returns NULL_GESTURE_CONSUMER for invalid input.
+ */
+ public void testNewInstanceGivesNullGestureConsumerForInvalidInputs() {
+ assertSame(GestureConsumer.NULL_GESTURE_CONSUMER,
+ GestureConsumer.newInstance(null, null, null, null));
+ }
+}
diff --git a/tests/src/com/android/inputmethod/latin/utils/CollectionUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/CollectionUtilsTests.java
new file mode 100644
index 000000000..76e28288f
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/utils/CollectionUtilsTests.java
@@ -0,0 +1,55 @@
+/*
+ * 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.latin.utils;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+
+/**
+ * Tests for {@link CollectionUtils}.
+ */
+@SmallTest
+public class CollectionUtilsTests extends AndroidTestCase {
+ /**
+ * Tests that {@link CollectionUtils#arrayAsList(E[],int,int)} gives the expected
+ * results for a few valid inputs.
+ */
+ public void testArrayAsList() {
+ final String[] array = { "0", "1", "2", "3", "4" };
+ final ArrayList