Event.java revision 46e17983c69650415c6469a80c46154cb4299f9d
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.inputmethod.event; 18 19import com.android.inputmethod.latin.Constants; 20import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; 21 22/** 23 * Class representing a generic input event as handled by Latin IME. 24 * 25 * This contains information about the origin of the event, but it is generalized and should 26 * represent a software keypress, hardware keypress, or d-pad move alike. 27 * Very importantly, this does not necessarily result in inputting one character, or even anything 28 * at all - it may be a dead key, it may be a partial input, it may be a special key on the 29 * keyboard, it may be a cancellation of a keypress (e.g. in a soft keyboard the finger of the 30 * user has slid out of the key), etc. It may also be a batch input from a gesture or handwriting 31 * for example. 32 * The combiner should figure out what to do with this. 33 */ 34public class Event { 35 // Should the types below be represented by separate classes instead? It would be cleaner 36 // but probably a bit too much 37 // An event we don't handle in Latin IME, for example pressing Ctrl on a hardware keyboard. 38 final public static int EVENT_NOT_HANDLED = 0; 39 // A key press that is part of input, for example pressing an alphabetic character on a 40 // hardware qwerty keyboard. It may be part of a sequence that will be re-interpreted later 41 // through combination. 42 final public static int EVENT_INPUT_KEYPRESS = 1; 43 // A toggle event is triggered by a key that affects the previous character. An example would 44 // be a numeric key on a 10-key keyboard, which would toggle between 1 - a - b - c with 45 // repeated presses. 46 final public static int EVENT_TOGGLE = 2; 47 // A mode event instructs the combiner to change modes. The canonical example would be the 48 // hankaku/zenkaku key on a Japanese keyboard, or even the caps lock key on a qwerty keyboard 49 // if handled at the combiner level. 50 final public static int EVENT_MODE_KEY = 3; 51 // An event corresponding to a gesture. 52 final public static int EVENT_GESTURE = 4; 53 // An event corresponding to the manual pick of a suggestion. 54 final public static int EVENT_SUGGESTION_PICKED = 5; 55 56 // 0 is a valid code point, so we use -1 here. 57 final public static int NOT_A_CODE_POINT = -1; 58 // -1 is a valid key code, so we use 0 here. 59 final public static int NOT_A_KEY_CODE = 0; 60 61 final private static int FLAG_NONE = 0; 62 // This event is a dead character, usually input by a dead key. Examples include dead-acute 63 // or dead-abovering. 64 final private static int FLAG_DEAD = 0x1; 65 66 final private int mType; // The type of event - one of the constants above 67 // The code point associated with the event, if relevant. This is a unicode code point, and 68 // has nothing to do with other representations of the key. It is only relevant if this event 69 // is of KEYPRESS type, but for a mode key like hankaku/zenkaku or ctrl, there is no code point 70 // associated so this should be NOT_A_CODE_POINT to avoid unintentional use of its value when 71 // it's not relevant. 72 final public int mCodePoint; 73 74 // The key code associated with the event, if relevant. This is relevant whenever this event 75 // has been triggered by a key press, but not for a gesture for example. This has conceptually 76 // no link to the code point, although keys that enter a straight code point may often set 77 // this to be equal to mCodePoint for convenience. If this is not a key, this must contain 78 // NOT_A_KEY_CODE. 79 final public int mKeyCode; 80 81 // Coordinates of the touch event, if relevant. If useful, we may want to replace this with 82 // a MotionEvent or something in the future. This is only relevant when the keypress is from 83 // a software keyboard obviously, unless there are touch-sensitive hardware keyboards in the 84 // future or some other awesome sauce. 85 final public int mX; 86 final public int mY; 87 88 // Some flags that can't go into the key code. It's a bit field of FLAG_* 89 final private int mFlags; 90 91 // If this is of type EVENT_SUGGESTION_PICKED, this must not be null (and must be null in 92 // other cases). 93 final public SuggestedWordInfo mSuggestedWordInfo; 94 95 // The next event, if any. Null if there is no next event yet. 96 final public Event mNextEvent; 97 98 // This method is private - to create a new event, use one of the create* utility methods. 99 private Event(final int type, final int codePoint, final int keyCode, final int x, final int y, 100 final SuggestedWordInfo suggestedWordInfo, final int flags, final Event next) { 101 mType = type; 102 mCodePoint = codePoint; 103 mKeyCode = keyCode; 104 mX = x; 105 mY = y; 106 mSuggestedWordInfo = suggestedWordInfo; 107 mFlags = flags; 108 mNextEvent = next; 109 // Sanity checks 110 // mSuggestedWordInfo is non-null if and only if the type is SUGGESTION_PICKED 111 if (EVENT_SUGGESTION_PICKED == mType) { 112 if (null == mSuggestedWordInfo) { 113 throw new RuntimeException("Wrong event: SUGGESTION_PICKED event must have a " 114 + "non-null SuggestedWordInfo"); 115 } 116 } else { 117 if (null != mSuggestedWordInfo) { 118 throw new RuntimeException("Wrong event: only SUGGESTION_PICKED events may have " + 119 "a non-null SuggestedWordInfo"); 120 } 121 } 122 } 123 124 public static Event createSoftwareKeypressEvent(final int codePoint, final int keyCode, 125 final int x, final int y) { 126 return new Event(EVENT_INPUT_KEYPRESS, codePoint, keyCode, x, y, 127 null /* suggestedWordInfo */, FLAG_NONE, null); 128 } 129 130 public static Event createHardwareKeypressEvent(final int codePoint, final int keyCode, 131 final Event next) { 132 return new Event(EVENT_INPUT_KEYPRESS, codePoint, keyCode, 133 Constants.EXTERNAL_KEYBOARD_COORDINATE, Constants.EXTERNAL_KEYBOARD_COORDINATE, 134 null /* suggestedWordInfo */, FLAG_NONE, next); 135 } 136 137 // This creates an input event for a dead character. @see {@link #FLAG_DEAD} 138 public static Event createDeadEvent(final int codePoint, final int keyCode, final Event next) { 139 // TODO: add an argument or something if we ever create a software layout with dead keys. 140 return new Event(EVENT_INPUT_KEYPRESS, codePoint, keyCode, 141 Constants.EXTERNAL_KEYBOARD_COORDINATE, Constants.EXTERNAL_KEYBOARD_COORDINATE, 142 null /* suggestedWordInfo */, FLAG_DEAD, next); 143 } 144 145 /** 146 * Create an input event with nothing but a code point. This is the most basic possible input 147 * event; it contains no information on many things the IME requires to function correctly, 148 * so avoid using it unless really nothing is known about this input. 149 * @param codePoint the code point. 150 * @return an event for this code point. 151 */ 152 public static Event createEventForCodePointFromUnknownSource(final int codePoint) { 153 // TODO: should we have a different type of event for this? After all, it's not a key press. 154 return new Event(EVENT_INPUT_KEYPRESS, codePoint, NOT_A_KEY_CODE, 155 Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, 156 null /* suggestedWordInfo */, FLAG_NONE, null /* next */); 157 } 158 159 /** 160 * Creates an input event with a code point and x, y coordinates. This is typically used when 161 * resuming a previously-typed word, when the coordinates are still known. 162 * @param codePoint the code point to input. 163 * @param x the X coordinate. 164 * @param y the Y coordinate. 165 * @return an event for this code point and coordinates. 166 */ 167 public static Event createEventForCodePointFromAlreadyTypedText(final int codePoint, 168 final int x, final int y) { 169 // TODO: should we have a different type of event for this? After all, it's not a key press. 170 return new Event(EVENT_INPUT_KEYPRESS, codePoint, NOT_A_KEY_CODE, x, y, 171 null /* suggestedWordInfo */, FLAG_NONE, null /* next */); 172 } 173 174 /** 175 * Creates an input event representing the manual pick of a suggestion. 176 * @return an event for this suggestion pick. 177 */ 178 public static Event createSuggestionPickedEvent(final SuggestedWordInfo suggestedWordInfo) { 179 return new Event(EVENT_SUGGESTION_PICKED, NOT_A_CODE_POINT, NOT_A_KEY_CODE, 180 Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE, 181 suggestedWordInfo, FLAG_NONE, null); 182 } 183 184 public static Event createNotHandledEvent() { 185 return new Event(EVENT_NOT_HANDLED, NOT_A_CODE_POINT, NOT_A_KEY_CODE, 186 Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, 187 null /* suggestedWordInfo */, FLAG_NONE, null); 188 } 189 190 // Returns whether this event is for a dead character. @see {@link #FLAG_DEAD} 191 public boolean isDead() { 192 return 0 != (FLAG_DEAD & mFlags); 193 } 194 195 // Returns whether this is a fake key press from the suggestion strip. This happens with 196 // punctuation signs selected from the suggestion strip. 197 public boolean isSuggestionStripPress() { 198 return EVENT_INPUT_KEYPRESS == mType && Constants.SUGGESTION_STRIP_COORDINATE == mX; 199 } 200 201 // TODO: remove this method - we should not have to test this 202 public boolean isCommittable() { 203 return EVENT_INPUT_KEYPRESS == mType || EVENT_MODE_KEY == mType || EVENT_TOGGLE == mType; 204 } 205 206 public boolean isHandled() { 207 return EVENT_NOT_HANDLED != mType; 208 } 209} 210