aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/event/DeadKeyCombiner.java8
-rw-r--r--java/src/com/android/inputmethod/event/Event.java130
-rw-r--r--java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java22
-rw-r--r--java/src/com/android/inputmethod/event/InputTransaction.java15
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java52
-rw-r--r--java/src/com/android/inputmethod/latin/LastComposedWord.java15
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java20
-rw-r--r--java/src/com/android/inputmethod/latin/WordComposer.java33
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java266
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java3
10 files changed, 357 insertions, 207 deletions
diff --git a/java/src/com/android/inputmethod/event/DeadKeyCombiner.java b/java/src/com/android/inputmethod/event/DeadKeyCombiner.java
index 52987d571..ae8639713 100644
--- a/java/src/com/android/inputmethod/event/DeadKeyCombiner.java
+++ b/java/src/com/android/inputmethod/event/DeadKeyCombiner.java
@@ -43,19 +43,19 @@ public class DeadKeyCombiner implements Combiner {
final int resultingCodePoint =
KeyCharacterMap.getDeadChar(deadCodePoint, event.mCodePoint);
if (0 == resultingCodePoint) {
- // We can't combine both characters. We need to commit the dead key as a committable
+ // We can't combine both characters. We need to commit the dead key as a separate
// character, and the next char too unless it's a space (because as a special case,
// dead key + space should result in only the dead key being committed - that's
// how dead keys work).
// If the event is a space, we should commit the dead char alone, but if it's
// not, we need to commit both.
- return Event.createCommittableEvent(deadCodePoint,
+ return Event.createHardwareKeypressEvent(deadCodePoint, event.mKeyCode,
Constants.CODE_SPACE == event.mCodePoint ? null : event /* next */);
} else {
// We could combine the characters.
- return Event.createCommittableEvent(resultingCodePoint, null /* next */);
+ return Event.createHardwareKeypressEvent(resultingCodePoint, event.mKeyCode,
+ null /* next */);
}
}
}
-
}
diff --git a/java/src/com/android/inputmethod/event/Event.java b/java/src/com/android/inputmethod/event/Event.java
index 1f3320eb7..ed487e13f 100644
--- a/java/src/com/android/inputmethod/event/Event.java
+++ b/java/src/com/android/inputmethod/event/Event.java
@@ -16,6 +16,8 @@
package com.android.inputmethod.event;
+import com.android.inputmethod.latin.Constants;
+
/**
* Class representing a generic input event as handled by Latin IME.
*
@@ -33,61 +35,137 @@ public class Event {
// but probably a bit too much
// An event we don't handle in Latin IME, for example pressing Ctrl on a hardware keyboard.
final public static int EVENT_NOT_HANDLED = 0;
- // A character that is already final, for example pressing an alphabetic character on a
- // hardware qwerty keyboard.
- final public static int EVENT_COMMITTABLE = 1;
- // A dead key, which means a character that should combine with what is coming next. Examples
- // include the "^" character on an azerty keyboard which combines with "e" to make "ê", or
- // AltGr+' on a dvorak international keyboard which combines with "e" to make "é". This is
- // true regardless of the language or combining mode, and should be seen as a property of the
- // key - a dead key followed by another key with which it can combine should be regarded as if
- // the keyboard actually had such a key.
- final public static int EVENT_DEAD = 2;
+ // A key press that is part of input, for example pressing an alphabetic character on a
+ // hardware qwerty keyboard. It may be part of a sequence that will be re-interpreted later
+ // through combination.
+ final public static int EVENT_INPUT_KEYPRESS = 1;
// A toggle event is triggered by a key that affects the previous character. An example would
// be a numeric key on a 10-key keyboard, which would toggle between 1 - a - b - c with
// repeated presses.
- final public static int EVENT_TOGGLE = 3;
+ final public static int EVENT_TOGGLE = 2;
// A mode event instructs the combiner to change modes. The canonical example would be the
// hankaku/zenkaku key on a Japanese keyboard, or even the caps lock key on a qwerty keyboard
// if handled at the combiner level.
- final public static int EVENT_MODE_KEY = 4;
+ final public static int EVENT_MODE_KEY = 3;
+ // An event corresponding to a gesture.
+ final public static int EVENT_GESTURE = 4;
+
+ // 0 is a valid code point, so we use -1 here.
+ final public static int NOT_A_CODE_POINT = -1;
+ // -1 is a valid key code, so we use 0 here.
+ final public static int NOT_A_KEY_CODE = 0;
- final private static int NOT_A_CODE_POINT = 0;
+ final private static int FLAG_NONE = 0;
+ // This event is a dead character, usually input by a dead key. Examples include dead-acute
+ // or dead-abovering.
+ final private static int FLAG_DEAD = 0x1;
final private int mType; // The type of event - one of the constants above
// The code point associated with the event, if relevant. This is a unicode code point, and
// has nothing to do with other representations of the key. It is only relevant if this event
- // is the right type: COMMITTABLE or DEAD or TOGGLE, but for a mode key like hankaku/zenkaku or
- // ctrl, there is no code point associated so this should be NOT_A_CODE_POINT to avoid
- // unintentional use of its value when it's not relevant.
+ // is of KEYPRESS type, but for a mode key like hankaku/zenkaku or ctrl, there is no code point
+ // associated so this should be NOT_A_CODE_POINT to avoid unintentional use of its value when
+ // it's not relevant.
final public int mCodePoint;
+
+ // 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
+ // this to be equal to mCodePoint for convenience. If this is not a key, this must contain
+ // NOT_A_KEY_CODE.
+ final public int mKeyCode;
+
+ // Coordinates of the touch event, if relevant. If useful, we may want to replace this with
+ // a MotionEvent or something in the future. This is only relevant when the keypress is from
+ // a software keyboard obviously, unless there are touch-sensitive hardware keyboards in the
+ // future or some other awesome sauce.
+ final public int mX;
+ final public int mY;
+
+ // Some flags that can't go into the key code. It's a bit field of FLAG_*
+ final private int mFlags;
+
// The next event, if any. Null if there is no next event yet.
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 Event next) {
+ private Event(final int type, final int codePoint, final int keyCode, final int x, final int y,
+ final int flags, final Event next) {
mType = type;
mCodePoint = codePoint;
+ mKeyCode = keyCode;
+ mX = x;
+ mY = y;
+ mFlags = flags;
mNextEvent = next;
}
- public static Event createDeadEvent(final int codePoint, final Event next) {
- return new Event(EVENT_DEAD, codePoint, next);
+ 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, FLAG_NONE, null);
}
- public static Event createCommittableEvent(final int codePoint, final Event next) {
- return new Event(EVENT_COMMITTABLE, codePoint, next);
+ public static Event createHardwareKeypressEvent(final int codePoint, final int keyCode,
+ final Event next) {
+ return new Event(EVENT_INPUT_KEYPRESS, codePoint, keyCode,
+ Constants.EXTERNAL_KEYBOARD_COORDINATE, Constants.EXTERNAL_KEYBOARD_COORDINATE,
+ FLAG_NONE, next);
}
- public static Event createNotHandledEvent() {
- return new Event(EVENT_NOT_HANDLED, NOT_A_CODE_POINT, null);
+ // 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,
+ Constants.EXTERNAL_KEYBOARD_COORDINATE, Constants.EXTERNAL_KEYBOARD_COORDINATE,
+ FLAG_DEAD, next);
}
- public boolean isCommittable() {
- return EVENT_COMMITTABLE == mType;
+ /**
+ * Create an input event with nothing but a code point. This is the most basic possible input
+ * event; it contains no information on many things the IME requires to function correctly,
+ * so avoid using it unless really nothing is known about this input.
+ * @param codePoint the code point.
+ * @return an event for this code point.
+ */
+ 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,
+ Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, FLAG_NONE, null /* next */);
+ }
+
+ /**
+ * Creates an input event with a code point and x, y coordinates. This is typically used when
+ * resuming a previously-typed word, when the coordinates are still known.
+ * @param codePoint the code point to input.
+ * @param x the X coordinate.
+ * @param y the Y coordinate.
+ * @return an event for this code point and coordinates.
+ */
+ 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, FLAG_NONE,
+ null /* next */);
}
+ public static Event createNotHandledEvent() {
+ return new Event(EVENT_NOT_HANDLED, NOT_A_CODE_POINT, NOT_A_KEY_CODE,
+ Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, FLAG_NONE, null);
+ }
+
+ // Returns whether this event is for a dead character. @see {@link #FLAG_DEAD}
public boolean isDead() {
- return EVENT_DEAD == mType;
+ return 0 != (FLAG_DEAD & mFlags);
+ }
+
+ // Returns whether this is a fake key press from the suggestion strip. This happens with
+ // punctuation signs selected from the suggestion strip.
+ public boolean isSuggestionStripPress() {
+ 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;
}
}
diff --git a/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java b/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java
index 720d07433..da6780e08 100644
--- a/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java
+++ b/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java
@@ -47,27 +47,33 @@ public class HardwareKeyboardEventDecoder implements HardwareEventDecoder {
// the key for 'A' or Space, but also Backspace or Ctrl or Caps Lock.
final int keyCode = keyEvent.getKeyCode();
if (KeyEvent.KEYCODE_DEL == keyCode) {
- return Event.createCommittableEvent(Constants.CODE_DELETE, null /* next */);
+ return Event.createHardwareKeypressEvent(Event.NOT_A_CODE_POINT, Constants.CODE_DELETE,
+ null /* next */);
}
if (keyEvent.isPrintingKey() || KeyEvent.KEYCODE_SPACE == keyCode
|| KeyEvent.KEYCODE_ENTER == keyCode) {
if (0 != (codePointAndFlags & KeyCharacterMap.COMBINING_ACCENT)) {
// A dead key.
return Event.createDeadEvent(
- codePointAndFlags & KeyCharacterMap.COMBINING_ACCENT_MASK, null /* next */);
+ codePointAndFlags & KeyCharacterMap.COMBINING_ACCENT_MASK, keyCode,
+ null /* next */);
}
if (KeyEvent.KEYCODE_ENTER == keyCode) {
// The Enter key. If the Shift key is not being pressed, this should send a
// CODE_ENTER to trigger the action if any, or a carriage return otherwise. If the
// Shift key is being pressed, this should send a CODE_SHIFT_ENTER and let
// Latin IME decide what to do with it.
- return Event.createCommittableEvent(keyEvent.isShiftPressed()
- ? Constants.CODE_SHIFT_ENTER : Constants.CODE_ENTER,
- null /* next */);
+ if (keyEvent.isShiftPressed()) {
+ return Event.createHardwareKeypressEvent(Event.NOT_A_CODE_POINT,
+ Constants.CODE_SHIFT_ENTER, null /* next */);
+ } else {
+ return Event.createHardwareKeypressEvent(Constants.CODE_ENTER, keyCode,
+ null /* next */);
+ }
}
- // If not Enter, then we have a committable character. This should be committed
- // right away, taking into account the current state.
- return Event.createCommittableEvent(codePointAndFlags, null /* next */);
+ // If not Enter, then this is just a regular keypress event for a normal character
+ // that can be committed right away, taking into account the current state.
+ return Event.createHardwareKeypressEvent(keyCode, codePointAndFlags, null /* next */);
}
return Event.createNotHandledEvent();
}
diff --git a/java/src/com/android/inputmethod/event/InputTransaction.java b/java/src/com/android/inputmethod/event/InputTransaction.java
index 3f709a674..2e9014f20 100644
--- a/java/src/com/android/inputmethod/event/InputTransaction.java
+++ b/java/src/com/android/inputmethod/event/InputTransaction.java
@@ -33,11 +33,7 @@ public class InputTransaction {
// Initial conditions
public final SettingsValues mSettingsValues;
- // If the key inserts a code point, mKeyCode is always equal to the code points. Otherwise,
- // it's always a code that may not be a code point, typically a negative number.
- public final int mKeyCode;
- public final int mX; // Pressed x-coordinate, or one of Constants.*_COORDINATE
- public final int mY; // Pressed y-coordinate, or one of Constants.*_COORDINATE
+ public final Event mEvent;
public final long mTimestamp;
public final int mSpaceState;
public final int mShiftState;
@@ -45,13 +41,10 @@ public class InputTransaction {
// Outputs
private int mRequiredShiftUpdate = SHIFT_NO_UPDATE;
- public InputTransaction(final SettingsValues settingsValues, final int keyCode,
- final int x, final int y, final long timestamp, final int spaceState,
- final int shiftState) {
+ public InputTransaction(final SettingsValues settingsValues, final Event event,
+ final long timestamp, final int spaceState, final int shiftState) {
mSettingsValues = settingsValues;
- mKeyCode = keyCode;
- mX = x;
- mY = y;
+ mEvent = event;
mTimestamp = timestamp;
mSpaceState = spaceState;
mShiftState = shiftState;
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
index 79d088f2e..6c9b5adc3 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
@@ -34,29 +34,47 @@ public final class KeyboardIconsSet {
public static final int ICON_UNDEFINED = 0;
private static final int ATTR_UNDEFINED = 0;
+ private static final String NAME_UNDEFINED = "undefined";
+ public static final String NAME_SHIFT_KEY = "shift_key";
+ public static final String NAME_SHIFT_KEY_SHIFTED = "shift_key_shifted";
+ public static final String NAME_DELETE_KEY = "delete_key";
+ public static final String NAME_SETTINGS_KEY = "settings_key";
+ public static final String NAME_SPACE_KEY = "space_key";
+ public static final String NAME_SPACE_KEY_FOR_NUMBER_LAYOUT = "space_key_for_number_layout";
+ public static final String NAME_ENTER_KEY = "enter_key";
+ public static final String NAME_SEARCH_KEY = "search_key";
+ public static final String NAME_TAB_KEY = "tab_key";
+ public static final String NANE_TAB_KEY_PREVIEW = "tab_key_preview";
+ public static final String NAME_SHORTCUT_KEY = "shortcut_key";
+ public static final String NAME_SHORTCUT_KEY_DISABLED = "shortcut_key_disabled";
+ public static final String NAME_LANGUAGE_SWITCH_KEY = "language_switch_key";
+ public static final String NAME_ZWNJ_KEY = "zwnj_key";
+ public static final String NAME_ZWJ_KEY = "zwj_key";
+ public static final String NAME_EMOJI_KEY = "emoji_key";
+
private static final SparseIntArray ATTR_ID_TO_ICON_ID = new SparseIntArray();
// Icon name to icon id map.
private static final HashMap<String, Integer> sNameToIdsMap = CollectionUtils.newHashMap();
private static final Object[] NAMES_AND_ATTR_IDS = {
- "undefined", ATTR_UNDEFINED,
- "shift_key", R.styleable.Keyboard_iconShiftKey,
- "delete_key", R.styleable.Keyboard_iconDeleteKey,
- "settings_key", R.styleable.Keyboard_iconSettingsKey,
- "space_key", R.styleable.Keyboard_iconSpaceKey,
- "enter_key", R.styleable.Keyboard_iconEnterKey,
- "search_key", R.styleable.Keyboard_iconSearchKey,
- "tab_key", R.styleable.Keyboard_iconTabKey,
- "shortcut_key", R.styleable.Keyboard_iconShortcutKey,
- "space_key_for_number_layout", R.styleable.Keyboard_iconSpaceKeyForNumberLayout,
- "shift_key_shifted", R.styleable.Keyboard_iconShiftKeyShifted,
- "shortcut_key_disabled", R.styleable.Keyboard_iconShortcutKeyDisabled,
- "tab_key_preview", R.styleable.Keyboard_iconTabKeyPreview,
- "language_switch_key", R.styleable.Keyboard_iconLanguageSwitchKey,
- "zwnj_key", R.styleable.Keyboard_iconZwnjKey,
- "zwj_key", R.styleable.Keyboard_iconZwjKey,
- "emoji_key", R.styleable.Keyboard_iconEmojiKey,
+ NAME_UNDEFINED, ATTR_UNDEFINED,
+ NAME_SHIFT_KEY, R.styleable.Keyboard_iconShiftKey,
+ NAME_DELETE_KEY, R.styleable.Keyboard_iconDeleteKey,
+ NAME_SETTINGS_KEY, R.styleable.Keyboard_iconSettingsKey,
+ NAME_SPACE_KEY, R.styleable.Keyboard_iconSpaceKey,
+ NAME_ENTER_KEY, R.styleable.Keyboard_iconEnterKey,
+ NAME_SEARCH_KEY, R.styleable.Keyboard_iconSearchKey,
+ NAME_TAB_KEY, R.styleable.Keyboard_iconTabKey,
+ NAME_SHORTCUT_KEY, R.styleable.Keyboard_iconShortcutKey,
+ NAME_SPACE_KEY_FOR_NUMBER_LAYOUT, R.styleable.Keyboard_iconSpaceKeyForNumberLayout,
+ NAME_SHIFT_KEY_SHIFTED, R.styleable.Keyboard_iconShiftKeyShifted,
+ NAME_SHORTCUT_KEY_DISABLED, R.styleable.Keyboard_iconShortcutKeyDisabled,
+ NANE_TAB_KEY_PREVIEW, R.styleable.Keyboard_iconTabKeyPreview,
+ NAME_LANGUAGE_SWITCH_KEY, R.styleable.Keyboard_iconLanguageSwitchKey,
+ NAME_ZWNJ_KEY, R.styleable.Keyboard_iconZwnjKey,
+ NAME_ZWJ_KEY, R.styleable.Keyboard_iconZwjKey,
+ NAME_EMOJI_KEY, R.styleable.Keyboard_iconEmojiKey,
};
private static int NUM_ICONS = NAMES_AND_ATTR_IDS.length / 2;
diff --git a/java/src/com/android/inputmethod/latin/LastComposedWord.java b/java/src/com/android/inputmethod/latin/LastComposedWord.java
index 8546cebd5..2a16ab5ab 100644
--- a/java/src/com/android/inputmethod/latin/LastComposedWord.java
+++ b/java/src/com/android/inputmethod/latin/LastComposedWord.java
@@ -18,6 +18,10 @@ package com.android.inputmethod.latin;
import android.text.TextUtils;
+import com.android.inputmethod.event.Event;
+
+import java.util.ArrayList;
+
/**
* This class encapsulates data about a word previously composed, but that has been
* committed already. This is used for resuming suggestion, and cancel auto-correction.
@@ -41,6 +45,7 @@ public final class LastComposedWord {
public static final String NOT_A_SEPARATOR = "";
public final int[] mPrimaryKeyCodes;
+ public final ArrayList<Event> mEvents;
public final String mTypedWord;
public final CharSequence mCommittedWord;
public final String mSeparatorString;
@@ -52,19 +57,21 @@ public final class LastComposedWord {
private boolean mActive;
public static final LastComposedWord NOT_A_COMPOSED_WORD =
- new LastComposedWord(null, null, "", "", NOT_A_SEPARATOR, null,
- WordComposer.CAPS_MODE_OFF);
+ new LastComposedWord(null, new ArrayList<Event>(), null, "", "",
+ NOT_A_SEPARATOR, null, WordComposer.CAPS_MODE_OFF);
// Warning: this is using the passed objects as is and fully expects them to be
// immutable. Do not fiddle with their contents after you passed them to this constructor.
- public LastComposedWord(final int[] primaryKeyCodes, final InputPointers inputPointers,
- final String typedWord, final CharSequence committedWord, final String separatorString,
+ public LastComposedWord(final int[] primaryKeyCodes, final ArrayList<Event> events,
+ final InputPointers inputPointers, final String typedWord,
+ final CharSequence committedWord, final String separatorString,
final String prevWord, final int capitalizedMode) {
mPrimaryKeyCodes = primaryKeyCodes;
if (inputPointers != null) {
mInputPointers.copy(inputPointers);
}
mTypedWord = typedWord;
+ mEvents = new ArrayList<Event>(events);
mCommittedWord = committedWord;
mSeparatorString = separatorString;
mActive = true;
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index a9e548060..222e73529 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -59,6 +59,7 @@ import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy;
import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.compat.InputMethodServiceCompatUtils;
import com.android.inputmethod.dictionarypack.DictionaryPackConstants;
+import com.android.inputmethod.event.Event;
import com.android.inputmethod.event.InputTransaction;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.KeyboardActionListener;
@@ -1266,8 +1267,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mSubtypeSwitcher.switchToShortcutIME(this);
// Still call the *#onCodeInput methods for readability.
}
+ final Event event = createSoftwareKeypressEvent(codeToSend, keyX, keyY);
final InputTransaction completeInputTransaction =
- mInputLogic.onCodeInput(mSettings.getCurrent(), codeToSend, keyX, keyY,
+ mInputLogic.onCodeInput(mSettings.getCurrent(), event,
mKeyboardSwitcher.getKeyboardShiftMode(), mHandler);
switch (completeInputTransaction.getRequiredShiftUpdate()) {
case InputTransaction.SHIFT_UPDATE_LATER:
@@ -1281,6 +1283,22 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mKeyboardSwitcher.onCodeInput(codePoint);
}
+ // A helper method to split the code point and the key code. Ultimately, they should not be
+ // squashed into the same variable, and this method should be removed.
+ private static Event createSoftwareKeypressEvent(final int keyCodeOrCodePoint, final int keyX,
+ final int keyY) {
+ final int keyCode;
+ final int codePoint;
+ if (keyCodeOrCodePoint <= 0) {
+ keyCode = keyCodeOrCodePoint;
+ codePoint = Event.NOT_A_CODE_POINT;
+ } else {
+ keyCode = Event.NOT_A_KEY_CODE;
+ codePoint = keyCodeOrCodePoint;
+ }
+ return Event.createSoftwareKeypressEvent(codePoint, keyCode, keyX, keyY);
+ }
+
// Called from PointerTracker through the KeyboardActionListener interface
@Override
public void onTextInput(final String rawText) {
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index 125976932..2ac11aa29 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -16,10 +16,14 @@
package com.android.inputmethod.latin;
+import com.android.inputmethod.event.Event;
+import com.android.inputmethod.latin.utils.CollectionUtils;
import com.android.inputmethod.latin.utils.CoordinateUtils;
import com.android.inputmethod.latin.utils.StringUtils;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
/**
* A place to store the currently composing word with information such as adjacent key codes as well
@@ -41,6 +45,8 @@ public final class WordComposer {
// and mCodePointSize can go past that. If mCodePointSize is greater than MAX_WORD_LENGTH,
// this just does not contain the associated code points past MAX_WORD_LENGTH.
private int[] mPrimaryKeyCodes;
+ // The list of events that served to compose this string.
+ private final ArrayList<Event> mEvents;
private final InputPointers mInputPointers = new InputPointers(MAX_WORD_LENGTH);
// This is the typed word, as a StringBuilder. This has the same contents as mPrimaryKeyCodes
// but under a StringBuilder representation for ease of use, depending on what is more useful
@@ -82,6 +88,7 @@ public final class WordComposer {
public WordComposer() {
mPrimaryKeyCodes = new int[MAX_WORD_LENGTH];
+ mEvents = CollectionUtils.newArrayList();
mTypedWord = new StringBuilder(MAX_WORD_LENGTH);
mAutoCorrection = null;
mTrailingSingleQuotesCount = 0;
@@ -95,6 +102,7 @@ public final class WordComposer {
public WordComposer(final WordComposer source) {
mPrimaryKeyCodes = Arrays.copyOf(source.mPrimaryKeyCodes, source.mPrimaryKeyCodes.length);
+ mEvents = new ArrayList<Event>(source.mEvents);
mTypedWord = new StringBuilder(source.mTypedWord);
mInputPointers.copy(source.mInputPointers);
mCapsCount = source.mCapsCount;
@@ -115,6 +123,7 @@ public final class WordComposer {
*/
public void reset() {
mTypedWord.setLength(0);
+ mEvents.clear();
mAutoCorrection = null;
mCapsCount = 0;
mDigitsCount = 0;
@@ -170,11 +179,16 @@ public final class WordComposer {
}
/**
- * Add a new keystroke, with the pressed key's code point with the touch point coordinates.
+ * Add a new event for a key stroke, with the pressed key's code point with the touch point
+ * coordinates.
*/
- public void add(final int primaryCode, final int keyX, final int keyY) {
+ public void add(final Event event) {
+ final int primaryCode = event.mCodePoint;
+ final int keyX = event.mX;
+ final int keyY = event.mY;
final int newIndex = size();
mTypedWord.appendCodePoint(primaryCode);
+ mEvents.add(event);
refreshSize();
mCursorPositionWithinWord = mCodePointSize;
if (newIndex < MAX_WORD_LENGTH) {
@@ -202,6 +216,7 @@ public final class WordComposer {
public void setCursorPositionWithinWord(final int posWithinWord) {
mCursorPositionWithinWord = posWithinWord;
+ // TODO: compute where that puts us inside the events
}
public boolean isCursorFrontOrMiddleOfComposingWord() {
@@ -268,7 +283,7 @@ public final class WordComposer {
final int codePoint = Character.codePointAt(word, i);
// We don't want to override the batch input points that are held in mInputPointers
// (See {@link #add(int,int,int)}).
- add(codePoint, Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
+ add(Event.createEventForCodePointFromUnknownSource(codePoint));
}
}
@@ -285,8 +300,9 @@ public final class WordComposer {
reset();
final int length = codePoints.length;
for (int i = 0; i < length; ++i) {
- add(codePoints[i], CoordinateUtils.xFromArray(coordinates, i),
- CoordinateUtils.yFromArray(coordinates, i));
+ add(Event.createEventForCodePointFromAlreadyTypedText(codePoints[i],
+ CoordinateUtils.xFromArray(coordinates, i),
+ CoordinateUtils.yFromArray(coordinates, i)));
}
mIsResumed = true;
mPreviousWordForSuggestion = null == previousWord ? null : previousWord.toString();
@@ -305,6 +321,8 @@ public final class WordComposer {
"In WordComposer: mCodes and mTypedWords have non-matching lengths");
}
final int lastChar = mTypedWord.codePointBefore(stringBuilderLength);
+ // TODO: with events and composition, this is absolutely not necessarily true.
+ mEvents.remove(mEvents.size() - 1);
if (Character.isSupplementaryCodePoint(lastChar)) {
mTypedWord.delete(stringBuilderLength - 2, stringBuilderLength);
} else {
@@ -445,7 +463,7 @@ public final class WordComposer {
// the last composed word to ensure this does not happen.
final int[] primaryKeyCodes = mPrimaryKeyCodes;
mPrimaryKeyCodes = new int[MAX_WORD_LENGTH];
- final LastComposedWord lastComposedWord = new LastComposedWord(primaryKeyCodes,
+ final LastComposedWord lastComposedWord = new LastComposedWord(primaryKeyCodes, mEvents,
mInputPointers, mTypedWord.toString(), committedWord, separatorString,
prevWord, mCapitalizedMode);
mInputPointers.reset();
@@ -458,6 +476,7 @@ public final class WordComposer {
mIsBatchMode = false;
mPreviousWordForSuggestion = committedWord.toString();
mTypedWord.setLength(0);
+ mEvents.clear();
mCodePointSize = 0;
mTrailingSingleQuotesCount = 0;
mIsFirstCharCapitalized = false;
@@ -480,6 +499,8 @@ public final class WordComposer {
public void resumeSuggestionOnLastComposedWord(final LastComposedWord lastComposedWord,
final String previousWord) {
mPrimaryKeyCodes = lastComposedWord.mPrimaryKeyCodes;
+ mEvents.clear();
+ Collections.copy(mEvents, lastComposedWord.mEvents);
mInputPointers.set(lastComposedWord.mInputPointers);
mTypedWord.setLength(0);
mTypedWord.append(lastComposedWord.mTypedWord);
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index dd9d6e8a9..cb55aa06c 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -27,6 +27,7 @@ import android.view.inputmethod.CorrectionInfo;
import android.view.inputmethod.EditorInfo;
import com.android.inputmethod.compat.SuggestionSpanUtils;
+import com.android.inputmethod.event.Event;
import com.android.inputmethod.event.EventInterpreter;
import com.android.inputmethod.event.InputTransaction;
import com.android.inputmethod.keyboard.KeyboardSwitcher;
@@ -205,9 +206,9 @@ public final class InputLogic {
LatinImeLogger.logOnManualSuggestion("", suggestion, index, suggestedWords);
// Rely on onCodeInput to do the complicated swapping/stripping logic consistently.
final int primaryCode = suggestion.charAt(0);
- onCodeInput(settingsValues, primaryCode,
- Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE,
- keyboardSwitcher.getKeyboardShiftMode(), handler);
+ final Event event = Event.createSoftwareKeypressEvent(primaryCode, Event.NOT_A_KEY_CODE,
+ Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE);
+ onCodeInput(settingsValues, event, keyboardSwitcher.getKeyboardShiftMode(), handler);
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.latinIME_punctuationSuggestion(index, suggestion,
false /* isBatchMode */, suggestedWords.mIsPrediction);
@@ -354,25 +355,26 @@ public final class InputLogic {
* the entry point for gesture input; see the onBatchInput* family of functions for this.
*
* @param settingsValues the current settings values.
- * @param code the code to handle. It may be a code point, or an internal key code.
- * @param x the x-coordinate where the user pressed the key, or NOT_A_COORDINATE.
- * @param y the y-coordinate where the user pressed the key, or NOT_A_COORDINATE.
+ * @param event the event to handle.
* @param keyboardShiftMode the current shift mode of the keyboard, as returned by
* {@link com.android.inputmethod.keyboard.KeyboardSwitcher#getKeyboardShiftMode()}
* @return the complete transaction object
*/
- public InputTransaction onCodeInput(final SettingsValues settingsValues, final int code,
- final int x, final int y, final int keyboardShiftMode,
+ public InputTransaction onCodeInput(final SettingsValues settingsValues, final Event event,
+ final int keyboardShiftMode,
// TODO: remove this argument
final LatinIME.UIHandler handler) {
- final InputTransaction inputTransaction = new InputTransaction(settingsValues, code, x, y,
+ // TODO: rework the following to not squash the keycode and the code point into the same
+ // var because it's confusing. Instead the switch() should handle this in a readable manner.
+ final int code =
+ Event.NOT_A_CODE_POINT == event.mCodePoint ? event.mKeyCode : event.mCodePoint;
+ final InputTransaction inputTransaction = new InputTransaction(settingsValues, event,
SystemClock.uptimeMillis(), mSpaceState,
getActualCapsMode(settingsValues, keyboardShiftMode));
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
- ResearchLogger.latinIME_onCodeInput(inputTransaction.mKeyCode,
- inputTransaction.mX, inputTransaction.mY);
+ ResearchLogger.latinIME_onCodeInput(code, event.mX, event.mY);
}
- if (inputTransaction.mKeyCode != Constants.CODE_DELETE
+ if (event.mKeyCode != Constants.CODE_DELETE
|| inputTransaction.mTimestamp > mLastKeyTime + Constants.LONG_PRESS_MILLISECONDS) {
mDeleteCount = 0;
}
@@ -383,97 +385,104 @@ public final class InputLogic {
}
// TODO: Consolidate the double-space period timer, mLastKeyTime, and the space state.
- if (inputTransaction.mKeyCode != Constants.CODE_SPACE) {
+ if (event.mCodePoint != Constants.CODE_SPACE) {
handler.cancelDoubleSpacePeriodTimer();
}
boolean didAutoCorrect = false;
- switch (inputTransaction.mKeyCode) {
- case Constants.CODE_DELETE:
- handleBackspace(inputTransaction, handler);
- LatinImeLogger.logOnDelete(inputTransaction.mX, inputTransaction.mY);
- break;
- case Constants.CODE_SHIFT:
- performRecapitalization(inputTransaction.mSettingsValues);
- inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
- break;
- case Constants.CODE_CAPSLOCK:
- // Note: Changing keyboard to shift lock state is handled in
- // {@link KeyboardSwitcher#onCodeInput(int)}.
- break;
- case Constants.CODE_SYMBOL_SHIFT:
- // Note: Calling back to the keyboard on the symbol Shift key is handled in
- // {@link #onPressKey(int,int,boolean)} and {@link #onReleaseKey(int,boolean)}.
- break;
- case Constants.CODE_SWITCH_ALPHA_SYMBOL:
- // Note: Calling back to the keyboard on symbol key is handled in
- // {@link #onPressKey(int,int,boolean)} and {@link #onReleaseKey(int,boolean)}.
- break;
- case Constants.CODE_SETTINGS:
- onSettingsKeyPressed();
- break;
- case Constants.CODE_SHORTCUT:
- // We need to switch to the shortcut IME. This is handled by LatinIME since the
- // input logic has no business with IME switching.
- break;
- case Constants.CODE_ACTION_NEXT:
- performEditorAction(EditorInfo.IME_ACTION_NEXT);
- break;
- case Constants.CODE_ACTION_PREVIOUS:
- performEditorAction(EditorInfo.IME_ACTION_PREVIOUS);
- break;
- case Constants.CODE_LANGUAGE_SWITCH:
- handleLanguageSwitchKey();
- break;
- case Constants.CODE_EMOJI:
- // Note: Switching emoji keyboard is being handled in
- // {@link KeyboardState#onCodeInput(int,int)}.
- break;
- case Constants.CODE_ENTER:
- final EditorInfo editorInfo = getCurrentInputEditorInfo();
- final int imeOptionsActionId =
- InputTypeUtils.getImeOptionsActionIdFromEditorInfo(editorInfo);
- if (InputTypeUtils.IME_ACTION_CUSTOM_LABEL == imeOptionsActionId) {
- // Either we have an actionLabel and we should performEditorAction with actionId
- // regardless of its value.
- performEditorAction(editorInfo.actionId);
- } else if (EditorInfo.IME_ACTION_NONE != imeOptionsActionId) {
- // We didn't have an actionLabel, but we had another action to execute.
- // EditorInfo.IME_ACTION_NONE explicitly means no action. In contrast,
- // EditorInfo.IME_ACTION_UNSPECIFIED is the default value for an action, so it
- // means there should be an action and the app didn't bother to set a specific
- // code for it - presumably it only handles one. It does not have to be treated
- // in any specific way: anything that is not IME_ACTION_NONE should be sent to
- // performEditorAction.
- performEditorAction(imeOptionsActionId);
- } else {
- // No action label, and the action from imeOptions is NONE: this is a regular
- // enter key that should input a carriage return.
+ if (Event.NOT_A_KEY_CODE != event.mKeyCode) {
+ // A special key, like delete, shift, emoji, or the settings key.
+ switch (event.mKeyCode) {
+ case Constants.CODE_DELETE:
+ handleBackspace(inputTransaction, handler);
+ LatinImeLogger.logOnDelete(event.mX, event.mY);
+ break;
+ case Constants.CODE_SHIFT:
+ performRecapitalization(inputTransaction.mSettingsValues);
+ inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
+ break;
+ case Constants.CODE_CAPSLOCK:
+ // Note: Changing keyboard to shift lock state is handled in
+ // {@link KeyboardSwitcher#onCodeInput(int)}.
+ break;
+ case Constants.CODE_SYMBOL_SHIFT:
+ // Note: Calling back to the keyboard on the symbol Shift key is handled in
+ // {@link #onPressKey(int,int,boolean)} and {@link #onReleaseKey(int,boolean)}.
+ break;
+ case Constants.CODE_SWITCH_ALPHA_SYMBOL:
+ // Note: Calling back to the keyboard on symbol key is handled in
+ // {@link #onPressKey(int,int,boolean)} and {@link #onReleaseKey(int,boolean)}.
+ break;
+ case Constants.CODE_SETTINGS:
+ onSettingsKeyPressed();
+ break;
+ case Constants.CODE_SHORTCUT:
+ // We need to switch to the shortcut IME. This is handled by LatinIME since the
+ // input logic has no business with IME switching.
+ break;
+ case Constants.CODE_ACTION_NEXT:
+ performEditorAction(EditorInfo.IME_ACTION_NEXT);
+ break;
+ case Constants.CODE_ACTION_PREVIOUS:
+ performEditorAction(EditorInfo.IME_ACTION_PREVIOUS);
+ break;
+ case Constants.CODE_LANGUAGE_SWITCH:
+ handleLanguageSwitchKey();
+ break;
+ case Constants.CODE_EMOJI:
+ // Note: Switching emoji keyboard is being handled in
+ // {@link KeyboardState#onCodeInput(int,int)}.
+ break;
+ case Constants.CODE_ALPHA_FROM_EMOJI:
+ // Note: Switching back from Emoji keyboard to the main keyboard is being
+ // handled in {@link KeyboardState#onCodeInput(int,int)}.
+ break;
+ case Constants.CODE_SHIFT_ENTER:
+ // TODO: remove this object
+ final InputTransaction tmpTransaction = new InputTransaction(
+ inputTransaction.mSettingsValues, inputTransaction.mEvent,
+ inputTransaction.mTimestamp, inputTransaction.mSpaceState,
+ inputTransaction.mShiftState);
+ didAutoCorrect = handleNonSpecialCharacter(tmpTransaction, handler);
+ break;
+ default:
+ throw new RuntimeException("Unknown key code : " + event.mKeyCode);
+ }
+ } else {
+ switch (event.mCodePoint) {
+ case Constants.CODE_ENTER:
+ final EditorInfo editorInfo = getCurrentInputEditorInfo();
+ final int imeOptionsActionId =
+ InputTypeUtils.getImeOptionsActionIdFromEditorInfo(editorInfo);
+ if (InputTypeUtils.IME_ACTION_CUSTOM_LABEL == imeOptionsActionId) {
+ // Either we have an actionLabel and we should performEditorAction with
+ // actionId regardless of its value.
+ performEditorAction(editorInfo.actionId);
+ } else if (EditorInfo.IME_ACTION_NONE != imeOptionsActionId) {
+ // We didn't have an actionLabel, but we had another action to execute.
+ // EditorInfo.IME_ACTION_NONE explicitly means no action. In contrast,
+ // EditorInfo.IME_ACTION_UNSPECIFIED is the default value for an action, so it
+ // means there should be an action and the app didn't bother to set a specific
+ // code for it - presumably it only handles one. It does not have to be treated
+ // in any specific way: anything that is not IME_ACTION_NONE should be sent to
+ // performEditorAction.
+ performEditorAction(imeOptionsActionId);
+ } else {
+ // No action label, and the action from imeOptions is NONE: this is a regular
+ // enter key that should input a carriage return.
+ didAutoCorrect = handleNonSpecialCharacter(inputTransaction, handler);
+ }
+ break;
+ default:
didAutoCorrect = handleNonSpecialCharacter(inputTransaction, handler);
+ break;
}
- break;
- case Constants.CODE_SHIFT_ENTER:
- // TODO: remove this object
- final InputTransaction tmpTransaction = new InputTransaction(
- inputTransaction.mSettingsValues, inputTransaction.mKeyCode,
- inputTransaction.mX, inputTransaction.mY, inputTransaction.mTimestamp,
- inputTransaction.mSpaceState, inputTransaction.mShiftState);
- didAutoCorrect = handleNonSpecialCharacter(tmpTransaction, handler);
- break;
- case Constants.CODE_ALPHA_FROM_EMOJI:
- // Note: Switching back from Emoji keyboard to the main keyboard is being handled in
- // {@link KeyboardState#onCodeInput(int,int)}.
- break;
- default:
- didAutoCorrect = handleNonSpecialCharacter(inputTransaction, handler);
- break;
- }
- // Reset after any single keystroke, except shift, capslock, and symbol-shift
- if (!didAutoCorrect && inputTransaction.mKeyCode != Constants.CODE_SHIFT
- && inputTransaction.mKeyCode != Constants.CODE_CAPSLOCK
- && inputTransaction.mKeyCode != Constants.CODE_SWITCH_ALPHA_SYMBOL)
+ }
+ if (!didAutoCorrect && event.mKeyCode != Constants.CODE_SHIFT
+ && event.mKeyCode != Constants.CODE_CAPSLOCK
+ && event.mKeyCode != Constants.CODE_SWITCH_ALPHA_SYMBOL)
mLastComposedWord.deactivate();
- if (Constants.CODE_DELETE != inputTransaction.mKeyCode) {
+ if (Constants.CODE_DELETE != event.mKeyCode) {
mEnteredText = null;
}
mConnection.endBatchEdit();
@@ -627,15 +636,16 @@ public final class InputLogic {
private boolean handleNonSpecialCharacter(final InputTransaction inputTransaction,
// TODO: remove this argument
final LatinIME.UIHandler handler) {
+ final int codePoint = inputTransaction.mEvent.mCodePoint;
mSpaceState = SpaceState.NONE;
final boolean didAutoCorrect;
- if (inputTransaction.mSettingsValues.isWordSeparator(inputTransaction.mKeyCode)
- || Character.getType(inputTransaction.mKeyCode) == Character.OTHER_SYMBOL) {
+ if (inputTransaction.mSettingsValues.isWordSeparator(codePoint)
+ || Character.getType(codePoint) == Character.OTHER_SYMBOL) {
didAutoCorrect = handleSeparator(inputTransaction,
- Constants.SUGGESTION_STRIP_COORDINATE == inputTransaction.mX, handler);
+ inputTransaction.mEvent.isSuggestionStripPress(), handler);
if (inputTransaction.mSettingsValues.mIsInternal) {
- LatinImeLoggerUtils.onSeparator((char)inputTransaction.mKeyCode,
- inputTransaction.mX, inputTransaction.mY);
+ LatinImeLoggerUtils.onSeparator((char)codePoint,
+ inputTransaction.mEvent.mX, inputTransaction.mEvent.mY);
}
} else {
didAutoCorrect = false;
@@ -669,6 +679,7 @@ public final class InputLogic {
final InputTransaction inputTransaction,
// TODO: Remove this argument
final LatinIME.UIHandler handler) {
+ final int codePoint = inputTransaction.mEvent.mCodePoint;
// TODO: refactor this method to stop flipping isComposingWord around all the time, and
// make it shorter (possibly cut into several pieces). Also factor handleNonSpecialCharacter
// which has the same name as other handle* methods but is not the same.
@@ -677,7 +688,7 @@ public final class InputLogic {
// TODO: remove isWordConnector() and use isUsuallyFollowedBySpace() instead.
// See onStartBatchInput() to see how to do it.
if (SpaceState.PHANTOM == inputTransaction.mSpaceState
- && !settingsValues.isWordConnector(inputTransaction.mKeyCode)) {
+ && !settingsValues.isWordConnector(codePoint)) {
if (isComposingWord) {
// Sanity check
throw new RuntimeException("Should not be composing here");
@@ -699,7 +710,7 @@ public final class InputLogic {
if (!isComposingWord
// We only start composing if this is a word code point. Essentially that means it's a
// a letter or a word connector.
- && settingsValues.isWordCodePoint(inputTransaction.mKeyCode)
+ && settingsValues.isWordCodePoint(codePoint)
// We never go into composing state if suggestions are not requested.
&& settingsValues.isSuggestionsRequested() &&
// In languages with spaces, we only start composing a word when we are not already
@@ -710,8 +721,8 @@ public final class InputLogic {
// the character is a single quote or a dash. The idea here is, single quote and dash
// are not separators and they should be treated as normal characters, except in the
// first position where they should not start composing a word.
- isComposingWord = (Constants.CODE_SINGLE_QUOTE != inputTransaction.mKeyCode
- && Constants.CODE_DASH != inputTransaction.mKeyCode);
+ isComposingWord = (Constants.CODE_SINGLE_QUOTE != codePoint
+ && Constants.CODE_DASH != codePoint);
// Here we don't need to reset the last composed word. It will be reset
// when we commit this one, if we ever do; if on the other hand we backspace
// it entirely and resume suggestions on the previous word, we'd like to still
@@ -719,7 +730,7 @@ public final class InputLogic {
resetComposingState(false /* alsoResetLastComposedWord */);
}
if (isComposingWord) {
- mWordComposer.add(inputTransaction.mKeyCode, inputTransaction.mX, inputTransaction.mY);
+ mWordComposer.add(inputTransaction.mEvent);
// If it's the first letter, make note of auto-caps state
if (mWordComposer.size() == 1) {
// We pass 1 to getPreviousWordForSuggestion because we were not composing a word
@@ -732,9 +743,9 @@ public final class InputLogic {
mWordComposer.getTypedWord()), 1);
} else {
final boolean swapWeakSpace = maybeStripSpace(inputTransaction,
- Constants.SUGGESTION_STRIP_COORDINATE == inputTransaction.mX);
+ inputTransaction.mEvent.isSuggestionStripPress());
- sendKeyCodePoint(settingsValues, inputTransaction.mKeyCode);
+ sendKeyCodePoint(settingsValues, codePoint);
if (swapWeakSpace) {
swapSwapperAndSpace(inputTransaction);
@@ -745,8 +756,8 @@ public final class InputLogic {
}
handler.postUpdateSuggestionStrip();
if (settingsValues.mIsInternal) {
- LatinImeLoggerUtils.onNonSeparator((char)inputTransaction.mKeyCode, inputTransaction.mX,
- inputTransaction.mY);
+ LatinImeLoggerUtils.onNonSeparator((char)codePoint, inputTransaction.mEvent.mX,
+ inputTransaction.mEvent.mY);
}
}
@@ -760,9 +771,10 @@ public final class InputLogic {
final boolean isFromSuggestionStrip,
// TODO: remove this argument
final LatinIME.UIHandler handler) {
+ final int codePoint = inputTransaction.mEvent.mCodePoint;
boolean didAutoCorrect = false;
// We avoid sending spaces in languages without spaces if we were composing.
- final boolean shouldAvoidSendingCode = Constants.CODE_SPACE == inputTransaction.mKeyCode
+ final boolean shouldAvoidSendingCode = Constants.CODE_SPACE == codePoint
&& !inputTransaction.mSettingsValues.mSpacingAndPunctuations
.mCurrentLanguageHasSpaces
&& mWordComposer.isComposingWord();
@@ -776,46 +788,44 @@ public final class InputLogic {
if (mWordComposer.isComposingWord()) {
if (inputTransaction.mSettingsValues.mCorrectionEnabled) {
final String separator = shouldAvoidSendingCode ? LastComposedWord.NOT_A_SEPARATOR
- : StringUtils.newSingleCodePointString(inputTransaction.mKeyCode);
+ : StringUtils.newSingleCodePointString(codePoint);
commitCurrentAutoCorrection(inputTransaction.mSettingsValues, separator, handler);
didAutoCorrect = true;
} else {
commitTyped(inputTransaction.mSettingsValues,
- StringUtils.newSingleCodePointString(inputTransaction.mKeyCode));
+ StringUtils.newSingleCodePointString(codePoint));
}
}
final boolean swapWeakSpace = maybeStripSpace(inputTransaction, isFromSuggestionStrip);
- final boolean isInsideDoubleQuoteOrAfterDigit =
- Constants.CODE_DOUBLE_QUOTE == inputTransaction.mKeyCode
+ final boolean isInsideDoubleQuoteOrAfterDigit = Constants.CODE_DOUBLE_QUOTE == codePoint
&& mConnection.isInsideDoubleQuoteOrAfterDigit();
final boolean needsPrecedingSpace;
if (SpaceState.PHANTOM != inputTransaction.mSpaceState) {
needsPrecedingSpace = false;
- } else if (Constants.CODE_DOUBLE_QUOTE == inputTransaction.mKeyCode) {
+ } else if (Constants.CODE_DOUBLE_QUOTE == codePoint) {
// Double quotes behave like they are usually preceded by space iff we are
// not inside a double quote or after a digit.
needsPrecedingSpace = !isInsideDoubleQuoteOrAfterDigit;
} else {
needsPrecedingSpace = inputTransaction.mSettingsValues.isUsuallyPrecededBySpace(
- inputTransaction.mKeyCode);
+ codePoint);
}
if (needsPrecedingSpace) {
promotePhantomSpace(inputTransaction.mSettingsValues);
}
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
- ResearchLogger.latinIME_handleSeparator(inputTransaction.mKeyCode,
- mWordComposer.isComposingWord());
+ ResearchLogger.latinIME_handleSeparator(codePoint, mWordComposer.isComposingWord());
}
if (!shouldAvoidSendingCode) {
- sendKeyCodePoint(inputTransaction.mSettingsValues, inputTransaction.mKeyCode);
+ sendKeyCodePoint(inputTransaction.mSettingsValues, codePoint);
}
- if (Constants.CODE_SPACE == inputTransaction.mKeyCode) {
+ if (Constants.CODE_SPACE == codePoint) {
if (inputTransaction.mSettingsValues.isSuggestionsRequested()) {
if (maybeDoubleSpacePeriod(inputTransaction.mSettingsValues, handler)) {
inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
@@ -832,9 +842,8 @@ public final class InputLogic {
swapSwapperAndSpace(inputTransaction);
mSpaceState = SpaceState.SWAP_PUNCTUATION;
} else if ((SpaceState.PHANTOM == inputTransaction.mSpaceState
- && inputTransaction.mSettingsValues.isUsuallyFollowedBySpace(
- inputTransaction.mKeyCode))
- || (Constants.CODE_DOUBLE_QUOTE == inputTransaction.mKeyCode
+ && inputTransaction.mSettingsValues.isUsuallyFollowedBySpace(codePoint))
+ || (Constants.CODE_DOUBLE_QUOTE == codePoint
&& isInsideDoubleQuoteOrAfterDigit)) {
// If we are in phantom space state, and the user presses a separator, we want to
// stay in phantom space state so that the next keypress has a chance to add the
@@ -1051,7 +1060,8 @@ public final class InputLogic {
*/
private boolean maybeStripSpace(final InputTransaction inputTransaction,
final boolean isFromSuggestionStrip) {
- if (Constants.CODE_ENTER == inputTransaction.mKeyCode &&
+ final int codePoint = inputTransaction.mEvent.mCodePoint;
+ if (Constants.CODE_ENTER == codePoint &&
SpaceState.SWAP_PUNCTUATION == inputTransaction.mSpaceState) {
mConnection.removeTrailingSpace();
return false;
@@ -1059,12 +1069,10 @@ public final class InputLogic {
if ((SpaceState.WEAK == inputTransaction.mSpaceState
|| SpaceState.SWAP_PUNCTUATION == inputTransaction.mSpaceState)
&& isFromSuggestionStrip) {
- if (inputTransaction.mSettingsValues.isUsuallyPrecededBySpace(
- inputTransaction.mKeyCode)) {
+ if (inputTransaction.mSettingsValues.isUsuallyPrecededBySpace(codePoint)) {
return false;
}
- if (inputTransaction.mSettingsValues.isUsuallyFollowedBySpace(
- inputTransaction.mKeyCode)) {
+ if (inputTransaction.mSettingsValues.isUsuallyFollowedBySpace(codePoint)) {
return true;
}
mConnection.removeTrailingSpace();
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
index afa8fe3a8..c26e223c9 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
@@ -511,7 +511,8 @@ final class SuggestionStripLayoutHelper {
final String importantNoticeTitle) {
final TextView titleView = (TextView)importantNoticeStrip.findViewById(
R.id.important_notice_title);
- final int width = stripWidth - titleView.getPaddingLeft() - titleView.getPaddingRight();
+ final int width = titleView.getWidth() - titleView.getPaddingLeft()
+ - titleView.getPaddingRight();
titleView.setTextColor(mColorAutoCorrect);
titleView.setText(importantNoticeTitle);
titleView.setTextScaleX(1.0f); // Reset textScaleX.