aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--java/res/values-am/strings.xml4
-rw-r--r--java/src/com/android/inputmethod/event/Event.java4
-rw-r--r--java/src/com/android/inputmethod/event/EventInterpreter.java81
-rw-r--r--java/src/com/android/inputmethod/event/SoftwareEventDecoder.java29
-rw-r--r--java/src/com/android/inputmethod/event/SoftwareKeyboardEventDecoder.java27
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java41
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java12
-rw-r--r--native/jni/src/defines.h4
-rw-r--r--native/jni/src/suggest/policyimpl/typing/typing_scoring.h23
-rw-r--r--native/jni/src/suggest/policyimpl/typing/typing_weighting.h2
-rw-r--r--tests/src/com/android/inputmethod/keyboard/layout/Hebrew.java195
-rw-r--r--tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHebrew.java37
12 files changed, 290 insertions, 169 deletions
diff --git a/java/res/values-am/strings.xml b/java/res/values-am/strings.xml
index 6d4c5bf88..13fe7f83f 100644
--- a/java/res/values-am/strings.xml
+++ b/java/res/values-am/strings.xml
@@ -210,10 +210,10 @@
<string name="message_updating" msgid="4457761393932375219">"ዝማኔዎችን በመፈለግ ላይ"</string>
<string name="message_loading" msgid="5638680861387748936">"በመጫን ላይ…"</string>
<string name="main_dict_description" msgid="3072821352793492143">"ዋና መዝገበ-ቃላት"</string>
- <string name="cancel" msgid="6830980399865683324">"ሰርዝ"</string>
+ <string name="cancel" msgid="6830980399865683324">"ይቅር"</string>
<string name="go_to_settings" msgid="3876892339342569259">"ቅንብሮች"</string>
<string name="install_dict" msgid="180852772562189365">"ጫን"</string>
- <string name="cancel_download_dict" msgid="7843340278507019303">"ሰርዝ"</string>
+ <string name="cancel_download_dict" msgid="7843340278507019303">"ይቅር"</string>
<string name="delete_dict" msgid="756853268088330054">"ሰርዝ"</string>
<string name="should_download_over_metered_prompt" msgid="1583881200688185508">"በተንቀሳቃሽ መሣሪያዎ ላይ ለተመረጠው ቋንቋ የሚሆን መዝገበ-ቃላት ይገኛል።&lt;br/&gt; የትየባ ተሞክሮዎን ለማሻሻል የ<xliff:g id="LANGUAGE_NAME">%1$s</xliff:g> መዝገበ-ቃላቱን &lt;b&gt;እንዲያወርዱ&lt;/b&gt; እንመክራለን።&lt;br/&gt; &lt;br/&gt; ማውረድ በ3ጂ ላይ አንድ ወይም ሁለት ደቂቃ ሊወስድ ይችላል። &lt;b&gt;ያልተገደበ የውሂብ ዕቅድ&lt;/b&gt; ከሌለዎት ክፍያዎች መከፈል ሊኖርባቸው ይችላል።&lt;br/&gt; የትኛው የውሂብ ዕቅድ እንዳለዎት እርግጠኛ ካልሆኑ ውርዱን በራስ-ሰር ለመጀመር የWi-Fi ግንኙነት እንዲፈልጉ እንመክራለን።&lt;br/&gt; &lt;br/&gt; ጠቃሚ ምክር፦ የተንቀሳቃሽ መሣሪያዎ &lt;b&gt;ቅንብሮች&lt;/b&gt; ምናሌ ውስጥ ወዳለው &lt;b&gt;ቋንቋ እና ግብዓት&lt;/b&gt; በመሄድ መዝገበ-ቃላትን ማውረድና ማስወገድ ይችላሉ።"</string>
<string name="download_over_metered" msgid="1643065851159409546">"አሁን አውርድ (<xliff:g id="SIZE_IN_MEGABYTES">%1$.1f</xliff:g> ሜባ)"</string>
diff --git a/java/src/com/android/inputmethod/event/Event.java b/java/src/com/android/inputmethod/event/Event.java
index ed487e13f..41bf36b36 100644
--- a/java/src/com/android/inputmethod/event/Event.java
+++ b/java/src/com/android/inputmethod/event/Event.java
@@ -168,4 +168,8 @@ public class Event {
public boolean isCommittable() {
return EVENT_INPUT_KEYPRESS == mType || EVENT_MODE_KEY == mType || EVENT_TOGGLE == mType;
}
+
+ public boolean isHandled() {
+ return EVENT_NOT_HANDLED != mType;
+ }
}
diff --git a/java/src/com/android/inputmethod/event/EventInterpreter.java b/java/src/com/android/inputmethod/event/EventInterpreter.java
index 726b9206b..bcf10fc58 100644
--- a/java/src/com/android/inputmethod/event/EventInterpreter.java
+++ b/java/src/com/android/inputmethod/event/EventInterpreter.java
@@ -16,11 +16,6 @@
package com.android.inputmethod.event;
-import android.util.SparseArray;
-import android.view.KeyEvent;
-
-import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.utils.CollectionUtils;
import java.util.ArrayList;
@@ -37,25 +32,9 @@ public class EventInterpreter {
// TODO: Implement an object pool for events, as we'll create a lot of them
// TODO: Create a combiner
// TODO: Create an object type to represent input material + visual feedback + decoding state
- // TODO: Create an interface to call back to Latin IME through the above object
- final EventDecoderSpec mDecoderSpec;
- final SparseArray<HardwareEventDecoder> mHardwareEventDecoders;
- final SoftwareEventDecoder mSoftwareEventDecoder;
- final LatinIME mLatinIme;
- final ArrayList<Combiner> mCombiners;
-
- /**
- * Create a default interpreter.
- *
- * This creates a default interpreter that does nothing. A default interpreter should normally
- * only be used for fallback purposes, when we really don't know what we want to do with input.
- *
- * @param latinIme a reference to the ime.
- */
- public EventInterpreter(final LatinIME latinIme) {
- this(null, latinIme);
- }
+ private final EventDecoderSpec mDecoderSpec;
+ private final ArrayList<Combiner> mCombiners;
/**
* Create an event interpreter according to a specification.
@@ -70,64 +49,10 @@ public class EventInterpreter {
* interpreter that does no specific combining, and assumes the most common cases.
*
* @param specification the specification for event interpretation. null for default.
- * @param latinIme a reference to the ime.
*/
- public EventInterpreter(final EventDecoderSpec specification, final LatinIME latinIme) {
+ public EventInterpreter(final EventDecoderSpec specification) {
mDecoderSpec = null != specification ? specification : new EventDecoderSpec();
- // For both, we expect to have only one decoder in almost all cases, hence the default
- // capacity of 1.
- mHardwareEventDecoders = new SparseArray<HardwareEventDecoder>(1);
- mSoftwareEventDecoder = new SoftwareKeyboardEventDecoder();
mCombiners = CollectionUtils.newArrayList();
mCombiners.add(new DeadKeyCombiner());
- mLatinIme = latinIme;
- }
-
- // Helper method to decode a hardware key event into a generic event, and execute any
- // necessary action.
- public boolean onHardwareKeyEvent(final KeyEvent hardwareKeyEvent) {
- final Event decodedEvent = getHardwareKeyEventDecoder(hardwareKeyEvent.getDeviceId())
- .decodeHardwareKey(hardwareKeyEvent);
- return onEvent(decodedEvent);
- }
-
- public boolean onSoftwareEvent() {
- final Event decodedEvent = getSoftwareEventDecoder().decodeSoftwareEvent();
- return onEvent(decodedEvent);
- }
-
- private HardwareEventDecoder getHardwareKeyEventDecoder(final int deviceId) {
- final HardwareEventDecoder decoder = mHardwareEventDecoders.get(deviceId);
- if (null != decoder) return decoder;
- // TODO: create the decoder according to the specification
- final HardwareEventDecoder newDecoder = new HardwareKeyboardEventDecoder(deviceId);
- mHardwareEventDecoders.put(deviceId, newDecoder);
- return newDecoder;
- }
-
- private SoftwareEventDecoder getSoftwareEventDecoder() {
- // Within the context of Latin IME, since we never present several software interfaces
- // at the time, we should never need multiple software event decoders at a time.
- return mSoftwareEventDecoder;
- }
-
- private boolean onEvent(final Event event) {
- Event currentlyProcessingEvent = event;
- boolean processed = false;
- for (int i = 0; i < mCombiners.size(); ++i) {
- currentlyProcessingEvent = mCombiners.get(i).combine(event);
- }
- while (null != currentlyProcessingEvent) {
- if (currentlyProcessingEvent.isCommittable()) {
- mLatinIme.onCodeInput(currentlyProcessingEvent.mCodePoint,
- Constants.EXTERNAL_KEYBOARD_COORDINATE,
- Constants.EXTERNAL_KEYBOARD_COORDINATE);
- processed = true;
- } else if (event.isDead()) {
- processed = true;
- }
- currentlyProcessingEvent = currentlyProcessingEvent.mNextEvent;
- }
- return processed;
}
}
diff --git a/java/src/com/android/inputmethod/event/SoftwareEventDecoder.java b/java/src/com/android/inputmethod/event/SoftwareEventDecoder.java
deleted file mode 100644
index d81ee0b37..000000000
--- a/java/src/com/android/inputmethod/event/SoftwareEventDecoder.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * 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.event;
-
-/**
- * An event decoder for events out of a software keyboard.
- *
- * This defines the interface for an event decoder that supports events out of a software keyboard.
- * This differs significantly from hardware keyboard event decoders in several respects. First,
- * a software keyboard does not have a scancode/layout system; the keypresses that insert
- * characters output unicode characters directly.
- */
-public interface SoftwareEventDecoder extends EventDecoder {
- public Event decodeSoftwareEvent();
-}
diff --git a/java/src/com/android/inputmethod/event/SoftwareKeyboardEventDecoder.java b/java/src/com/android/inputmethod/event/SoftwareKeyboardEventDecoder.java
deleted file mode 100644
index de91567c7..000000000
--- a/java/src/com/android/inputmethod/event/SoftwareKeyboardEventDecoder.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * 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.event;
-
-/**
- * A decoder for events from software keyboard, like the ones displayed by Latin IME.
- */
-public class SoftwareKeyboardEventDecoder implements SoftwareEventDecoder {
- @Override
- public Event decodeSoftwareEvent() {
- return null;
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 222e73529..4a18c2b3c 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -45,6 +45,7 @@ import android.text.TextUtils;
import android.util.Log;
import android.util.PrintWriterPrinter;
import android.util.Printer;
+import android.util.SparseArray;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
@@ -60,6 +61,8 @@ 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.HardwareEventDecoder;
+import com.android.inputmethod.event.HardwareKeyboardEventDecoder;
import com.android.inputmethod.event.InputTransaction;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.KeyboardActionListener;
@@ -120,6 +123,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private final Settings mSettings;
private final InputLogic mInputLogic = new InputLogic(this /* LatinIME */,
this /* SuggestionStripViewAccessor */);
+ // We expect to have only one decoder in almost all cases, hence the default capacity of 1.
+ // If it turns out we need several, it will get grown seamlessly.
+ final SparseArray<HardwareEventDecoder> mHardwareEventDecoders
+ = new SparseArray<HardwareEventDecoder>(1);
private View mExtractArea;
private View mKeyPreviewBackingView;
@@ -643,9 +650,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.getInstance().initDictionary(newSuggest.mDictionaryFacilitator);
}
- final Suggest oldSuggest = mInputLogic.mSuggest;
- mInputLogic.mSuggest = newSuggest;
- if (oldSuggest != null) oldSuggest.close();
+ mInputLogic.replaceSuggest(newSuggest);
refreshPersonalizationDictionarySession();
}
@@ -1588,19 +1593,31 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
}
+ private HardwareEventDecoder getHardwareKeyEventDecoder(final int deviceId) {
+ final HardwareEventDecoder decoder = mHardwareEventDecoders.get(deviceId);
+ if (null != decoder) return decoder;
+ // TODO: create the decoder according to the specification
+ final HardwareEventDecoder newDecoder = new HardwareKeyboardEventDecoder(deviceId);
+ mHardwareEventDecoders.put(deviceId, newDecoder);
+ return newDecoder;
+ }
+
// Hooks for hardware keyboard
@Override
- public boolean onKeyDown(final int keyCode, final KeyEvent event) {
- if (!ProductionFlag.IS_HARDWARE_KEYBOARD_SUPPORTED) return super.onKeyDown(keyCode, event);
- // onHardwareKeyEvent, like onKeyDown returns true if it handled the event, false if
- // it doesn't know what to do with it and leave it to the application. For example,
- // hardware key events for adjusting the screen's brightness are passed as is.
- if (mInputLogic.mEventInterpreter.onHardwareKeyEvent(event)) {
- final long keyIdentifier = event.getDeviceId() << 32 + event.getKeyCode();
- mInputLogic.mCurrentlyPressedHardwareKeys.add(keyIdentifier);
+ public boolean onKeyDown(final int keyCode, final KeyEvent keyEvent) {
+ if (!ProductionFlag.IS_HARDWARE_KEYBOARD_SUPPORTED) {
+ return super.onKeyDown(keyCode, keyEvent);
+ }
+ final Event event = getHardwareKeyEventDecoder(
+ keyEvent.getDeviceId()).decodeHardwareKey(keyEvent);
+ // If the event is not handled by LatinIME, we just pass it to the parent implementation.
+ // If it's handled, we return true because we did handle it.
+ if (event.isHandled()) {
+ mInputLogic.onCodeInput(mSettings.getCurrent(), event,
+ mKeyboardSwitcher.getKeyboardShiftMode(), mHandler);
return true;
}
- return super.onKeyDown(keyCode, event);
+ return super.onKeyDown(keyCode, keyEvent);
}
@Override
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index cb55aa06c..fa7c4b4fc 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -80,8 +80,6 @@ public final class InputLogic {
public SuggestedWords mSuggestedWords = SuggestedWords.EMPTY;
// TODO: mSuggest should be touched by a single thread.
public volatile Suggest mSuggest;
- // The event interpreter should never be null.
- public final EventInterpreter mEventInterpreter;
public LastComposedWord mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
public final WordComposer mWordComposer;
@@ -104,11 +102,19 @@ public final class InputLogic {
mLatinIME = latinIME;
mSuggestionStripViewAccessor = suggestionStripViewAccessor;
mWordComposer = new WordComposer();
- mEventInterpreter = new EventInterpreter(latinIME);
mConnection = new RichInputConnection(latinIME);
mInputLogicHandler = InputLogicHandler.NULL_HANDLER;
}
+ // Replace the old Suggest with the passed Suggest and close it.
+ public void replaceSuggest(final Suggest newSuggest) {
+ final Suggest oldSuggest = mSuggest;
+ mSuggest = newSuggest;
+ if (oldSuggest != null) {
+ oldSuggest.close();
+ }
+ }
+
/**
* Initializes the input logic for input in an editor.
*
diff --git a/native/jni/src/defines.h b/native/jni/src/defines.h
index 4c57af0ba..4e6ff9556 100644
--- a/native/jni/src/defines.h
+++ b/native/jni/src/defines.h
@@ -344,10 +344,6 @@ static inline void prof_out(void) {
#define MAX_POINTER_COUNT 1
#define MAX_POINTER_COUNT_G 2
-// DEBUG
-#define INPUTLENGTH_FOR_DEBUG (-1)
-#define MIN_OUTPUT_INDEX_FOR_DEBUG (-1)
-
#define DISALLOW_DEFAULT_CONSTRUCTOR(TypeName) \
TypeName() = delete
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_scoring.h b/native/jni/src/suggest/policyimpl/typing/typing_scoring.h
index 7ef905df7..8982800b7 100644
--- a/native/jni/src/suggest/policyimpl/typing/typing_scoring.h
+++ b/native/jni/src/suggest/policyimpl/typing/typing_scoring.h
@@ -32,25 +32,24 @@ class TypingScoring : public Scoring {
public:
static const TypingScoring *getInstance() { return &sInstance; }
- AK_FORCE_INLINE bool getMostProbableString(
- const DicTraverseSession *const traverseSession, const int terminalSize,
- const float languageWeight, int *const outputCodePoints, int *const type,
- int *const freq) const {
+ AK_FORCE_INLINE bool getMostProbableString(const DicTraverseSession *const traverseSession,
+ const int terminalSize, const float languageWeight, int *const outputCodePoints,
+ int *const type, int *const freq) const {
return false;
}
- AK_FORCE_INLINE void safetyNetForMostProbableString(const int scoreCount,
- const int maxScore, int *const outputCodePoints, int *const scores) const {
+ AK_FORCE_INLINE void safetyNetForMostProbableString(const int scoreCount, const int maxScore,
+ int *const outputCodePoints, int *const scores) const {
}
AK_FORCE_INLINE float getAdjustedLanguageWeight(DicTraverseSession *const traverseSession,
- DicNode *const terminals, const int size) const {
+ DicNode *const terminals, const int size) const {
return 1.0f;
}
- AK_FORCE_INLINE int calculateFinalScore(const float compoundDistance,
- const int inputSize, const ErrorTypeUtils::ErrorType containedErrorTypes,
- const bool forceCommit, const bool boostExactMatches) const {
+ AK_FORCE_INLINE int calculateFinalScore(const float compoundDistance, const int inputSize,
+ const ErrorTypeUtils::ErrorType containedErrorTypes, const bool forceCommit,
+ const bool boostExactMatches) const {
const float maxDistance = ScoringParams::DISTANCE_WEIGHT_LANGUAGE
+ static_cast<float>(inputSize) * ScoringParams::TYPING_MAX_OUTPUT_SCORE_PER_INPUT;
float score = ScoringParams::TYPING_BASE_OUTPUT_SCORE - compoundDistance / maxDistance;
@@ -85,8 +84,8 @@ class TypingScoring : public Scoring {
return true;
}
- AK_FORCE_INLINE bool sameAsTyped(
- const DicTraverseSession *const traverseSession, const DicNode *const dicNode) const {
+ AK_FORCE_INLINE bool sameAsTyped(const DicTraverseSession *const traverseSession,
+ const DicNode *const dicNode) const {
return traverseSession->getProximityInfoState(0)->sameAsTyped(
dicNode->getOutputWordBuf(), dicNode->getNodeCodePointCount());
}
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_weighting.h b/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
index 41314ef52..b36605af9 100644
--- a/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
+++ b/native/jni/src/suggest/policyimpl/typing/typing_weighting.h
@@ -72,8 +72,6 @@ class TypingWeighting : public Weighting {
float getMatchedCost(const DicTraverseSession *const traverseSession,
const DicNode *const dicNode, DicNode_InputStateG *inputStateG) const {
const int pointIndex = dicNode->getInputIndex(0);
- // Note: min() required since length can be MAX_POINT_TO_KEY_LENGTH for characters not on
- // the keyboard (like accented letters)
const float normalizedSquaredLength = traverseSession->getProximityInfoState(0)
->getPointToKeyLength(pointIndex,
CharUtils::toBaseLowerCase(dicNode->getNodeCodePoint()));
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/Hebrew.java b/tests/src/com/android/inputmethod/keyboard/layout/Hebrew.java
new file mode 100644
index 000000000..a5befab00
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/Hebrew.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * 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.layout;
+
+import com.android.inputmethod.keyboard.layout.Symbols.RtlSymbols;
+import com.android.inputmethod.keyboard.layout.SymbolsShifted.RtlSymbolsShifted;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKey;
+import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
+import com.android.inputmethod.latin.Constants;
+
+import java.util.Locale;
+
+public final class Hebrew extends LayoutBase {
+ private static final String LAYOUT_NAME = "hebrew";
+
+ public Hebrew(final LayoutCustomizer customizer) {
+ super(customizer, HebrewSymbols.class, RtlSymbolsShifted.class);
+ }
+
+ @Override
+ public String getName() { return LAYOUT_NAME; }
+
+ public static class HebrewCustomizer extends LayoutCustomizer {
+ public HebrewCustomizer(final Locale locale) {
+ super(locale);
+ }
+
+ @Override
+ public ExpectedKey getAlphabetKey() { return HEBREW_ALPHABET_KEY; }
+
+ @Override
+ public ExpectedKey getCurrencyKey() { return CURRENCY_NEW_SHEQEL; }
+
+ @Override
+ public ExpectedKey[] getOtherCurrencyKeys() {
+ return SymbolsShifted.CURRENCIES_OTHER_GENERIC;
+ }
+
+ @Override
+ public ExpectedKey[] getDoubleQuoteMoreKeys() { return Symbols.DOUBLE_QUOTES_LR9; }
+
+ @Override
+ public ExpectedKey[] getSingleQuoteMoreKeys() { return Symbols.SINGLE_QUOTES_LR9; }
+
+ @Override
+ public ExpectedKey[] getDoubleAngleQuoteKeys() {
+ return RtlSymbols.DOUBLE_ANGLE_QUOTES_LR_RTL;
+ }
+
+ @Override
+ public ExpectedKey[] getSingleAngleQuoteKeys() {
+ return RtlSymbols.SINGLE_ANGLE_QUOTES_LR_RTL;
+ }
+
+ @Override
+ public ExpectedKey[] getLeftShiftKeys(final boolean isPhone) {
+ return EMPTY_KEYS;
+ }
+
+ @Override
+ public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
+ return isPhone ? EMPTY_KEYS : EXCLAMATION_AND_QUESTION_MARKS;
+ }
+
+ @Override
+ public ExpectedKey[] getPunctuationMoreKeys(final boolean isPhone) {
+ return isPhone ? RTL_PHONE_PUNCTUATION_MORE_KEYS
+ : RTL_TABLET_PUNCTUATION_MORE_KEYS;
+ }
+
+ // U+05D0: "א" HEBREW LETTER ALEF
+ // U+05D1: "ב" HEBREW LETTER BET
+ // U+05D2: "ג" HEBREW LETTER GIMEL
+ private static final ExpectedKey HEBREW_ALPHABET_KEY = key(
+ "\u05D0\u05D1\u05D2", Constants.CODE_SWITCH_ALPHA_SYMBOL);
+ // U+20AA: "₪" NEW SHEQEL SIGN
+ private static final ExpectedKey CURRENCY_NEW_SHEQEL = key("\u20AA",
+ Symbols.CURRENCY_GENERIC_MORE_KEYS);
+ private static final ExpectedKey[] RTL_PHONE_PUNCTUATION_MORE_KEYS = joinKeys(
+ ";", "/", key("(", ")"), key(")", "("), "#", "!", ",", "?",
+ "&", "%", "+", "\"", "-", ":", "'", "@");
+ // Punctuation more keys for tablet form factor.
+ private static final ExpectedKey[] RTL_TABLET_PUNCTUATION_MORE_KEYS = joinKeys(
+ ";", "/", key("(", ")"), key(")", "("), "#", "'", ",",
+ "&", "%", "+", "\"", "-", ":", "@");
+ }
+
+ @Override
+ ExpectedKey[][] getCommonAlphabetLayout(final boolean isPhone) { return ALPHABET_COMMON; }
+
+ @Override
+ ExpectedKey[][] getCommonAlphabetShiftLayout(final boolean isPhone, final int elementId) {
+ return null;
+ }
+
+ private static final ExpectedKey[][] ALPHABET_COMMON = new ExpectedKeyboardBuilder()
+ .setKeysOfRow(1,
+ key("'", joinMoreKeys("1", "\"")),
+ key("-", joinMoreKeys("2", "_")),
+ // U+05E7: "ק" HEBREW LETTER QOF
+ key("\u05E7", moreKey("3")),
+ // U+05E8: "ר" HEBREW LETTER RESH
+ key("\u05E8", moreKey("4")),
+ // U+05D0: "א" HEBREW LETTER ALEF
+ key("\u05D0", moreKey("5")),
+ // U+05D8: "ט" HEBREW LETTER TET
+ key("\u05D8", moreKey("6")),
+ // U+05D5: "ו" HEBREW LETTER VAV
+ key("\u05D5", moreKey("7")),
+ // U+05DF: "ן" HEBREW LETTER FINAL NUN
+ key("\u05DF", moreKey("8")),
+ // U+05DD: "ם" HEBREW LETTER FINAL MEM
+ key("\u05DD", moreKey("9")),
+ // U+05E4: "פ" HEBREW LETTER PE
+ key("\u05E4", moreKey("0")))
+ .setKeysOfRow(2,
+ // U+05E9: "ש" HEBREW LETTER SHIN
+ key("\u05E9"),
+ // U+05D3: "ד" HEBREW LETTER DALET
+ key("\u05D3"),
+ // U+05D2: "ג" HEBREW LETTER GIMEL
+ // U+05D2 U+05F3: "ג׳" HEBREW LETTER GIMEL + HEBREW PUNCTUATION GERESH
+ key("\u05D2", moreKey("\u05D2\u05F3")),
+ // U+05DB: "כ" HEBREW LETTER KAF
+ key("\u05DB"),
+ // U+05E2: "ע" HEBREW LETTER AYIN
+ key("\u05E2"),
+ // U+05D9: "י" HEBREW LETTER YOD
+ // U+05F2 U+05B7: "ײַ" HEBREW LIGATURE YIDDISH DOUBLE YOD + HEBREW POINT PATAH
+ key("\u05D9", moreKey("\u05F2\u05B7")),
+ // U+05D7: "ח" HEBREW LETTER HET
+ // U+05D7 U+05F3: "ח׳" HEBREW LETTER HET + HEBREW PUNCTUATION GERESH
+ key("\u05D7", moreKey("\u05D7\u05F3")),
+ // U+05DC: "ל" HEBREW LETTER LAMED
+ key("\u05DC"),
+ // U+05DA: "ך" HEBREW LETTER FINAL KAF
+ key("\u05DA"),
+ // U+05E3: "ף" HEBREW LETTER FINAL PE
+ key("\u05E3"))
+ .setKeysOfRow(3,
+ // U+05D6: "ז" HEBREW LETTER ZAYIN
+ // U+05D6 U+05F3: "ז׳" HEBREW LETTER ZAYIN + HEBREW PUNCTUATION GERESH
+ key("\u05D6", moreKey("\u05D6\u05F3")),
+ // U+05E1: "ס" HEBREW LETTER SAMEKH
+ key("\u05E1"),
+ // U+05D1: "ב" HEBREW LETTER BET
+ key("\u05D1"),
+ // U+05D4: "ה" HEBREW LETTER HE
+ key("\u05D4"),
+ // U+05E0: "נ" HEBREW LETTER NUN
+ key("\u05E0"),
+ // U+05DE: "מ" HEBREW LETTER MEM
+ key("\u05DE"),
+ // U+05E6: "צ" HEBREW LETTER TSADI
+ // U+05E6 U+05F3: "צ׳" HEBREW LETTER TSADI + HEBREW PUNCTUATION GERESH
+ key("\u05E6", moreKey("\u05E6\u05F3")),
+ // U+05EA: "ת" HEBREW LETTER TAV
+ // U+05EA U+05F3: "ת׳" HEBREW LETTER TAV + HEBREW PUNCTUATION GERESH
+ key("\u05EA", moreKey("\u05EA\u05F3")),
+ // U+05E5: "ץ" HEBREW LETTER FINAL TSADI
+ // U+05E5 U+05F3: "ץ׳" HEBREW LETTER FINAL TSADI + HEBREW PUNCTUATION GERESH
+ key("\u05E5", moreKey("\u05E5\u05F3")))
+ .build();
+
+ private static class HebrewSymbols extends RtlSymbols {
+ public HebrewSymbols(final LayoutCustomizer customizer) {
+ super(customizer);
+ }
+
+ @Override
+ public ExpectedKey[][] getLayout(final boolean isPhone) {
+ return new ExpectedKeyboardBuilder(super.getLayout(isPhone))
+ // U+00B1: "±" PLUS-MINUS SIGN
+ // U+FB29: "﬩" HEBREW LETTER ALTERNATIVE PLUS SIGN
+ .setMoreKeysOf("+", "\u00B1", "\uFB29")
+ // U+2605: "★" BLACK STAR
+ .setMoreKeysOf("*", "\u2605")
+ .build();
+ }
+ }
+}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHebrew.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHebrew.java
new file mode 100644
index 000000000..c0243a870
--- /dev/null
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHebrew.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * 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.layout.tests;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.inputmethod.keyboard.layout.Hebrew;
+import com.android.inputmethod.keyboard.layout.Hebrew.HebrewCustomizer;
+import com.android.inputmethod.keyboard.layout.LayoutBase;
+
+import java.util.Locale;
+
+/**
+ * iw: Hebrew/hebrew
+ */
+@SmallTest
+public class TestsHebrew extends LayoutTestsBase {
+ private static final Locale LOCALE = new Locale("iw");
+ private static final LayoutBase LAYOUT = new Hebrew(new HebrewCustomizer(LOCALE));
+
+ @Override
+ LayoutBase getLayout() { return LAYOUT; }
+}