aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/event
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android/inputmethod/event')
-rw-r--r--java/src/com/android/inputmethod/event/Combiner.java3
-rw-r--r--java/src/com/android/inputmethod/event/CombinerChain.java35
-rw-r--r--java/src/com/android/inputmethod/event/DeadKeyCombiner.java10
-rw-r--r--java/src/com/android/inputmethod/event/Event.java21
-rw-r--r--java/src/com/android/inputmethod/event/InputTransaction.java16
-rw-r--r--java/src/com/android/inputmethod/event/MyanmarReordering.java23
6 files changed, 89 insertions, 19 deletions
diff --git a/java/src/com/android/inputmethod/event/Combiner.java b/java/src/com/android/inputmethod/event/Combiner.java
index 8b808c6b3..fee93f0c6 100644
--- a/java/src/com/android/inputmethod/event/Combiner.java
+++ b/java/src/com/android/inputmethod/event/Combiner.java
@@ -18,6 +18,8 @@ package com.android.inputmethod.event;
import java.util.ArrayList;
+import javax.annotation.Nonnull;
+
/**
* A generic interface for combiners. Combiners are objects that transform chains of input events
* into committable strings and manage feedback to show to the user on the combining state.
@@ -33,6 +35,7 @@ public interface Combiner {
* @param event the event to combine with the existing state.
* @return the resulting event.
*/
+ @Nonnull
Event processEvent(ArrayList<Event> previousEvents, Event event);
/**
diff --git a/java/src/com/android/inputmethod/event/CombinerChain.java b/java/src/com/android/inputmethod/event/CombinerChain.java
index 61bc11b39..2d2731f21 100644
--- a/java/src/com/android/inputmethod/event/CombinerChain.java
+++ b/java/src/com/android/inputmethod/event/CombinerChain.java
@@ -24,6 +24,8 @@ import com.android.inputmethod.latin.Constants;
import java.util.ArrayList;
import java.util.HashMap;
+import javax.annotation.Nonnull;
+
/**
* This class implements the logic chain between receiving events and generating code points.
*
@@ -80,23 +82,43 @@ public class CombinerChain {
}
}
+ private void updateStateFeedback() {
+ mStateFeedback.clear();
+ for (int i = mCombiners.size() - 1; i >= 0; --i) {
+ mStateFeedback.append(mCombiners.get(i).getCombiningStateFeedback());
+ }
+ }
+
/**
- * Pass a new event through the whole chain.
+ * Process an event through the combining chain, and return a processed event to apply.
* @param previousEvents the list of previous events in this composition
* @param newEvent the new event to process
+ * @return the processed event. It may be the same event, or a consumed event, or a completely
+ * new event. However it may never be null.
*/
- public void processEvent(final ArrayList<Event> previousEvents, final Event newEvent) {
+ @Nonnull
+ public Event processEvent(final ArrayList<Event> previousEvents, final Event newEvent) {
final ArrayList<Event> modifiablePreviousEvents = new ArrayList<>(previousEvents);
Event event = newEvent;
for (final Combiner combiner : mCombiners) {
// A combiner can never return more than one event; it can return several
// code points, but they should be encapsulated within one event.
event = combiner.processEvent(modifiablePreviousEvents, event);
- if (null == event) {
- // Combiners return null if they eat the event.
+ if (event.isConsumed()) {
+ // If the event is consumed, then we don't pass it to subsequent combiners:
+ // they should not see it at all.
break;
}
}
+ updateStateFeedback();
+ return event;
+ }
+
+ /**
+ * Apply a processed event.
+ * @param event the event to be applied
+ */
+ public void applyProcessedEvent(final Event event) {
if (null != event) {
// TODO: figure out the generic way of doing this
if (Constants.CODE_DELETE == event.mKeyCode) {
@@ -112,10 +134,7 @@ public class CombinerChain {
}
}
}
- mStateFeedback.clear();
- for (int i = mCombiners.size() - 1; i >= 0; --i) {
- mStateFeedback.append(mCombiners.get(i).getCombiningStateFeedback());
- }
+ updateStateFeedback();
}
/**
diff --git a/java/src/com/android/inputmethod/event/DeadKeyCombiner.java b/java/src/com/android/inputmethod/event/DeadKeyCombiner.java
index bef4d8594..4f3f4d25f 100644
--- a/java/src/com/android/inputmethod/event/DeadKeyCombiner.java
+++ b/java/src/com/android/inputmethod/event/DeadKeyCombiner.java
@@ -23,6 +23,8 @@ import com.android.inputmethod.latin.Constants;
import java.util.ArrayList;
+import javax.annotation.Nonnull;
+
/**
* A combiner that handles dead keys.
*/
@@ -31,12 +33,18 @@ public class DeadKeyCombiner implements Combiner {
final StringBuilder mDeadSequence = new StringBuilder();
@Override
+ @Nonnull
public Event processEvent(final ArrayList<Event> previousEvents, final Event event) {
- if (null == event) return null; // Just in case some combiner is broken
if (TextUtils.isEmpty(mDeadSequence)) {
+ // No dead char is currently being tracked: this is the most common case.
if (event.isDead()) {
+ // The event was a dead key. Start tracking it.
mDeadSequence.appendCodePoint(event.mCodePoint);
+ return Event.createConsumedEvent(event);
}
+ // Regular keystroke when not keeping track of a dead key. Simply said, there are
+ // no dead keys at all in the current input, so this combiner has nothing to do and
+ // simply returns the event as is. The majority of events will go through this path.
return event;
} else {
// TODO: Allow combining for several dead chars rather than only the first one.
diff --git a/java/src/com/android/inputmethod/event/Event.java b/java/src/com/android/inputmethod/event/Event.java
index d257441e0..ef5b04747 100644
--- a/java/src/com/android/inputmethod/event/Event.java
+++ b/java/src/com/android/inputmethod/event/Event.java
@@ -67,6 +67,8 @@ public class Event {
final private static int FLAG_DEAD = 0x1;
// This event is coming from a key repeat, software or hardware.
final private static int FLAG_REPEAT = 0x2;
+ // This event has already been consumed.
+ final private static int FLAG_CONSUMED = 0x4;
final private int mEventType; // 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
@@ -219,6 +221,18 @@ public class Event {
null /* next */);
}
+ /**
+ * Creates an event identical to the passed event, but that has already been consumed.
+ * @param source the event to copy the properties of.
+ * @return an identical event marked as consumed.
+ */
+ public static Event createConsumedEvent(final Event source) {
+ // A consumed event should not input any text at all, so we pass the empty string as text.
+ return new Event(source.mEventType, source.mText, source.mCodePoint, source.mKeyCode,
+ source.mX, source.mY, source.mSuggestedWordInfo, source.mFlags | FLAG_CONSUMED,
+ source.mNextEvent);
+ }
+
public static Event createNotHandledEvent() {
return new Event(EVENT_TYPE_NOT_HANDLED, null /* text */, NOT_A_CODE_POINT, NOT_A_KEY_CODE,
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE,
@@ -241,6 +255,10 @@ public class Event {
return 0 != (FLAG_REPEAT & mFlags);
}
+ public boolean isConsumed() { return 0 != (FLAG_CONSUMED & mFlags); }
+
+ public boolean isGesture() { return EVENT_TYPE_GESTURE == mEventType; }
+
// 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() {
@@ -252,6 +270,9 @@ public class Event {
}
public CharSequence getTextToCommit() {
+ if (isConsumed()) {
+ return ""; // A consumed event should input no text.
+ }
switch (mEventType) {
case EVENT_TYPE_MODE_KEY:
case EVENT_TYPE_NOT_HANDLED:
diff --git a/java/src/com/android/inputmethod/event/InputTransaction.java b/java/src/com/android/inputmethod/event/InputTransaction.java
index cdff265c6..5bc9111de 100644
--- a/java/src/com/android/inputmethod/event/InputTransaction.java
+++ b/java/src/com/android/inputmethod/event/InputTransaction.java
@@ -42,6 +42,7 @@ public class InputTransaction {
private int mRequiredShiftUpdate = SHIFT_NO_UPDATE;
private boolean mRequiresUpdateSuggestions = false;
private boolean mDidAffectContents = false;
+ private boolean mDidAutoCorrect = false;
public InputTransaction(final SettingsValues settingsValues, final Event event,
final long timestamp, final int spaceState, final int shiftState) {
@@ -97,4 +98,19 @@ public class InputTransaction {
public boolean didAffectContents() {
return mDidAffectContents;
}
+
+ /**
+ * Indicate that this transaction performed an auto-correction.
+ */
+ public void setDidAutoCorrect() {
+ mDidAutoCorrect = true;
+ }
+
+ /**
+ * Find out whether this transaction performed an auto-correction.
+ * @return Whether this transaction performed an auto-correction.
+ */
+ public boolean didAutoCorrect() {
+ return mDidAutoCorrect;
+ }
}
diff --git a/java/src/com/android/inputmethod/event/MyanmarReordering.java b/java/src/com/android/inputmethod/event/MyanmarReordering.java
index 32919932d..dcd06c899 100644
--- a/java/src/com/android/inputmethod/event/MyanmarReordering.java
+++ b/java/src/com/android/inputmethod/event/MyanmarReordering.java
@@ -21,6 +21,8 @@ import com.android.inputmethod.latin.Constants;
import java.util.ArrayList;
import java.util.Arrays;
+import javax.annotation.Nonnull;
+
/**
* A combiner that reorders input for Myanmar.
*/
@@ -111,7 +113,7 @@ public class MyanmarReordering implements Combiner {
* Clears the currently combining stream of events and returns the resulting software text
* event corresponding to the stream. Optionally adds a new event to the cleared stream.
* @param newEvent the new event to add to the stream. null if none.
- * @return the resulting software text event. Null if none.
+ * @return the resulting software text event. Never null.
*/
private Event clearAndGetResultingEvent(final Event newEvent) {
final CharSequence combinedText;
@@ -124,18 +126,19 @@ public class MyanmarReordering implements Combiner {
if (null != newEvent) {
mCurrentEvents.add(newEvent);
}
- return null == combinedText ? null
+ return null == combinedText ? Event.createConsumedEvent(newEvent)
: Event.createSoftwareTextEvent(combinedText, Event.NOT_A_KEY_CODE);
}
@Override
+ @Nonnull
public Event processEvent(ArrayList<Event> previousEvents, Event newEvent) {
final int codePoint = newEvent.mCodePoint;
if (VOWEL_E == codePoint) {
final Event lastEvent = getLastEvent();
if (null == lastEvent) {
mCurrentEvents.add(newEvent);
- return null;
+ return Event.createConsumedEvent(newEvent);
} else if (isConsonantOrMedial(lastEvent.mCodePoint)) {
final Event resultingEvent = clearAndGetResultingEvent(null);
mCurrentEvents.add(Event.createSoftwareKeypressEvent(ZERO_WIDTH_NON_JOINER,
@@ -151,7 +154,7 @@ public class MyanmarReordering implements Combiner {
final Event lastEvent = getLastEvent();
if (null == lastEvent) {
mCurrentEvents.add(newEvent);
- return null;
+ return Event.createConsumedEvent(newEvent);
} else if (VOWEL_E == lastEvent.mCodePoint) {
final int eventSize = mCurrentEvents.size();
if (eventSize >= 2
@@ -162,7 +165,7 @@ public class MyanmarReordering implements Combiner {
mCurrentEvents.remove(eventSize - 2);
mCurrentEvents.add(newEvent);
mCurrentEvents.add(lastEvent);
- return null;
+ return Event.createConsumedEvent(newEvent);
}
// If there is already a consonant, then we are starting a new syllable.
for (int i = eventSize - 2; i >= 0; --i) {
@@ -174,7 +177,7 @@ public class MyanmarReordering implements Combiner {
mCurrentEvents.remove(eventSize - 1);
mCurrentEvents.add(newEvent);
mCurrentEvents.add(lastEvent);
- return null;
+ return Event.createConsumedEvent(newEvent);
} else { // lastCodePoint is a consonant/medial. But if it's something else it's fine
return clearAndGetResultingEvent(newEvent);
}
@@ -182,7 +185,7 @@ public class MyanmarReordering implements Combiner {
final Event lastEvent = getLastEvent();
if (null == lastEvent) {
mCurrentEvents.add(newEvent);
- return null;
+ return Event.createConsumedEvent(newEvent);
} else if (VOWEL_E == lastEvent.mCodePoint) {
final int eventSize = mCurrentEvents.size();
// If there is already a consonant, then we are in the middle of a syllable, and we
@@ -198,7 +201,7 @@ public class MyanmarReordering implements Combiner {
mCurrentEvents.remove(eventSize - 1);
mCurrentEvents.add(newEvent);
mCurrentEvents.add(lastEvent);
- return null;
+ return Event.createConsumedEvent(newEvent);
}
// Otherwise, we just commit everything.
return clearAndGetResultingEvent(null);
@@ -228,10 +231,10 @@ public class MyanmarReordering implements Combiner {
mCurrentEvents.remove(eventSize - 1);
}
}
- return null;
+ return Event.createConsumedEvent(newEvent);
} else if (eventSize > 0) {
mCurrentEvents.remove(eventSize - 1);
- return null;
+ return Event.createConsumedEvent(newEvent);
}
}
}