aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/event/Combiner.java6
-rw-r--r--java/src/com/android/inputmethod/event/CombinerChain.java34
-rw-r--r--java/src/com/android/inputmethod/event/DeadKeyCombiner.java5
-rw-r--r--java/src/com/android/inputmethod/event/Event.java61
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java2
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java15
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java21
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java4
-rw-r--r--java/src/com/android/inputmethod/latin/RichInputConnection.java24
-rw-r--r--java/src/com/android/inputmethod/latin/WordComposer.java5
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java5
11 files changed, 131 insertions, 51 deletions
diff --git a/java/src/com/android/inputmethod/event/Combiner.java b/java/src/com/android/inputmethod/event/Combiner.java
index c3869a299..bdc761234 100644
--- a/java/src/com/android/inputmethod/event/Combiner.java
+++ b/java/src/com/android/inputmethod/event/Combiner.java
@@ -34,4 +34,10 @@ public interface Combiner {
* @return the resulting event.
*/
Event processEvent(ArrayList<Event> previousEvents, Event event);
+
+ /**
+ * Get the feedback that should be shown to the user for the current state of this combiner.
+ * @return A CharSequence representing the feedback to show users. It may include styles.
+ */
+ CharSequence getCombiningStateFeedback();
}
diff --git a/java/src/com/android/inputmethod/event/CombinerChain.java b/java/src/com/android/inputmethod/event/CombinerChain.java
index 0e01c819a..cf2a4d1a1 100644
--- a/java/src/com/android/inputmethod/event/CombinerChain.java
+++ b/java/src/com/android/inputmethod/event/CombinerChain.java
@@ -16,6 +16,8 @@
package com.android.inputmethod.event;
+import android.text.SpannableStringBuilder;
+
import com.android.inputmethod.latin.utils.CollectionUtils;
import java.util.ArrayList;
@@ -33,8 +35,10 @@ import java.util.ArrayList;
* a colored background.
*/
public class CombinerChain {
- // TODO: Create an object type to represent input material + visual feedback + decoding state
-
+ // The already combined text, as described above
+ private StringBuilder mCombinedText;
+ // The feedback on the composing state, as described above
+ private SpannableStringBuilder mStateFeedback;
private final ArrayList<Combiner> mCombiners;
/**
@@ -50,9 +54,15 @@ public class CombinerChain {
mCombiners = CollectionUtils.newArrayList();
// The dead key combiner is always active, and always first
mCombiners.add(new DeadKeyCombiner());
+ mCombinedText = new StringBuilder();
+ mStateFeedback = new SpannableStringBuilder();
}
- // Pass a new event through the whole chain.
+ /**
+ * Pass a new event through the whole chain.
+ * @param previousEvents the list of previous events in this composition
+ * @param newEvent the new event to process
+ */
public void processEvent(final ArrayList<Event> previousEvents, final Event newEvent) {
final ArrayList<Event> modifiablePreviousEvents = new ArrayList<Event>(previousEvents);
Event event = newEvent;
@@ -62,8 +72,24 @@ public class CombinerChain {
event = combiner.processEvent(modifiablePreviousEvents, event);
if (null == event) {
// Combiners return null if they eat the event.
- return;
+ break;
}
}
+ if (null != event) {
+ mCombinedText.append(event.getTextToCommit());
+ }
+ mStateFeedback.clear();
+ for (int i = mCombiners.size() - 1; i >= 0; --i) {
+ mStateFeedback.append(mCombiners.get(i).getCombiningStateFeedback());
+ }
+ }
+
+ /**
+ * Get the char sequence that should be displayed as the composing word. It may include
+ * styling spans.
+ */
+ public CharSequence getComposingWordWithCombiningFeedback() {
+ final SpannableStringBuilder s = new SpannableStringBuilder(mCombinedText);
+ return s.append(mStateFeedback);
}
}
diff --git a/java/src/com/android/inputmethod/event/DeadKeyCombiner.java b/java/src/com/android/inputmethod/event/DeadKeyCombiner.java
index f77ce6347..f891017a3 100644
--- a/java/src/com/android/inputmethod/event/DeadKeyCombiner.java
+++ b/java/src/com/android/inputmethod/event/DeadKeyCombiner.java
@@ -61,4 +61,9 @@ public class DeadKeyCombiner implements Combiner {
}
}
}
+
+ @Override
+ public CharSequence getCombiningStateFeedback() {
+ return mDeadSequence;
+ }
}
diff --git a/java/src/com/android/inputmethod/event/Event.java b/java/src/com/android/inputmethod/event/Event.java
index bd4143d25..2bfe0732d 100644
--- a/java/src/com/android/inputmethod/event/Event.java
+++ b/java/src/com/android/inputmethod/event/Event.java
@@ -18,6 +18,7 @@ package com.android.inputmethod.event;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.utils.StringUtils;
/**
* Class representing a generic input event as handled by Latin IME.
@@ -52,6 +53,8 @@ public class Event {
final public static int EVENT_GESTURE = 4;
// An event corresponding to the manual pick of a suggestion.
final public static int EVENT_SUGGESTION_PICKED = 5;
+ // An event corresponding to a string generated by some software process.
+ final public static int EVENT_SOFTWARE_GENERATED_STRING = 6;
// 0 is a valid code point, so we use -1 here.
final public static int NOT_A_CODE_POINT = -1;
@@ -71,6 +74,9 @@ public class Event {
// it's not relevant.
final public int mCodePoint;
+ // If applicable, this contains the string that should be input.
+ final public CharSequence mText;
+
// The key code associated with the event, if relevant. This is relevant whenever this event
// has been triggered by a key press, but not for a gesture for example. This has conceptually
// no link to the code point, although keys that enter a straight code point may often set
@@ -96,9 +102,11 @@ public class Event {
final public Event mNextEvent;
// This method is private - to create a new event, use one of the create* utility methods.
- private Event(final int type, final int codePoint, final int keyCode, final int x, final int y,
- final SuggestedWordInfo suggestedWordInfo, final int flags, final Event next) {
+ private Event(final int type, final CharSequence text, final int codePoint, final int keyCode,
+ final int x, final int y, final SuggestedWordInfo suggestedWordInfo, final int flags,
+ final Event next) {
mType = type;
+ mText = text;
mCodePoint = codePoint;
mKeyCode = keyCode;
mX = x;
@@ -123,13 +131,13 @@ public class Event {
public static Event createSoftwareKeypressEvent(final int codePoint, final int keyCode,
final int x, final int y) {
- return new Event(EVENT_INPUT_KEYPRESS, codePoint, keyCode, x, y,
+ return new Event(EVENT_INPUT_KEYPRESS, null /* text */, codePoint, keyCode, x, y,
null /* suggestedWordInfo */, FLAG_NONE, null);
}
public static Event createHardwareKeypressEvent(final int codePoint, final int keyCode,
final Event next) {
- return new Event(EVENT_INPUT_KEYPRESS, codePoint, keyCode,
+ return new Event(EVENT_INPUT_KEYPRESS, null /* text */, codePoint, keyCode,
Constants.EXTERNAL_KEYBOARD_COORDINATE, Constants.EXTERNAL_KEYBOARD_COORDINATE,
null /* suggestedWordInfo */, FLAG_NONE, next);
}
@@ -137,7 +145,7 @@ public class Event {
// This creates an input event for a dead character. @see {@link #FLAG_DEAD}
public static Event createDeadEvent(final int codePoint, final int keyCode, final Event next) {
// TODO: add an argument or something if we ever create a software layout with dead keys.
- return new Event(EVENT_INPUT_KEYPRESS, codePoint, keyCode,
+ return new Event(EVENT_INPUT_KEYPRESS, null /* text */, codePoint, keyCode,
Constants.EXTERNAL_KEYBOARD_COORDINATE, Constants.EXTERNAL_KEYBOARD_COORDINATE,
null /* suggestedWordInfo */, FLAG_DEAD, next);
}
@@ -151,7 +159,7 @@ public class Event {
*/
public static Event createEventForCodePointFromUnknownSource(final int codePoint) {
// TODO: should we have a different type of event for this? After all, it's not a key press.
- return new Event(EVENT_INPUT_KEYPRESS, codePoint, NOT_A_KEY_CODE,
+ return new Event(EVENT_INPUT_KEYPRESS, null /* text */, codePoint, NOT_A_KEY_CODE,
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
null /* suggestedWordInfo */, FLAG_NONE, null /* next */);
}
@@ -167,7 +175,7 @@ public class Event {
public static Event createEventForCodePointFromAlreadyTypedText(final int codePoint,
final int x, final int y) {
// TODO: should we have a different type of event for this? After all, it's not a key press.
- return new Event(EVENT_INPUT_KEYPRESS, codePoint, NOT_A_KEY_CODE, x, y,
+ return new Event(EVENT_INPUT_KEYPRESS, null /* text */, codePoint, NOT_A_KEY_CODE, x, y,
null /* suggestedWordInfo */, FLAG_NONE, null /* next */);
}
@@ -176,13 +184,28 @@ public class Event {
* @return an event for this suggestion pick.
*/
public static Event createSuggestionPickedEvent(final SuggestedWordInfo suggestedWordInfo) {
- return new Event(EVENT_SUGGESTION_PICKED, NOT_A_CODE_POINT, NOT_A_KEY_CODE,
+ return new Event(EVENT_SUGGESTION_PICKED, suggestedWordInfo.mWord,
+ NOT_A_CODE_POINT, NOT_A_KEY_CODE,
Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE,
suggestedWordInfo, FLAG_NONE, null);
}
+ /**
+ * Creates an input event with a CharSequence. This is used by some software processes whose
+ * output is a string, possibly with styling. Examples include press on a multi-character key,
+ * or combination that outputs a string.
+ * @param text the CharSequence associated with this event.
+ * @param keyCode the key code, or NOT_A_KEYCODE if not applicable.
+ * @return an event for this text.
+ */
+ public static Event createSoftwareTextEvent(final CharSequence text, final int keyCode) {
+ return new Event(EVENT_SOFTWARE_GENERATED_STRING, text, NOT_A_CODE_POINT, keyCode,
+ Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
+ null /* suggestedWordInfo */, FLAG_NONE, null /* next */);
+ }
+
public static Event createNotHandledEvent() {
- return new Event(EVENT_NOT_HANDLED, NOT_A_CODE_POINT, NOT_A_KEY_CODE,
+ return new Event(EVENT_NOT_HANDLED, null /* text */, NOT_A_CODE_POINT, NOT_A_KEY_CODE,
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
null /* suggestedWordInfo */, FLAG_NONE, null);
}
@@ -198,12 +221,22 @@ public class Event {
return EVENT_INPUT_KEYPRESS == mType && Constants.SUGGESTION_STRIP_COORDINATE == mX;
}
- // TODO: remove this method - we should not have to test this
- public boolean isCommittable() {
- return EVENT_INPUT_KEYPRESS == mType || EVENT_MODE_KEY == mType || EVENT_TOGGLE == mType;
- }
-
public boolean isHandled() {
return EVENT_NOT_HANDLED != mType;
}
+
+ public CharSequence getTextToCommit() {
+ switch (mType) {
+ case EVENT_MODE_KEY:
+ case EVENT_NOT_HANDLED:
+ return "";
+ case EVENT_INPUT_KEYPRESS:
+ case EVENT_TOGGLE:
+ return StringUtils.newSingleCodePointString(mCodePoint);
+ case EVENT_GESTURE:
+ case EVENT_SOFTWARE_GENERATED_STRING:
+ return mText;
+ }
+ throw new RuntimeException("Unknown event type: " + mType);
+ }
}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 66cb9e35d..2dfde9434 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -163,7 +163,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
mCurrentSettingsValues = settingsValues;
try {
mState.onLoadKeyboard();
- mKeyboardTextsSet.setLocale(mSubtypeSwitcher.getCurrentSubtypeLocale());
+ mKeyboardTextsSet.setLocale(mSubtypeSwitcher.getCurrentSubtypeLocale(), mThemeContext);
} catch (KeyboardLayoutSetException e) {
Log.w(TAG, "loading keyboard failed: " + e.mKeyboardId, e.getCause());
LatinImeLogger.logOnException(e.mKeyboardId.toString(), e.getCause());
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
index 81a8e7196..dfe0df04c 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
@@ -34,7 +34,6 @@ import com.android.inputmethod.keyboard.KeyboardId;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.utils.ResourceUtils;
-import com.android.inputmethod.latin.utils.RunInLocale;
import com.android.inputmethod.latin.utils.StringUtils;
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
import com.android.inputmethod.latin.utils.XmlParseUtils;
@@ -45,7 +44,6 @@ import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.Arrays;
-import java.util.Locale;
/**
* Keyboard Building helper.
@@ -278,18 +276,7 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
params.mThemeId = keyboardAttr.getInt(R.styleable.Keyboard_themeId, 0);
params.mIconsSet.loadIcons(keyboardAttr);
- final Locale locale = params.mId.mLocale;
- params.mTextsSet.setLocale(locale);
- final RunInLocale<Void> job = new RunInLocale<Void>() {
- @Override
- protected Void job(final Resources res) {
- params.mTextsSet.loadStringResources(mContext);
- return null;
- }
- };
- // Null means the current system locale.
- job.runInLocale(mResources,
- SubtypeLocaleUtils.isNoLanguage(params.mId.mSubtype) ? null : locale);
+ params.mTextsSet.setLocale(params.mId.mLocale, mContext);
final int resourceId = keyboardAttr.getResourceId(
R.styleable.Keyboard_touchPositionCorrectionData, 0);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
index bdc36ed45..044cd119e 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.java
@@ -23,6 +23,8 @@ import android.text.TextUtils;
import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.utils.CollectionUtils;
+import com.android.inputmethod.latin.utils.RunInLocale;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
import java.util.HashMap;
import java.util.Locale;
@@ -38,17 +40,22 @@ public final class KeyboardTextsSet {
// Resource name to text map.
private HashMap<String, String> mResourceNameToTextsMap = CollectionUtils.newHashMap();
- public void setLocale(final Locale locale) {
+ public void setLocale(final Locale locale, final Context context) {
final String language = locale.getLanguage();
mTextsTable = KeyboardTextsTable.getTextsTable(language);
- }
-
- // TODO: Consolidate this method with {@link #setLocale(Locale)}.
- public void loadStringResources(final Context context) {
final Resources res = context.getResources();
final int referenceId = context.getApplicationInfo().labelRes;
final String resourcePackageName = res.getResourcePackageName(referenceId);
- loadStringResourcesInternal(res, RESOURCE_NAMES, resourcePackageName);
+ final RunInLocale<Void> job = new RunInLocale<Void>() {
+ @Override
+ protected Void job(final Resources resource) {
+ loadStringResourcesInternal(res, RESOURCE_NAMES, resourcePackageName);
+ return null;
+ }
+ };
+ // Null means the current system locale.
+ job.runInLocale(res,
+ SubtypeLocaleUtils.NO_LANGUAGE.equals(locale.toString()) ? null : locale);
}
@UsedForTesting
@@ -129,7 +136,7 @@ public final class KeyboardTextsSet {
// These texts' name should be aligned with the @string/<name> in
// values*/strings-action-keys.xml.
- private static final String[] RESOURCE_NAMES = {
+ static final String[] RESOURCE_NAMES = {
// Labels for action.
"label_go_key",
"label_send_key",
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index b6d477629..38e386493 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1277,7 +1277,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Called from PointerTracker through the KeyboardActionListener interface
@Override
public void onTextInput(final String rawText) {
- mInputLogic.onTextInput(mSettings.getCurrent(), rawText, mHandler);
+ // TODO: have the keyboard pass the correct key code when we need it.
+ final Event event = Event.createSoftwareTextEvent(rawText, Event.NOT_A_KEY_CODE);
+ mInputLogic.onTextInput(mSettings.getCurrent(), event, mHandler);
mKeyboardSwitcher.updateShiftState();
mKeyboardSwitcher.onCodeInput(Constants.CODE_OUTPUT_TEXT);
}
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index 965518e34..606bb775e 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -687,13 +687,23 @@ public final class RichInputConnection {
}
public boolean isCursorTouchingWord(final SpacingAndPunctuations spacingAndPunctuations) {
- final int codePointBeforeCursor = getCodePointBeforeCursor();
- if (Constants.NOT_A_CODE == codePointBeforeCursor
- || spacingAndPunctuations.isWordSeparator(codePointBeforeCursor)
- || spacingAndPunctuations.isWordConnector(codePointBeforeCursor)) {
- return isCursorFollowedByWordCharacter(spacingAndPunctuations);
- }
- return true;
+ if (isCursorFollowedByWordCharacter(spacingAndPunctuations)) {
+ // If what's after the cursor is a word character, then we're touching a word.
+ return true;
+ }
+ final String textBeforeCursor = mCommittedTextBeforeComposingText.toString();
+ int indexOfCodePointInJavaChars = textBeforeCursor.length();
+ int consideredCodePoint = 0 == indexOfCodePointInJavaChars ? Constants.NOT_A_CODE
+ : textBeforeCursor.codePointBefore(indexOfCodePointInJavaChars);
+ // Search for the first non word-connector char
+ if (spacingAndPunctuations.isWordConnector(consideredCodePoint)) {
+ indexOfCodePointInJavaChars -= Character.charCount(consideredCodePoint);
+ consideredCodePoint = 0 == indexOfCodePointInJavaChars ? Constants.NOT_A_CODE
+ : textBeforeCursor.codePointBefore(indexOfCodePointInJavaChars);
+ }
+ return !(Constants.NOT_A_CODE == consideredCodePoint
+ || spacingAndPunctuations.isWordSeparator(consideredCodePoint)
+ || spacingAndPunctuations.isWordConnector(consideredCodePoint));
}
public boolean isCursorFollowedByWordCharacter(
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index 29382fea4..d55a773b4 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -193,7 +193,10 @@ public final class WordComposer {
final int keyY = event.mY;
final int newIndex = size();
mCombinerChain.processEvent(mEvents, event);
- mTypedWord.appendCodePoint(primaryCode);
+ // TODO: remove mTypedWord and compute it dynamically when necessary. We also need to
+ // make the views of the composing word a SpannableString.
+ mTypedWord.replace(0, mTypedWord.length(),
+ mCombinerChain.getComposingWordWithCombiningFeedback().toString());
mEvents.add(event);
refreshSize();
mCursorPositionWithinWord = mCodePointSize;
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 8faf17584..36b30eabe 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -161,11 +161,12 @@ public final class InputLogic {
* some additional keys for example.
*
* @param settingsValues the current values of the settings.
- * @param rawText the text to input.
+ * @param event the input event containing the data.
*/
- public void onTextInput(final SettingsValues settingsValues, final String rawText,
+ public void onTextInput(final SettingsValues settingsValues, final Event event,
// TODO: remove this argument
final LatinIME.UIHandler handler) {
+ final String rawText = event.mText.toString();
mConnection.beginBatchEdit();
if (mWordComposer.isComposingWord()) {
commitCurrentAutoCorrection(settingsValues, rawText, handler);