2010-12-02 09:46:21 +00:00
|
|
|
/*
|
2011-05-20 03:09:57 +00:00
|
|
|
* Copyright (C) 2010 The Android Open Source Project
|
2010-12-02 09:46:21 +00:00
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
|
|
* use this file except in compliance with the License. You may obtain a copy of
|
|
|
|
* the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
|
|
* License for the specific language governing permissions and limitations under
|
|
|
|
* the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package com.android.inputmethod.keyboard;
|
|
|
|
|
2011-12-12 04:08:41 +00:00
|
|
|
import android.util.Log;
|
2012-06-29 07:32:45 +00:00
|
|
|
import android.util.SparseArray;
|
2010-12-02 09:46:21 +00:00
|
|
|
|
2012-08-30 08:42:49 +00:00
|
|
|
import com.android.inputmethod.keyboard.internal.KeyVisualAttributes;
|
2011-06-21 14:38:42 +00:00
|
|
|
import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
|
2012-08-30 05:22:40 +00:00
|
|
|
import com.android.inputmethod.keyboard.internal.KeyboardParams;
|
2012-08-21 07:34:55 +00:00
|
|
|
import com.android.inputmethod.latin.CollectionUtils;
|
2011-06-15 04:38:58 +00:00
|
|
|
|
2011-12-18 10:54:08 +00:00
|
|
|
|
2010-12-02 09:46:21 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard
|
|
|
|
* consists of rows of keys.
|
|
|
|
* <p>The layout file for a keyboard contains XML that looks like the following snippet:</p>
|
|
|
|
* <pre>
|
|
|
|
* <Keyboard
|
|
|
|
* latin:keyWidth="%10p"
|
|
|
|
* latin:keyHeight="50px"
|
|
|
|
* latin:horizontalGap="2px"
|
|
|
|
* latin:verticalGap="2px" >
|
|
|
|
* <Row latin:keyWidth="32px" >
|
|
|
|
* <Key latin:keyLabel="A" />
|
|
|
|
* ...
|
|
|
|
* </Row>
|
|
|
|
* ...
|
|
|
|
* </Keyboard>
|
|
|
|
* </pre>
|
|
|
|
*/
|
|
|
|
public class Keyboard {
|
2011-12-12 04:08:41 +00:00
|
|
|
private static final String TAG = Keyboard.class.getSimpleName();
|
|
|
|
|
2011-12-26 14:40:09 +00:00
|
|
|
/** Some common keys code. Must be positive.
|
|
|
|
* These should be aligned with values/keycodes.xml
|
|
|
|
*/
|
2010-12-02 11:54:32 +00:00
|
|
|
public static final int CODE_ENTER = '\n';
|
|
|
|
public static final int CODE_TAB = '\t';
|
|
|
|
public static final int CODE_SPACE = ' ';
|
|
|
|
public static final int CODE_PERIOD = '.';
|
2011-04-28 06:39:39 +00:00
|
|
|
public static final int CODE_DASH = '-';
|
|
|
|
public static final int CODE_SINGLE_QUOTE = '\'';
|
|
|
|
public static final int CODE_DOUBLE_QUOTE = '"';
|
2011-07-14 05:15:01 +00:00
|
|
|
// TODO: Check how this should work for right-to-left languages. It seems to stand
|
|
|
|
// that for rtl languages, a closing parenthesis is a left parenthesis. Is this
|
|
|
|
// managed by the font? Or is it a different char?
|
|
|
|
public static final int CODE_CLOSING_PARENTHESIS = ')';
|
|
|
|
public static final int CODE_CLOSING_SQUARE_BRACKET = ']';
|
|
|
|
public static final int CODE_CLOSING_CURLY_BRACKET = '}';
|
|
|
|
public static final int CODE_CLOSING_ANGLE_BRACKET = '>';
|
|
|
|
|
2012-01-10 08:24:00 +00:00
|
|
|
/** Special keys code. Must be negative.
|
2012-06-04 19:27:37 +00:00
|
|
|
* These should be aligned with KeyboardCodesSet.ID_TO_NAME[],
|
|
|
|
* KeyboardCodesSet.DEFAULT[] and KeyboardCodesSet.RTL[]
|
2011-12-26 14:40:09 +00:00
|
|
|
*/
|
2010-12-02 11:54:32 +00:00
|
|
|
public static final int CODE_SHIFT = -1;
|
2010-12-06 03:12:27 +00:00
|
|
|
public static final int CODE_SWITCH_ALPHA_SYMBOL = -2;
|
2012-02-07 08:07:23 +00:00
|
|
|
public static final int CODE_OUTPUT_TEXT = -3;
|
|
|
|
public static final int CODE_DELETE = -4;
|
|
|
|
public static final int CODE_SETTINGS = -5;
|
|
|
|
public static final int CODE_SHORTCUT = -6;
|
|
|
|
public static final int CODE_ACTION_ENTER = -7;
|
2012-02-17 07:14:14 +00:00
|
|
|
public static final int CODE_ACTION_NEXT = -8;
|
|
|
|
public static final int CODE_ACTION_PREVIOUS = -9;
|
2012-02-18 01:46:01 +00:00
|
|
|
public static final int CODE_LANGUAGE_SWITCH = -10;
|
2012-06-04 19:27:37 +00:00
|
|
|
public static final int CODE_RESEARCH = -11;
|
2010-12-20 11:30:26 +00:00
|
|
|
// Code value representing the code is not specified.
|
2012-06-04 19:27:37 +00:00
|
|
|
public static final int CODE_UNSPECIFIED = -12;
|
2010-12-02 09:46:21 +00:00
|
|
|
|
2011-08-02 00:50:49 +00:00
|
|
|
public final KeyboardId mId;
|
2011-09-28 03:08:48 +00:00
|
|
|
public final int mThemeId;
|
2011-08-02 00:50:49 +00:00
|
|
|
|
|
|
|
/** Total height of the keyboard, including the padding and keys */
|
2011-07-29 00:05:40 +00:00
|
|
|
public final int mOccupiedHeight;
|
|
|
|
/** Total width of the keyboard, including the padding and keys */
|
|
|
|
public final int mOccupiedWidth;
|
2011-08-02 00:50:49 +00:00
|
|
|
|
2011-09-22 10:29:58 +00:00
|
|
|
/** The padding above the keyboard */
|
|
|
|
public final int mTopPadding;
|
2010-12-02 09:46:21 +00:00
|
|
|
/** Default gap between rows */
|
2011-07-29 00:05:40 +00:00
|
|
|
public final int mVerticalGap;
|
|
|
|
|
2012-08-28 02:28:42 +00:00
|
|
|
/** Per keyboard key visual parameters */
|
2012-08-30 08:42:49 +00:00
|
|
|
public final KeyVisualAttributes mKeyVisualAttributes;
|
2012-08-28 02:28:42 +00:00
|
|
|
|
2011-09-22 10:29:58 +00:00
|
|
|
public final int mMostCommonKeyHeight;
|
2011-07-29 00:05:40 +00:00
|
|
|
public final int mMostCommonKeyWidth;
|
2010-12-02 09:46:21 +00:00
|
|
|
|
2011-08-31 06:26:32 +00:00
|
|
|
/** More keys keyboard template */
|
|
|
|
public final int mMoreKeysTemplate;
|
2010-12-14 06:31:47 +00:00
|
|
|
|
2012-02-08 07:12:11 +00:00
|
|
|
/** Maximum column for more keys keyboard */
|
|
|
|
public final int mMaxMoreKeysKeyboardColumn;
|
2010-12-14 06:31:47 +00:00
|
|
|
|
2012-03-13 11:53:15 +00:00
|
|
|
/** Array of keys and icons in this keyboard */
|
|
|
|
public final Key[] mKeys;
|
|
|
|
public final Key[] mShiftKeys;
|
2012-03-13 08:15:05 +00:00
|
|
|
public final Key[] mAltCodeKeysWhileTyping;
|
2011-07-29 00:05:40 +00:00
|
|
|
public final KeyboardIconsSet mIconsSet;
|
2011-04-15 07:33:46 +00:00
|
|
|
|
2012-08-22 05:22:20 +00:00
|
|
|
private final SparseArray<Key> mKeyCache = CollectionUtils.newSparseArray();
|
2011-06-21 14:38:42 +00:00
|
|
|
|
2011-02-22 08:28:55 +00:00
|
|
|
private final ProximityInfo mProximityInfo;
|
2012-03-28 08:33:25 +00:00
|
|
|
private final boolean mProximityCharsCorrectionEnabled;
|
2011-02-22 08:28:55 +00:00
|
|
|
|
2012-08-30 05:22:40 +00:00
|
|
|
public Keyboard(final KeyboardParams params) {
|
2011-07-29 00:05:40 +00:00
|
|
|
mId = params.mId;
|
2011-09-28 03:08:48 +00:00
|
|
|
mThemeId = params.mThemeId;
|
2011-07-29 00:05:40 +00:00
|
|
|
mOccupiedHeight = params.mOccupiedHeight;
|
|
|
|
mOccupiedWidth = params.mOccupiedWidth;
|
2011-09-22 10:29:58 +00:00
|
|
|
mMostCommonKeyHeight = params.mMostCommonKeyHeight;
|
2011-07-29 00:05:40 +00:00
|
|
|
mMostCommonKeyWidth = params.mMostCommonKeyWidth;
|
2011-08-31 06:26:32 +00:00
|
|
|
mMoreKeysTemplate = params.mMoreKeysTemplate;
|
2012-02-08 07:12:11 +00:00
|
|
|
mMaxMoreKeysKeyboardColumn = params.mMaxMoreKeysKeyboardColumn;
|
2012-08-30 08:42:49 +00:00
|
|
|
mKeyVisualAttributes = params.mKeyVisualAttributes;
|
2011-09-22 10:29:58 +00:00
|
|
|
mTopPadding = params.mTopPadding;
|
2011-07-29 00:05:40 +00:00
|
|
|
mVerticalGap = params.mVerticalGap;
|
|
|
|
|
2012-03-13 11:53:15 +00:00
|
|
|
mKeys = params.mKeys.toArray(new Key[params.mKeys.size()]);
|
|
|
|
mShiftKeys = params.mShiftKeys.toArray(new Key[params.mShiftKeys.size()]);
|
2012-03-13 08:15:05 +00:00
|
|
|
mAltCodeKeysWhileTyping = params.mAltCodeKeysWhileTyping.toArray(
|
|
|
|
new Key[params.mAltCodeKeysWhileTyping.size()]);
|
2011-07-29 00:05:40 +00:00
|
|
|
mIconsSet = params.mIconsSet;
|
2010-12-02 09:46:21 +00:00
|
|
|
|
2012-03-13 10:16:33 +00:00
|
|
|
mProximityInfo = new ProximityInfo(params.mId.mLocale.toString(),
|
2011-07-29 00:05:40 +00:00
|
|
|
params.GRID_WIDTH, params.GRID_HEIGHT, mOccupiedWidth, mOccupiedHeight,
|
2012-03-19 05:47:38 +00:00
|
|
|
mMostCommonKeyWidth, mMostCommonKeyHeight, mKeys, params.mTouchPositionCorrection);
|
2012-03-28 08:33:25 +00:00
|
|
|
mProximityCharsCorrectionEnabled = params.mProximityCharsCorrectionEnabled;
|
|
|
|
}
|
|
|
|
|
2012-08-30 05:22:40 +00:00
|
|
|
public boolean hasProximityCharsCorrection(final int code) {
|
2012-03-28 08:33:25 +00:00
|
|
|
if (!mProximityCharsCorrectionEnabled) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// Note: The native code has the main keyboard layout only at this moment.
|
|
|
|
// TODO: Figure out how to handle proximity characters information of all layouts.
|
|
|
|
final boolean canAssumeNativeHasProximityCharsInfoOfAllKeys = (
|
|
|
|
mId.mElementId == KeyboardId.ELEMENT_ALPHABET
|
|
|
|
|| mId.mElementId == KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED);
|
|
|
|
return canAssumeNativeHasProximityCharsInfoOfAllKeys || Character.isLetter(code);
|
2011-02-22 08:28:55 +00:00
|
|
|
}
|
|
|
|
|
2011-08-04 03:08:22 +00:00
|
|
|
public ProximityInfo getProximityInfo() {
|
|
|
|
return mProximityInfo;
|
2010-12-02 09:46:21 +00:00
|
|
|
}
|
|
|
|
|
2012-08-30 05:22:40 +00:00
|
|
|
public Key getKey(final int code) {
|
2012-01-10 08:24:00 +00:00
|
|
|
if (code == CODE_UNSPECIFIED) {
|
2011-12-14 08:05:11 +00:00
|
|
|
return null;
|
|
|
|
}
|
2012-07-05 01:44:10 +00:00
|
|
|
synchronized (mKeyCache) {
|
|
|
|
final int index = mKeyCache.indexOfKey(code);
|
|
|
|
if (index >= 0) {
|
|
|
|
return mKeyCache.valueAt(index);
|
|
|
|
}
|
2011-11-30 08:54:58 +00:00
|
|
|
|
2012-07-05 01:44:10 +00:00
|
|
|
for (final Key key : mKeys) {
|
|
|
|
if (key.mCode == code) {
|
|
|
|
mKeyCache.put(code, key);
|
|
|
|
return key;
|
|
|
|
}
|
2011-11-30 08:54:58 +00:00
|
|
|
}
|
2012-07-05 01:44:10 +00:00
|
|
|
mKeyCache.put(code, null);
|
|
|
|
return null;
|
2011-11-30 08:54:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-30 05:22:40 +00:00
|
|
|
public boolean hasKey(final Key aKey) {
|
2012-06-29 07:32:45 +00:00
|
|
|
if (mKeyCache.indexOfValue(aKey) >= 0) {
|
2012-05-17 05:46:10 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (final Key key : mKeys) {
|
|
|
|
if (key == aKey) {
|
|
|
|
mKeyCache.put(key.mCode, key);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-08-30 05:22:40 +00:00
|
|
|
public static boolean isLetterCode(final int code) {
|
2012-07-18 05:05:01 +00:00
|
|
|
return code >= CODE_SPACE;
|
2011-12-26 14:40:09 +00:00
|
|
|
}
|
|
|
|
|
2012-08-08 06:59:56 +00:00
|
|
|
@Override
|
|
|
|
public String toString() {
|
|
|
|
return mId.toString();
|
|
|
|
}
|
|
|
|
|
2010-12-02 09:46:21 +00:00
|
|
|
/**
|
2011-12-16 05:20:11 +00:00
|
|
|
* Returns the array of the keys that are closest to the given point.
|
2010-12-02 09:46:21 +00:00
|
|
|
* @param x the x-coordinate of the point
|
|
|
|
* @param y the y-coordinate of the point
|
2011-12-16 05:20:11 +00:00
|
|
|
* @return the array of the nearest keys to the given point. If the given
|
2010-12-02 09:46:21 +00:00
|
|
|
* point is out of range, then an array of size zero is returned.
|
|
|
|
*/
|
2012-08-30 05:22:40 +00:00
|
|
|
public Key[] getNearestKeys(final int x, final int y) {
|
2011-12-19 08:58:36 +00:00
|
|
|
// Avoid dead pixels at edges of the keyboard
|
|
|
|
final int adjustedX = Math.max(0, Math.min(x, mOccupiedWidth - 1));
|
|
|
|
final int adjustedY = Math.max(0, Math.min(y, mOccupiedHeight - 1));
|
|
|
|
return mProximityInfo.getNearestKeys(adjustedX, adjustedY);
|
2010-12-02 09:46:21 +00:00
|
|
|
}
|
2011-09-28 03:08:48 +00:00
|
|
|
|
2012-08-30 05:22:40 +00:00
|
|
|
public static String printableCode(final int code) {
|
2011-12-12 04:08:41 +00:00
|
|
|
switch (code) {
|
|
|
|
case CODE_SHIFT: return "shift";
|
|
|
|
case CODE_SWITCH_ALPHA_SYMBOL: return "symbol";
|
2012-01-10 08:24:00 +00:00
|
|
|
case CODE_OUTPUT_TEXT: return "text";
|
2011-12-12 04:08:41 +00:00
|
|
|
case CODE_DELETE: return "delete";
|
2012-02-01 06:07:25 +00:00
|
|
|
case CODE_SETTINGS: return "settings";
|
2011-12-12 04:08:41 +00:00
|
|
|
case CODE_SHORTCUT: return "shortcut";
|
2012-02-07 08:07:23 +00:00
|
|
|
case CODE_ACTION_ENTER: return "actionEnter";
|
2012-02-17 07:14:14 +00:00
|
|
|
case CODE_ACTION_NEXT: return "actionNext";
|
|
|
|
case CODE_ACTION_PREVIOUS: return "actionPrevious";
|
2012-03-15 12:05:17 +00:00
|
|
|
case CODE_LANGUAGE_SWITCH: return "languageSwitch";
|
2011-12-12 04:08:41 +00:00
|
|
|
case CODE_UNSPECIFIED: return "unspec";
|
2012-01-26 09:03:30 +00:00
|
|
|
case CODE_TAB: return "tab";
|
|
|
|
case CODE_ENTER: return "enter";
|
2011-12-12 04:08:41 +00:00
|
|
|
default:
|
2012-01-17 08:08:26 +00:00
|
|
|
if (code <= 0) Log.w(TAG, "Unknown non-positive key code=" + code);
|
|
|
|
if (code < CODE_SPACE) return String.format("'\\u%02x'", code);
|
|
|
|
if (code < 0x100) return String.format("'%c'", code);
|
|
|
|
return String.format("'\\u%04x'", code);
|
2011-12-12 04:08:41 +00:00
|
|
|
}
|
|
|
|
}
|
2010-12-02 09:46:21 +00:00
|
|
|
}
|