Merge "Refactor keyboard layout test more customizable"
diff --git a/java/src/com/android/inputmethod/event/DeadKeyCombiner.java b/java/src/com/android/inputmethod/event/DeadKeyCombiner.java
index 4af4590..ae86397 100644
--- a/java/src/com/android/inputmethod/event/DeadKeyCombiner.java
+++ b/java/src/com/android/inputmethod/event/DeadKeyCombiner.java
@@ -49,11 +49,11 @@
                 // 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.createInputKeypressEvent(deadCodePoint, event.mKeyCode,
+                return Event.createHardwareKeypressEvent(deadCodePoint, event.mKeyCode,
                         Constants.CODE_SPACE == event.mCodePoint ? null : event /* next */);
             } else {
                 // We could combine the characters.
-                return Event.createInputKeypressEvent(resultingCodePoint, event.mKeyCode,
+                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 21cf915..31092f1 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.
  *
@@ -73,6 +75,13 @@
     // 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;
 
@@ -80,27 +89,40 @@
     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 flags,
-            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 createInputKeypressEvent(final int codePoint, final int keyCode,
+    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 createHardwareKeypressEvent(final int codePoint, final int keyCode,
             final Event next) {
-        return new Event(EVENT_INPUT_KEYPRESS, codePoint, keyCode, FLAG_NONE, next);
+        return new Event(EVENT_INPUT_KEYPRESS, codePoint, keyCode,
+                Constants.EXTERNAL_KEYBOARD_COORDINATE, Constants.EXTERNAL_KEYBOARD_COORDINATE,
+                FLAG_NONE, next);
     }
 
     // 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) {
-        return new Event(EVENT_INPUT_KEYPRESS, codePoint, keyCode, FLAG_DEAD, 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 static Event createNotHandledEvent() {
-        return new Event(EVENT_NOT_HANDLED, NOT_A_CODE_POINT, NOT_A_KEY_CODE, FLAG_NONE, null);
+        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}
diff --git a/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java b/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java
index 635f3b1..da6780e 100644
--- a/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java
+++ b/java/src/com/android/inputmethod/event/HardwareKeyboardEventDecoder.java
@@ -47,7 +47,7 @@
         // 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.createInputKeypressEvent(Event.NOT_A_CODE_POINT, Constants.CODE_DELETE,
+            return Event.createHardwareKeypressEvent(Event.NOT_A_CODE_POINT, Constants.CODE_DELETE,
                     null /* next */);
         }
         if (keyEvent.isPrintingKey() || KeyEvent.KEYCODE_SPACE == keyCode
@@ -64,16 +64,16 @@
                 // Shift key is being pressed, this should send a CODE_SHIFT_ENTER and let
                 // Latin IME decide what to do with it.
                 if (keyEvent.isShiftPressed()) {
-                    return Event.createInputKeypressEvent(Event.NOT_A_CODE_POINT,
+                    return Event.createHardwareKeypressEvent(Event.NOT_A_CODE_POINT,
                             Constants.CODE_SHIFT_ENTER, null /* next */);
                 } else {
-                    return Event.createInputKeypressEvent(Constants.CODE_ENTER, keyCode,
+                    return Event.createHardwareKeypressEvent(Constants.CODE_ENTER, keyCode,
                             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.createInputKeypressEvent(keyCode, codePointAndFlags, null /* next */);
+            return Event.createHardwareKeypressEvent(keyCode, codePointAndFlags, null /* next */);
         }
         return Event.createNotHandledEvent();
     }
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index a9e5480..222e735 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.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 @@
             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 @@
         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/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index dd9d6e8..f7e5286 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.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 @@
             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,17 +355,21 @@
      * 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) {
+        // 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 int x = event.mX;
+        final int y = event.mY;
         final InputTransaction inputTransaction = new InputTransaction(settingsValues, code, x, y,
                 SystemClock.uptimeMillis(), mSpaceState,
                 getActualCapsMode(settingsValues, keyboardShiftMode));