Shift+Smiley key will register newline character of textMultiLine

This change also
 * Honors the custom action label in EditorInfo.actionLabel.
 * Invokes InputConnection.performeEditorAction if action is specifed
   at EditorInfo.imeOptions or actionLabel/actionId.
 * Stops using InputMethodService.sendKeyChar. Implements
   sendKeyCodePoint instead.

Bug: 2498607
Bug: 5961809
Bug: 5368408
Change-Id: If4cd5eb3dacfc6b6a7ea434b0617c2438e06e42d
This commit is contained in:
Tadashi G. Takaoka 2012-02-07 17:07:23 +09:00
parent 82efc941ba
commit 7a39bd4454
49 changed files with 515 additions and 283 deletions

View file

@ -232,10 +232,7 @@
been replaced, those remaining entries are appended at the end of moreKeys. --> been replaced, those remaining entries are appended at the end of moreKeys. -->
<attr name="additionalMoreKeys" format="string" /> <attr name="additionalMoreKeys" format="string" />
<!-- Maximum column of more keys keyboard --> <!-- Maximum column of more keys keyboard -->
<attr name="maxMoreKeysColumn" format="integer"> <attr name="maxMoreKeysColumn" format="integer" />
<!-- This should be aligned with -->
<flag name="fixedWidthMoreKeysColumn" value="0x8000000" />
</attr>
<attr name="backgroundType" format="enum"> <attr name="backgroundType" format="enum">
<!-- This should be aligned with Key.BACKGROUND_TYPE_* --> <!-- This should be aligned with Key.BACKGROUND_TYPE_* -->
<enum name="normal" value="0" /> <enum name="normal" value="0" />
@ -281,10 +278,13 @@
<!-- If true, use keyShiftedLetterHintActivatedColor for the shifted letter hint and <!-- If true, use keyShiftedLetterHintActivatedColor for the shifted letter hint and
keyTextInactivatedColor for the primary key top label. --> keyTextInactivatedColor for the primary key top label. -->
<flag name="shiftedLetterActivated" value="0x10000" /> <flag name="shiftedLetterActivated" value="0x10000" />
<!-- If true, use EditorInfo.actionLabel for the key label. -->
<flag name="fromCustomActionLabel" value="0x20000" />
</attr> </attr>
<!-- The icon to display on the key instead of the label. --> <!-- The icon to display on the key instead of the label. -->
<attr name="keyIcon" format="enum"> <attr name="keyIcon" format="enum">
<!-- This should be aligned with the KeyboardIconsSet.ICON_* --> <!-- This should be aligned with the KeyboardIconsSet.ICON_* -->
<enum name="iconUndefined" value="0" />
<enum name="iconShiftKey" value="1" /> <enum name="iconShiftKey" value="1" />
<enum name="iconDeleteKey" value="2" /> <enum name="iconDeleteKey" value="2" />
<enum name="iconSettingsKey" value="3" /> <enum name="iconSettingsKey" value="3" />
@ -368,6 +368,7 @@
<attr name="clobberSettingsKey" format="boolean" /> <attr name="clobberSettingsKey" format="boolean" />
<attr name="shortcutKeyEnabled" format="boolean" /> <attr name="shortcutKeyEnabled" format="boolean" />
<attr name="hasShortcutKey" format="boolean" /> <attr name="hasShortcutKey" format="boolean" />
<attr name="isMultiLine" format="boolean" />
<attr name="imeAction" format="enum"> <attr name="imeAction" format="enum">
<!-- This should be aligned with EditorInfo.IME_ACTION_* --> <!-- This should be aligned with EditorInfo.IME_ACTION_* -->
<enum name="actionUnspecified" value="0" /> <enum name="actionUnspecified" value="0" />
@ -378,6 +379,8 @@
<enum name="actionNext" value="5" /> <enum name="actionNext" value="5" />
<enum name="actionDone" value="6" /> <enum name="actionDone" value="6" />
<enum name="actionPrevious" value="7" /> <enum name="actionPrevious" value="7" />
<!-- This should be aligned with KeyboardId.IME_ACTION_* -->
<enum name="actionCustomLabel" value="0x100" />
</attr> </attr>
<attr name="localeCode" format="string" /> <attr name="localeCode" format="string" />
<attr name="languageCode" format="string" /> <attr name="languageCode" format="string" />

View file

@ -25,9 +25,10 @@
<integer name="key_space">32</integer> <integer name="key_space">32</integer>
<integer name="key_shift">-1</integer> <integer name="key_shift">-1</integer>
<integer name="key_switch_alpha_symbol">-2</integer> <integer name="key_switch_alpha_symbol">-2</integer>
<integer name="key_output_text">-4</integer> <integer name="key_output_text">-3</integer>
<integer name="key_delete">-5</integer> <integer name="key_delete">-4</integer>
<integer name="key_settings">-6</integer> <integer name="key_settings">-5</integer>
<integer name="key_shortcut">-7</integer> <integer name="key_shortcut">-6</integer>
<integer name="key_action_enter">-7</integer>
<integer name="key_unspecified">-9</integer> <integer name="key_unspecified">-9</integer>
</resources> </resources>

View file

@ -128,6 +128,8 @@
<string name="label_go_key">Go</string> <string name="label_go_key">Go</string>
<!-- Label for soft enter key when it performs NEXT action. Must be short to fit on key! [CHAR LIMIT=5] --> <!-- Label for soft enter key when it performs NEXT action. Must be short to fit on key! [CHAR LIMIT=5] -->
<string name="label_next_key">Next</string> <string name="label_next_key">Next</string>
<!-- Label for soft enter key when it performs PREVIOUS action. Must be short to fit on key! [CHAR LIMIT=5] -->
<string name="label_previous_key">Prev</string>
<!-- Label for soft enter key when it performs DONE action. Must be short to fit on key! [CHAR LIMIT=5] --> <!-- Label for soft enter key when it performs DONE action. Must be short to fit on key! [CHAR LIMIT=5] -->
<string name="label_done_key">Done</string> <string name="label_done_key">Done</string>
<!-- Label for soft enter key when it performs SEND action. Must be short to fit on key! [CHAR LIMIT=5] --> <!-- Label for soft enter key when it performs SEND action. Must be short to fit on key! [CHAR LIMIT=5] -->

View file

@ -89,12 +89,8 @@
latin:keyIcon="iconDeleteKey" latin:keyIcon="iconDeleteKey"
latin:keyActionFlags="isRepeatable|noKeyPreview" latin:keyActionFlags="isRepeatable|noKeyPreview"
latin:backgroundType="functional" /> latin:backgroundType="functional" />
<key-style <include
latin:styleName="returnKeyStyle" latin:keyboardLayout="@xml/key_styles_enter_tablet" />
latin:code="@integer/key_return"
latin:keyIcon="iconReturnKey"
latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
<key-style <key-style
latin:styleName="spaceKeyStyle" latin:styleName="spaceKeyStyle"
latin:code="@integer/key_space" latin:code="@integer/key_space"

View file

@ -50,7 +50,7 @@
latin:keyLabel="l" latin:keyLabel="l"
latin:moreKeys="@string/more_keys_for_l" /> latin:moreKeys="@string/more_keys_for_l" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyXPos="-14.6%p" latin:keyXPos="-14.6%p"
latin:keyWidth="fillBoth" /> latin:keyWidth="fillBoth" />
</Row> </Row>

View file

@ -138,7 +138,7 @@
<Key <Key
latin:keyLabel="ط" /> latin:keyLabel="ط" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyXPos="-14.6%p" latin:keyXPos="-14.6%p"
latin:keyWidth="fillBoth" /> latin:keyWidth="fillBoth" />
</Row> </Row>

View file

@ -90,7 +90,7 @@
<Key <Key
latin:keyLabel="m" /> latin:keyLabel="m" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyXPos="-14.6%p" latin:keyXPos="-14.6%p"
latin:keyWidth="fillBoth" /> latin:keyWidth="fillBoth" />
</Row> </Row>

View file

@ -80,7 +80,7 @@
<Key <Key
latin:keyLabel="ь" /> latin:keyLabel="ь" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyWidth="fillBoth" /> latin:keyWidth="fillBoth" />
</Row> </Row>
<Row <Row

View file

@ -106,7 +106,7 @@
latin:keyLabel="ץ" latin:keyLabel="ץ"
latin:moreKeys="ץ׳" /> latin:moreKeys="ץ׳" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyXPos="-10.400%p" latin:keyXPos="-10.400%p"
latin:keyWidth="fillBoth" /> latin:keyWidth="fillBoth" />
</Row> </Row>

View file

@ -78,7 +78,7 @@
latin:keyLabel="6" latin:keyLabel="6"
latin:keyStyle="numKeyStyle" /> latin:keyStyle="numKeyStyle" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyXPos="-11.00%p" latin:keyXPos="-11.00%p"
latin:keyWidth="fillRight" /> latin:keyWidth="fillRight" />
</Row> </Row>

View file

@ -47,7 +47,7 @@
<Key <Key
latin:keyStyle="num6KeyStyle" /> latin:keyStyle="num6KeyStyle" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyXPos="-11.00%p" latin:keyXPos="-11.00%p"
latin:keyWidth="fillRight" /> latin:keyWidth="fillRight" />
</Row> </Row>

View file

@ -75,7 +75,7 @@
<Key <Key
latin:keyStyle="num6KeyStyle" /> latin:keyStyle="num6KeyStyle" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyXPos="-11.00%p" latin:keyXPos="-11.00%p"
latin:keyWidth="fillRight" /> latin:keyWidth="fillRight" />
</Row> </Row>

View file

@ -95,7 +95,7 @@
latin:keyLabel="@string/keylabel_for_scandinavia_row2_11" latin:keyLabel="@string/keylabel_for_scandinavia_row2_11"
latin:moreKeys="@string/more_keys_for_scandinavia_row2_11" /> latin:moreKeys="@string/more_keys_for_scandinavia_row2_11" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyXPos="-14.6%p" latin:keyXPos="-14.6%p"
latin:keyWidth="fillBoth" /> latin:keyWidth="fillBoth" />
</Row> </Row>

View file

@ -80,7 +80,7 @@
<Key <Key
latin:keyLabel="ћ" /> latin:keyLabel="ћ" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyXPos="-14.6%p" latin:keyXPos="-14.6%p"
latin:keyWidth="fillBoth" /> latin:keyWidth="fillBoth" />
</Row> </Row>

View file

@ -87,7 +87,7 @@
<Key <Key
latin:keyLabel="э" /> latin:keyLabel="э" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyXPos="-14.6%p" latin:keyXPos="-14.6%p"
latin:keyWidth="fillBoth" /> latin:keyWidth="fillBoth" />
</Row> </Row>

View file

@ -56,7 +56,7 @@
<Key <Key
latin:keyLabel="ñ" /> latin:keyLabel="ñ" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyXPos="-14.6%p" latin:keyXPos="-14.6%p"
latin:keyWidth="fillBoth" /> latin:keyWidth="fillBoth" />
</Row> </Row>

View file

@ -98,7 +98,7 @@
<include <include
latin:keyboardLayout="@xml/keys_parentheses" /> latin:keyboardLayout="@xml/keys_parentheses" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyXPos="-14.6%p" latin:keyXPos="-14.6%p"
latin:keyWidth="fillBoth" /> latin:keyWidth="fillBoth" />
</Row> </Row>

View file

@ -80,7 +80,7 @@
<include <include
latin:keyboardLayout="@xml/keys_curly_brackets" /> latin:keyboardLayout="@xml/keys_curly_brackets" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyXPos="-14.6%p" latin:keyXPos="-14.6%p"
latin:keyWidth="fillBoth" /> latin:keyWidth="fillBoth" />
</Row> </Row>

View file

@ -71,12 +71,8 @@
latin:keyIcon="iconDeleteKey" latin:keyIcon="iconDeleteKey"
latin:keyActionFlags="isRepeatable|noKeyPreview" latin:keyActionFlags="isRepeatable|noKeyPreview"
latin:backgroundType="functional" /> latin:backgroundType="functional" />
<key-style <include
latin:styleName="returnKeyStyle" latin:keyboardLayout="@xml/key_styles_enter_tablet" />
latin:code="@integer/key_return"
latin:keyIcon="iconReturnKey"
latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
<key-style <key-style
latin:styleName="spaceKeyStyle" latin:styleName="spaceKeyStyle"
latin:code="@integer/key_space" latin:code="@integer/key_space"

View file

@ -53,7 +53,7 @@
latin:keyLabel="l" latin:keyLabel="l"
latin:moreKeys="@string/more_keys_for_l" /> latin:moreKeys="@string/more_keys_for_l" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyXPos="-15.704%p" latin:keyXPos="-15.704%p"
latin:keyWidth="fillBoth" /> latin:keyWidth="fillBoth" />
</Row> </Row>

View file

@ -144,7 +144,7 @@
<Key <Key
latin:keyLabel="ط" /> latin:keyLabel="ط" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyXPos="-9.375%p" latin:keyXPos="-9.375%p"
latin:keyWidth="fillBoth" /> latin:keyWidth="fillBoth" />
</Row> </Row>

View file

@ -97,7 +97,7 @@
<Key <Key
latin:keyLabel="m" /> latin:keyLabel="m" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyXPos="-15.704%p" latin:keyXPos="-15.704%p"
latin:keyWidth="fillBoth" /> latin:keyWidth="fillBoth" />
</Row> </Row>

View file

@ -86,7 +86,7 @@
<Key <Key
latin:keyLabel="ь" /> latin:keyLabel="ь" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyWidth="fillBoth" /> latin:keyWidth="fillBoth" />
</Row> </Row>
<Row <Row

View file

@ -111,7 +111,7 @@
latin:keyLabel="ץ" latin:keyLabel="ץ"
latin:moreKeys="ץ׳" /> latin:moreKeys="ץ׳" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyXPos="-10.400%p" latin:keyXPos="-10.400%p"
latin:keyWidth="fillBoth" /> latin:keyWidth="fillBoth" />
</Row> </Row>

View file

@ -80,7 +80,7 @@
latin:keyLabel="6" latin:keyLabel="6"
latin:keyStyle="numKeyStyle" /> latin:keyStyle="numKeyStyle" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyXPos="-11.172%p" latin:keyXPos="-11.172%p"
latin:keyWidth="fillRight" /> latin:keyWidth="fillRight" />
</Row> </Row>

View file

@ -49,7 +49,7 @@
<Key <Key
latin:keyStyle="num6KeyStyle" /> latin:keyStyle="num6KeyStyle" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyXPos="-11.172%p" latin:keyXPos="-11.172%p"
latin:keyWidth="fillRight" /> latin:keyWidth="fillRight" />
</Row> </Row>

View file

@ -78,7 +78,7 @@
<Key <Key
latin:keyStyle="num6KeyStyle" /> latin:keyStyle="num6KeyStyle" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyXPos="-11.172%p" latin:keyXPos="-11.172%p"
latin:keyWidth="fillRight" /> latin:keyWidth="fillRight" />
</Row> </Row>

View file

@ -102,7 +102,7 @@
latin:keyLabel="@string/keylabel_for_scandinavia_row2_11" latin:keyLabel="@string/keylabel_for_scandinavia_row2_11"
latin:moreKeys="@string/more_keys_for_scandinavia_row2_11" /> latin:moreKeys="@string/more_keys_for_scandinavia_row2_11" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyXPos="-9.375%p" latin:keyXPos="-9.375%p"
latin:keyWidth="fillBoth" /> latin:keyWidth="fillBoth" />
</Row> </Row>

View file

@ -114,7 +114,7 @@
<include <include
latin:keyboardLayout="@xml/keys_comma_period" /> latin:keyboardLayout="@xml/keys_comma_period" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyXPos="-13.750%p" latin:keyXPos="-13.750%p"
latin:keyWidth="fillRight" /> latin:keyWidth="fillRight" />
</Row> </Row>

View file

@ -92,7 +92,7 @@
<Key <Key
latin:keyLabel="э" /> latin:keyLabel="э" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyXPos="-9.375%p" latin:keyXPos="-9.375%p"
latin:keyWidth="fillBoth" /> latin:keyWidth="fillBoth" />
</Row> </Row>

View file

@ -59,7 +59,7 @@
<Key <Key
latin:keyLabel="ñ" /> latin:keyLabel="ñ" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyXPos="-15.704%p" latin:keyXPos="-15.704%p"
latin:keyWidth="fillBoth" /> latin:keyWidth="fillBoth" />
</Row> </Row>

View file

@ -105,7 +105,7 @@
<include <include
latin:keyboardLayout="@xml/keys_parentheses" /> latin:keyboardLayout="@xml/keys_parentheses" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyXPos="-15.704%p" latin:keyXPos="-15.704%p"
latin:keyWidth="fillBoth" /> latin:keyWidth="fillBoth" />
</Row> </Row>

View file

@ -87,7 +87,7 @@
<include <include
latin:keyboardLayout="@xml/keys_curly_brackets" /> latin:keyboardLayout="@xml/keys_curly_brackets" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyXPos="-15.704%p" latin:keyXPos="-15.704%p"
latin:keyWidth="fillBoth" /> latin:keyWidth="fillBoth" />
</Row> </Row>

View file

@ -98,99 +98,8 @@
latin:keyIcon="iconDeleteKey" latin:keyIcon="iconDeleteKey"
latin:keyActionFlags="isRepeatable|noKeyPreview" latin:keyActionFlags="isRepeatable|noKeyPreview"
latin:backgroundType="functional" /> latin:backgroundType="functional" />
<!-- Return key style --> <include
<key-style latin:keyboardLayout="@xml/key_styles_enter_phone" />
latin:styleName="defaultReturnKeyStyle"
latin:code="@integer/key_return"
latin:keyIcon="iconReturnKey"
latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
<switch>
<case
latin:mode="im"
>
<!-- Smiley key. -->
<switch>
<case
latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted"
>
<key-style
latin:styleName="returnKeyStyle"
latin:parentStyle="defaultReturnKeyStyle" />
</case>
<default>
<key-style
latin:styleName="returnKeyStyle"
latin:keyLabel=":-)"
latin:keyOutputText=":-) "
latin:keyLabelFlags="hasPopupHint|preserveCase"
latin:moreKeys="@string/more_keys_for_smiley"
latin:maxMoreKeysColumn="5"
latin:backgroundType="functional" />
</default>
</switch>
</case>
<case
latin:imeAction="actionGo"
>
<key-style
latin:styleName="returnKeyStyle"
latin:code="@integer/key_return"
latin:keyLabel="@string/label_go_key"
latin:keyLabelFlags="autoXScale|preserveCase"
latin:keyActionFlags="noKeyPreview"
latin:backgroundType="action" />
</case>
<case
latin:imeAction="actionNext"
>
<key-style
latin:styleName="returnKeyStyle"
latin:code="@integer/key_return"
latin:keyLabel="@string/label_next_key"
latin:keyLabelFlags="autoXScale|preserveCase"
latin:keyActionFlags="noKeyPreview"
latin:backgroundType="action" />
</case>
<case
latin:imeAction="actionDone"
>
<key-style
latin:styleName="returnKeyStyle"
latin:code="@integer/key_return"
latin:keyLabel="@string/label_done_key"
latin:keyLabelFlags="autoXScale|preserveCase"
latin:keyActionFlags="noKeyPreview"
latin:backgroundType="action" />
</case>
<case
latin:imeAction="actionSend"
>
<key-style
latin:styleName="returnKeyStyle"
latin:code="@integer/key_return"
latin:keyLabel="@string/label_send_key"
latin:keyLabelFlags="autoXScale|preserveCase"
latin:keyActionFlags="noKeyPreview"
latin:backgroundType="action" />
</case>
<case
latin:imeAction="actionSearch"
>
<key-style
latin:styleName="returnKeyStyle"
latin:code="@integer/key_return"
latin:keyIcon="iconSearchKey"
latin:keyLabelFlags="autoXScale"
latin:keyActionFlags="noKeyPreview"
latin:backgroundType="action" />
</case>
<default>
<key-style
latin:styleName="returnKeyStyle"
latin:parentStyle="defaultReturnKeyStyle" />
</default>
</switch>
<key-style <key-style
latin:styleName="spaceKeyStyle" latin:styleName="spaceKeyStyle"
latin:code="@integer/key_space" latin:code="@integer/key_space"

View file

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 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.
*/
-->
<merge
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
>
<!-- Enter key style -->
<key-style
latin:styleName="defaultEnterKeyStyle"
latin:code="@integer/key_return"
latin:keyIcon="iconReturnKey"
latin:keyLabelFlags="autoXScale|preserveCase"
latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
<key-style
latin:styleName="defaultActionKeyStyle"
latin:code="@integer/key_action_enter"
latin:keyIcon="iconUndefined"
latin:backgroundType="action"
latin:parentStyle="defaultEnterKeyStyle" />
<switch>
<!-- Shift + Enter in textMultiLine field. -->
<case
latin:isMultiLine="true"
latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted"
>
<key-style
latin:styleName="enterKeyStyle"
latin:parentStyle="defaultEnterKeyStyle" />
</case>
<!-- Smiley in textShortMessage field. -->
<case
latin:mode="im"
>
<key-style
latin:styleName="enterKeyStyle"
latin:keyLabel=":-)"
latin:keyOutputText=":-) "
latin:keyLabelFlags="hasPopupHint"
latin:moreKeys="@string/more_keys_for_smiley"
latin:maxMoreKeysColumn="5"
latin:backgroundType="functional" />
</case>
<case
latin:imeAction="actionGo"
>
<key-style
latin:styleName="enterKeyStyle"
latin:keyLabel="@string/label_go_key"
latin:parentStyle="defaultActionKeyStyle" />
</case>
<case
latin:imeAction="actionNext"
>
<key-style
latin:styleName="enterKeyStyle"
latin:keyLabel="@string/label_next_key"
latin:parentStyle="defaultActionKeyStyle" />
</case>
<case
latin:imeAction="actionPrevious"
>
<key-style
latin:styleName="enterKeyStyle"
latin:keyLabel="@string/label_previous_key"
latin:parentStyle="defaultActionKeyStyle" />
</case>
<case
latin:imeAction="actionDone"
>
<key-style
latin:styleName="enterKeyStyle"
latin:keyLabel="@string/label_done_key"
latin:parentStyle="defaultActionKeyStyle" />
</case>
<case
latin:imeAction="actionSend"
>
<key-style
latin:styleName="enterKeyStyle"
latin:keyLabel="@string/label_send_key"
latin:parentStyle="defaultActionKeyStyle" />
</case>
<case
latin:imeAction="actionSearch"
>
<key-style
latin:styleName="enterKeyStyle"
latin:keyIcon="iconSearchKey"
latin:parentStyle="defaultActionKeyStyle" />
</case>
<case
latin:imeAction="actionCustomLabel"
>
<key-style
latin:styleName="enterKeyStyle"
latin:keyLabelFlags="fromCustomActionLabel"
latin:parentStyle="defaultActionKeyStyle" />
</case>
<!-- imeAction is either actionNone or actionUnspecified. -->
<default>
<key-style
latin:styleName="enterKeyStyle"
latin:parentStyle="defaultEnterKeyStyle" />
</default>
</switch>
</merge>

View file

@ -0,0 +1,111 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 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.
*/
-->
<merge
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
>
<!-- Enter key style -->
<key-style
latin:styleName="defaultEnterKeyStyle"
latin:code="@integer/key_return"
latin:keyIcon="iconReturnKey"
latin:keyLabelFlags="autoXScale|preserveCase"
latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
<key-style
latin:styleName="defaultActionKeyStyle"
latin:code="@integer/key_action_enter"
latin:keyIcon="iconUndefined"
latin:backgroundType="action"
latin:parentStyle="defaultEnterKeyStyle" />
<switch>
<!-- Shift + Enter in textMultiLine field. -->
<case
latin:isMultiLine="true"
latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLockShifted"
>
<key-style
latin:styleName="enterKeyStyle"
latin:parentStyle="defaultEnterKeyStyle" />
</case>
<case
latin:imeAction="actionGo"
>
<key-style
latin:styleName="enterKeyStyle"
latin:keyLabel="@string/label_go_key"
latin:parentStyle="defaultActionKeyStyle" />
</case>
<case
latin:imeAction="actionNext"
>
<key-style
latin:styleName="enterKeyStyle"
latin:keyLabel="@string/label_next_key"
latin:parentStyle="defaultActionKeyStyle" />
</case>
<case
latin:imeAction="actionPrevious"
>
<key-style
latin:styleName="enterKeyStyle"
latin:keyLabel="@string/label_previous_key"
latin:parentStyle="defaultActionKeyStyle" />
</case>
<case
latin:imeAction="actionDone"
>
<key-style
latin:styleName="enterKeyStyle"
latin:keyLabel="@string/label_done_key"
latin:parentStyle="defaultActionKeyStyle" />
</case>
<case
latin:imeAction="actionSend"
>
<key-style
latin:styleName="enterKeyStyle"
latin:keyLabel="@string/label_send_key"
latin:parentStyle="defaultActionKeyStyle" />
</case>
<case
latin:imeAction="actionSearch"
>
<key-style
latin:styleName="enterKeyStyle"
latin:keyIcon="iconSearchKey"
latin:parentStyle="defaultActionKeyStyle" />
</case>
<case
latin:imeAction="actionCustomLabel"
>
<key-style
latin:styleName="enterKeyStyle"
latin:keyLabelFlags="fromCustomActionLabel"
latin:parentStyle="defaultActionKeyStyle" />
</case>
<!-- imeAction is either actionNone or actionUnspecified. -->
<default>
<key-style
latin:styleName="enterKeyStyle"
latin:parentStyle="defaultEnterKeyStyle" />
</default>
</switch>
</merge>

View file

@ -40,7 +40,7 @@
<Key <Key
latin:keyStyle="punctuationKeyStyle" /> latin:keyStyle="punctuationKeyStyle" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyWidth="fillRight" /> latin:keyWidth="fillRight" />
</case> </case>
<!-- hasSettingsKey="true" or navigateAction="true" --> <!-- hasSettingsKey="true" or navigateAction="true" -->
@ -59,7 +59,7 @@
latin:keyStyle="punctuationKeyStyle" latin:keyStyle="punctuationKeyStyle"
latin:keyWidth="9.2%p" /> latin:keyWidth="9.2%p" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyWidth="fillRight" /> latin:keyWidth="fillRight" />
</default> </default>
</switch> </switch>

View file

@ -40,7 +40,7 @@
<Key <Key
latin:keyStyle="punctuationKeyStyle" /> latin:keyStyle="punctuationKeyStyle" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyWidth="fillRight" /> latin:keyWidth="fillRight" />
</case> </case>
<!-- hasSettingsKey="true" or navigateAction="true" --> <!-- hasSettingsKey="true" or navigateAction="true" -->
@ -59,7 +59,7 @@
latin:keyStyle="punctuationKeyStyle" latin:keyStyle="punctuationKeyStyle"
latin:keyWidth="9.2%p" /> latin:keyWidth="9.2%p" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyWidth="fillRight" /> latin:keyWidth="fillRight" />
</default> </default>
</switch> </switch>

View file

@ -45,7 +45,7 @@
latin:keyLabel="…" latin:keyLabel="…"
latin:backgroundType="functional" /> latin:backgroundType="functional" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyWidth="fillRight" /> latin:keyWidth="fillRight" />
</case> </case>
<!-- hasSettingsKey="true" or navigateAction="true" --> <!-- hasSettingsKey="true" or navigateAction="true" -->
@ -70,7 +70,7 @@
latin:keyWidth="9.2%p" latin:keyWidth="9.2%p"
latin:backgroundType="functional" /> latin:backgroundType="functional" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyWidth="fillRight" /> latin:keyWidth="fillRight" />
</default> </default>
</switch> </switch>

View file

@ -75,7 +75,7 @@
latin:keyLabel="." latin:keyLabel="."
latin:keyStyle="numKeyStyle" /> latin:keyStyle="numKeyStyle" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyWidth="fillRight" /> latin:keyWidth="fillRight" />
</Row> </Row>
</merge> </merge>

View file

@ -56,7 +56,7 @@
latin:keyStyle="num0KeyStyle" /> latin:keyStyle="num0KeyStyle" />
<Spacer /> <Spacer />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyWidth="fillRight" /> latin:keyWidth="fillRight" />
</Row> </Row>
</merge> </merge>

View file

@ -68,7 +68,7 @@
<Key <Key
latin:keyStyle="numSpaceKeyStyle" /> latin:keyStyle="numSpaceKeyStyle" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyWidth="fillRight" /> latin:keyWidth="fillRight" />
</Row> </Row>
</merge> </merge>

View file

@ -78,7 +78,7 @@
<Key <Key
latin:keyStyle="numSpaceKeyStyle" /> latin:keyStyle="numSpaceKeyStyle" />
<Key <Key
latin:keyStyle="returnKeyStyle" latin:keyStyle="enterKeyStyle"
latin:keyWidth="fillRight" /> latin:keyWidth="fillRight" />
</Row> </Row>
</merge> </merge>

View file

@ -67,42 +67,34 @@ public class EditorInfoCompatUtils {
ic.performEditorAction(OBJ_IME_ACTION_PREVIOUS); ic.performEditorAction(OBJ_IME_ACTION_PREVIOUS);
} }
public static String imeOptionsName(int imeOptions) { public static String imeActionName(int imeOptions) {
if (imeOptions == -1)
return null;
final int actionId = imeOptions & EditorInfo.IME_MASK_ACTION; final int actionId = imeOptions & EditorInfo.IME_MASK_ACTION;
final String action;
switch (actionId) { switch (actionId) {
case EditorInfo.IME_ACTION_UNSPECIFIED: case EditorInfo.IME_ACTION_UNSPECIFIED:
action = "actionUnspecified"; return "actionUnspecified";
break; case EditorInfo.IME_ACTION_NONE:
case EditorInfo.IME_ACTION_NONE: return "actionNone";
action = "actionNone"; case EditorInfo.IME_ACTION_GO:
break; return "actionGo";
case EditorInfo.IME_ACTION_GO: case EditorInfo.IME_ACTION_SEARCH:
action = "actionGo"; return "actionSearch";
break; case EditorInfo.IME_ACTION_SEND:
case EditorInfo.IME_ACTION_SEARCH: return "actionSend";
action = "actionSearch"; case EditorInfo.IME_ACTION_NEXT:
break; return "actionNext";
case EditorInfo.IME_ACTION_SEND: case EditorInfo.IME_ACTION_DONE:
action = "actionSend"; return "actionDone";
break; default:
case EditorInfo.IME_ACTION_NEXT: if (OBJ_IME_ACTION_PREVIOUS != null && actionId == OBJ_IME_ACTION_PREVIOUS) {
action = "actionNext"; return "actionPrevious";
break; } else {
case EditorInfo.IME_ACTION_DONE: return "actionUnknown(" + actionId + ")";
action = "actionDone";
break;
default: {
if (OBJ_IME_ACTION_PREVIOUS != null && actionId == OBJ_IME_ACTION_PREVIOUS) {
action = "actionPrevious";
} else {
action = "actionUnknown(" + actionId + ")";
}
break;
} }
} }
}
public static String imeOptionsName(int imeOptions) {
final String action = imeActionName(imeOptions);
final StringBuilder flags = new StringBuilder(); final StringBuilder flags = new StringBuilder();
if ((imeOptions & EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) { if ((imeOptions & EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) {
flags.append("flagNoEnterAction|"); flags.append("flagNoEnterAction|");
@ -116,6 +108,6 @@ public class EditorInfoCompatUtils {
if (hasFlagForceAscii(imeOptions)) { if (hasFlagForceAscii(imeOptions)) {
flags.append("flagForceAscii|"); flags.append("flagForceAscii|");
} }
return flags + action; return (action != null) ? flags + action : flags.toString();
} }
} }

View file

@ -72,6 +72,7 @@ public class Key {
private static final int LABEL_FLAGS_AUTO_X_SCALE = 0x4000; private static final int LABEL_FLAGS_AUTO_X_SCALE = 0x4000;
private static final int LABEL_FLAGS_PRESERVE_CASE = 0x8000; private static final int LABEL_FLAGS_PRESERVE_CASE = 0x8000;
private static final int LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED = 0x10000; private static final int LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED = 0x10000;
private static final int LABEL_FLAGS_FROM_CUSTOM_ACTION_LABEL = 0x20000;
/** Icon to display instead of a label. Icon takes precedence over a label */ /** Icon to display instead of a label. Icon takes precedence over a label */
private final int mIconId; private final int mIconId;
@ -247,14 +248,18 @@ public class Key {
mMaxMoreKeysColumn = style.getInt(keyAttr, mMaxMoreKeysColumn = style.getInt(keyAttr,
R.styleable.Keyboard_Key_maxMoreKeysColumn, params.mMaxMoreKeysKeyboardColumn); R.styleable.Keyboard_Key_maxMoreKeysColumn, params.mMaxMoreKeysKeyboardColumn);
mLabel = adjustCaseOfStringForKeyboardId(style.getString(keyAttr, if ((mLabelFlags & LABEL_FLAGS_FROM_CUSTOM_ACTION_LABEL) != 0) {
R.styleable.Keyboard_Key_keyLabel), preserveCase, params.mId); mLabel = params.mId.mCustomActionLabel;
mHintLabel = adjustCaseOfStringForKeyboardId(style.getString(keyAttr, } else {
R.styleable.Keyboard_Key_keyHintLabel), preserveCase, params.mId); mLabel = adjustCaseOfStringForKeyboardId(style.getString(
String outputText = adjustCaseOfStringForKeyboardId(style.getString(keyAttr, keyAttr, R.styleable.Keyboard_Key_keyLabel), preserveCase, params.mId);
R.styleable.Keyboard_Key_keyOutputText), preserveCase, params.mId); }
final int code = style.getInt(keyAttr, mHintLabel = adjustCaseOfStringForKeyboardId(style.getString(
R.styleable.Keyboard_Key_code, Keyboard.CODE_UNSPECIFIED); keyAttr, R.styleable.Keyboard_Key_keyHintLabel), preserveCase, params.mId);
String outputText = adjustCaseOfStringForKeyboardId(style.getString(
keyAttr, R.styleable.Keyboard_Key_keyOutputText), preserveCase, params.mId);
final int code = style.getInt(
keyAttr, R.styleable.Keyboard_Key_code, Keyboard.CODE_UNSPECIFIED);
// Choose the first letter of the label as primary code if not specified. // Choose the first letter of the label as primary code if not specified.
if (code == Keyboard.CODE_UNSPECIFIED && TextUtils.isEmpty(outputText) if (code == Keyboard.CODE_UNSPECIFIED && TextUtils.isEmpty(outputText)
&& !TextUtils.isEmpty(mLabel)) { && !TextUtils.isEmpty(mLabel)) {

View file

@ -28,7 +28,6 @@ import android.util.TypedValue;
import android.util.Xml; import android.util.Xml;
import android.view.InflateException; import android.view.InflateException;
import com.android.inputmethod.compat.EditorInfoCompatUtils;
import com.android.inputmethod.keyboard.internal.KeyStyles; import com.android.inputmethod.keyboard.internal.KeyStyles;
import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.LatinImeLogger;
@ -95,10 +94,11 @@ public class Keyboard {
*/ */
public static final int CODE_SHIFT = -1; public static final int CODE_SHIFT = -1;
public static final int CODE_SWITCH_ALPHA_SYMBOL = -2; public static final int CODE_SWITCH_ALPHA_SYMBOL = -2;
public static final int CODE_OUTPUT_TEXT = -4; public static final int CODE_OUTPUT_TEXT = -3;
public static final int CODE_DELETE = -5; public static final int CODE_DELETE = -4;
public static final int CODE_SETTINGS = -6; public static final int CODE_SETTINGS = -5;
public static final int CODE_SHORTCUT = -7; public static final int CODE_SHORTCUT = -6;
public static final int CODE_ACTION_ENTER = -7;
// Code value representing the code is not specified. // Code value representing the code is not specified.
public static final int CODE_UNSPECIFIED = -9; public static final int CODE_UNSPECIFIED = -9;
@ -380,6 +380,7 @@ public class Keyboard {
case CODE_DELETE: return "delete"; case CODE_DELETE: return "delete";
case CODE_SETTINGS: return "settings"; case CODE_SETTINGS: return "settings";
case CODE_SHORTCUT: return "shortcut"; case CODE_SHORTCUT: return "shortcut";
case CODE_ACTION_ENTER: return "actionEnter";
case CODE_UNSPECIFIED: return "unspec"; case CODE_UNSPECIFIED: return "unspec";
case CODE_TAB: return "tab"; case CODE_TAB: return "tab";
case CODE_ENTER: return "enter"; case CODE_ENTER: return "enter";
@ -475,7 +476,7 @@ public class Keyboard {
*/ */
public static class Builder<KP extends Params> { public static class Builder<KP extends Params> {
private static final String TAG = Builder.class.getSimpleName(); private static final String BUILDER_TAG = "Keyboard.Builder";
private static final boolean DEBUG = false; private static final boolean DEBUG = false;
// Keyboard XML Tags // Keyboard XML Tags
@ -643,7 +644,7 @@ public class Keyboard {
a.recycle(); a.recycle();
if (resourceId == 0) { if (resourceId == 0) {
if (LatinImeLogger.sDBG) if (LatinImeLogger.sDBG)
Log.e(TAG, "touchPositionCorrectionData is not defined"); Log.e(BUILDER_TAG, "touchPositionCorrectionData is not defined");
return; return;
} }
@ -680,10 +681,10 @@ public class Keyboard {
try { try {
parseKeyboard(parser); parseKeyboard(parser);
} catch (XmlPullParserException e) { } catch (XmlPullParserException e) {
Log.w(TAG, "keyboard XML parse error: " + e); Log.w(BUILDER_TAG, "keyboard XML parse error: " + e);
throw new IllegalArgumentException(e); throw new IllegalArgumentException(e);
} catch (IOException e) { } catch (IOException e) {
Log.w(TAG, "keyboard XML parse error: " + e); Log.w(BUILDER_TAG, "keyboard XML parse error: " + e);
throw new RuntimeException(e); throw new RuntimeException(e);
} finally { } finally {
parser.close(); parser.close();
@ -699,9 +700,29 @@ public class Keyboard {
return new Keyboard(mParams); return new Keyboard(mParams);
} }
private int mIndent;
private static final String SPACES = " ";
private static String spaces(int count) {
return (count < SPACES.length()) ? SPACES.substring(0, count) : SPACES;
}
private void startTag(String format, Object ... args) {
Log.d(BUILDER_TAG, String.format(spaces(++mIndent * 2) + format, args));
}
private void endTag(String format, Object ... args) {
Log.d(BUILDER_TAG, String.format(spaces(mIndent-- * 2) + format, args));
}
private void startEndTag(String format, Object ... args) {
Log.d(BUILDER_TAG, String.format(spaces(++mIndent * 2) + format, args));
mIndent--;
}
private void parseKeyboard(XmlPullParser parser) private void parseKeyboard(XmlPullParser parser)
throws XmlPullParserException, IOException { throws XmlPullParserException, IOException {
if (DEBUG) Log.d(TAG, String.format("<%s> %s", TAG_KEYBOARD, mParams.mId)); if (DEBUG) startTag("<%s> %s", TAG_KEYBOARD, mParams.mId);
int event; int event;
while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) { while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
if (event == XmlPullParser.START_TAG) { if (event == XmlPullParser.START_TAG) {
@ -788,9 +809,10 @@ public class Keyboard {
final String tag = parser.getName(); final String tag = parser.getName();
if (TAG_ROW.equals(tag)) { if (TAG_ROW.equals(tag)) {
Row row = parseRowAttributes(parser); Row row = parseRowAttributes(parser);
if (DEBUG) Log.d(TAG, String.format("<%s>", TAG_ROW)); if (DEBUG) startTag("<%s>%s", TAG_ROW, skip ? " skipped" : "");
if (!skip) if (!skip) {
startRow(row); startRow(row);
}
parseRowContent(parser, row, skip); parseRowContent(parser, row, skip);
} else if (TAG_INCLUDE.equals(tag)) { } else if (TAG_INCLUDE.equals(tag)) {
parseIncludeKeyboardContent(parser, skip); parseIncludeKeyboardContent(parser, skip);
@ -803,15 +825,13 @@ public class Keyboard {
} }
} else if (event == XmlPullParser.END_TAG) { } else if (event == XmlPullParser.END_TAG) {
final String tag = parser.getName(); final String tag = parser.getName();
if (DEBUG) endTag("</%s>", tag);
if (TAG_KEYBOARD.equals(tag)) { if (TAG_KEYBOARD.equals(tag)) {
endKeyboard(); endKeyboard();
break; break;
} else if (TAG_CASE.equals(tag) || TAG_DEFAULT.equals(tag) } else if (TAG_CASE.equals(tag) || TAG_DEFAULT.equals(tag)
|| TAG_MERGE.equals(tag)) { || TAG_MERGE.equals(tag)) {
if (DEBUG) Log.d(TAG, String.format("</%s>", tag));
break; break;
} else if (TAG_KEY_STYLE.equals(tag)) {
continue;
} else { } else {
throw new XmlParseUtils.IllegalEndTag(parser, TAG_ROW); throw new XmlParseUtils.IllegalEndTag(parser, TAG_ROW);
} }
@ -854,17 +874,15 @@ public class Keyboard {
} }
} else if (event == XmlPullParser.END_TAG) { } else if (event == XmlPullParser.END_TAG) {
final String tag = parser.getName(); final String tag = parser.getName();
if (DEBUG) endTag("</%s>", tag);
if (TAG_ROW.equals(tag)) { if (TAG_ROW.equals(tag)) {
if (DEBUG) Log.d(TAG, String.format("</%s>", TAG_ROW)); if (!skip) {
if (!skip)
endRow(row); endRow(row);
}
break; break;
} else if (TAG_CASE.equals(tag) || TAG_DEFAULT.equals(tag) } else if (TAG_CASE.equals(tag) || TAG_DEFAULT.equals(tag)
|| TAG_MERGE.equals(tag)) { || TAG_MERGE.equals(tag)) {
if (DEBUG) Log.d(TAG, String.format("</%s>", tag));
break; break;
} else if (TAG_KEY_STYLE.equals(tag)) {
continue;
} else { } else {
throw new XmlParseUtils.IllegalEndTag(parser, TAG_KEY); throw new XmlParseUtils.IllegalEndTag(parser, TAG_KEY);
} }
@ -876,11 +894,14 @@ public class Keyboard {
throws XmlPullParserException, IOException { throws XmlPullParserException, IOException {
if (skip) { if (skip) {
XmlParseUtils.checkEndTag(TAG_KEY, parser); XmlParseUtils.checkEndTag(TAG_KEY, parser);
if (DEBUG) startEndTag("<%s /> skipped", TAG_KEY);
} else { } else {
final Key key = new Key(mResources, mParams, row, parser, mKeyStyles); final Key key = new Key(mResources, mParams, row, parser, mKeyStyles);
if (DEBUG) Log.d(TAG, String.format("<%s%s keyLabel=%s code=%d moreKeys=%s />", if (DEBUG) {
TAG_KEY, (key.isEnabled() ? "" : " disabled"), key.mLabel, key.mCode, startEndTag("<%s%s %s moreKeys=%s />", TAG_KEY,
Arrays.toString(key.mMoreKeys))); (key.isEnabled() ? "" : " disabled"), key,
Arrays.toString(key.mMoreKeys));
}
XmlParseUtils.checkEndTag(TAG_KEY, parser); XmlParseUtils.checkEndTag(TAG_KEY, parser);
endKey(key); endKey(key);
} }
@ -890,10 +911,11 @@ public class Keyboard {
throws XmlPullParserException, IOException { throws XmlPullParserException, IOException {
if (skip) { if (skip) {
XmlParseUtils.checkEndTag(TAG_SPACER, parser); XmlParseUtils.checkEndTag(TAG_SPACER, parser);
if (DEBUG) startEndTag("<%s /> skipped", TAG_SPACER);
} else { } else {
final Key.Spacer spacer = new Key.Spacer( final Key.Spacer spacer = new Key.Spacer(
mResources, mParams, row, parser, mKeyStyles); mResources, mParams, row, parser, mKeyStyles);
if (DEBUG) Log.d(TAG, String.format("<%s />", TAG_SPACER)); if (DEBUG) startEndTag("<%s />", TAG_SPACER);
XmlParseUtils.checkEndTag(TAG_SPACER, parser); XmlParseUtils.checkEndTag(TAG_SPACER, parser);
endKey(spacer); endKey(spacer);
} }
@ -913,6 +935,7 @@ public class Keyboard {
throws XmlPullParserException, IOException { throws XmlPullParserException, IOException {
if (skip) { if (skip) {
XmlParseUtils.checkEndTag(TAG_INCLUDE, parser); XmlParseUtils.checkEndTag(TAG_INCLUDE, parser);
if (DEBUG) startEndTag("</%s> skipped", TAG_INCLUDE);
} else { } else {
final AttributeSet attr = Xml.asAttributeSet(parser); final AttributeSet attr = Xml.asAttributeSet(parser);
final TypedArray keyboardAttr = mResources.obtainAttributes(attr, final TypedArray keyboardAttr = mResources.obtainAttributes(attr,
@ -944,8 +967,10 @@ public class Keyboard {
} }
XmlParseUtils.checkEndTag(TAG_INCLUDE, parser); XmlParseUtils.checkEndTag(TAG_INCLUDE, parser);
if (DEBUG) Log.d(TAG, String.format("<%s keyboardLayout=%s />", if (DEBUG) {
TAG_INCLUDE, mResources.getResourceEntryName(keyboardLayout))); startEndTag("<%s keyboardLayout=%s />",TAG_INCLUDE,
mResources.getResourceEntryName(keyboardLayout));
}
final XmlResourceParser parserForInclude = mResources.getXml(keyboardLayout); final XmlResourceParser parserForInclude = mResources.getXml(keyboardLayout);
try { try {
parseMerge(parserForInclude, row, skip); parseMerge(parserForInclude, row, skip);
@ -961,6 +986,7 @@ public class Keyboard {
private void parseMerge(XmlPullParser parser, Row row, boolean skip) private void parseMerge(XmlPullParser parser, Row row, boolean skip)
throws XmlPullParserException, IOException { throws XmlPullParserException, IOException {
if (DEBUG) startTag("<%s>", TAG_MERGE);
int event; int event;
while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) { while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
if (event == XmlPullParser.START_TAG) { if (event == XmlPullParser.START_TAG) {
@ -992,7 +1018,7 @@ public class Keyboard {
private void parseSwitchInternal(XmlPullParser parser, Row row, boolean skip) private void parseSwitchInternal(XmlPullParser parser, Row row, boolean skip)
throws XmlPullParserException, IOException { throws XmlPullParserException, IOException {
if (DEBUG) Log.d(TAG, String.format("<%s> %s", TAG_SWITCH, mParams.mId)); if (DEBUG) startTag("<%s> %s", TAG_SWITCH, mParams.mId);
boolean selected = false; boolean selected = false;
int event; int event;
while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) { while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
@ -1008,7 +1034,7 @@ public class Keyboard {
} else if (event == XmlPullParser.END_TAG) { } else if (event == XmlPullParser.END_TAG) {
final String tag = parser.getName(); final String tag = parser.getName();
if (TAG_SWITCH.equals(tag)) { if (TAG_SWITCH.equals(tag)) {
if (DEBUG) Log.d(TAG, String.format("</%s>", TAG_SWITCH)); if (DEBUG) endTag("</%s>", TAG_SWITCH);
break; break;
} else { } else {
throw new XmlParseUtils.IllegalEndTag(parser, TAG_KEY); throw new XmlParseUtils.IllegalEndTag(parser, TAG_KEY);
@ -1057,10 +1083,8 @@ public class Keyboard {
R.styleable.Keyboard_Case_shortcutKeyEnabled, id.mShortcutKeyEnabled); R.styleable.Keyboard_Case_shortcutKeyEnabled, id.mShortcutKeyEnabled);
final boolean hasShortcutKeyMatched = matchBoolean(a, final boolean hasShortcutKeyMatched = matchBoolean(a,
R.styleable.Keyboard_Case_hasShortcutKey, id.mHasShortcutKey); R.styleable.Keyboard_Case_hasShortcutKey, id.mHasShortcutKey);
// As noted at {@link KeyboardId} class, we are interested only in enum value final boolean isMultiLineMatched = matchBoolean(a,
// masked by {@link android.view.inputmethod.EditorInfo#IME_MASK_ACTION} and R.styleable.Keyboard_Case_isMultiLine, id.isMultiLine());
// {@link android.view.inputmethod.EditorInfo#IME_FLAG_NO_ENTER_ACTION}. So matching
// this attribute with id.mImeOptions as integer value is enough for our purpose.
final boolean imeActionMatched = matchInteger(a, final boolean imeActionMatched = matchInteger(a,
R.styleable.Keyboard_Case_imeAction, id.imeAction()); R.styleable.Keyboard_Case_imeAction, id.imeAction());
final boolean localeCodeMatched = matchString(a, final boolean localeCodeMatched = matchString(a,
@ -1072,30 +1096,42 @@ public class Keyboard {
final boolean selected = keyboardSetElementMatched && modeMatched final boolean selected = keyboardSetElementMatched && modeMatched
&& navigateActionMatched && passwordInputMatched && hasSettingsKeyMatched && navigateActionMatched && passwordInputMatched && hasSettingsKeyMatched
&& f2KeyModeMatched && clobberSettingsKeyMatched && f2KeyModeMatched && clobberSettingsKeyMatched
&& shortcutKeyEnabledMatched && hasShortcutKeyMatched && imeActionMatched && shortcutKeyEnabledMatched && hasShortcutKeyMatched && isMultiLineMatched
&& localeCodeMatched && languageCodeMatched && countryCodeMatched; && imeActionMatched && localeCodeMatched && languageCodeMatched
&& countryCodeMatched;
if (DEBUG) Log.d(TAG, String.format("<%s%s%s%s%s%s%s%s%s%s%s%s%s%s> %s", TAG_CASE, if (DEBUG) {
textAttr(a.getString(R.styleable.Keyboard_Case_keyboardSetElement), startTag("<%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s>%s", TAG_CASE,
"keyboardSetElement"), textAttr(a.getString(R.styleable.Keyboard_Case_keyboardSetElement),
textAttr(a.getString(R.styleable.Keyboard_Case_mode), "mode"), "keyboardSetElement"),
booleanAttr(a, R.styleable.Keyboard_Case_navigateAction, "navigateAction"), textAttr(a.getString(R.styleable.Keyboard_Case_mode), "mode"),
booleanAttr(a, R.styleable.Keyboard_Case_passwordInput, "passwordInput"), booleanAttr(a, R.styleable.Keyboard_Case_navigateAction,
booleanAttr(a, R.styleable.Keyboard_Case_hasSettingsKey, "hasSettingsKey"), "navigateAction"),
textAttr(KeyboardId.f2KeyModeName( booleanAttr(a, R.styleable.Keyboard_Case_passwordInput,
a.getInt(R.styleable.Keyboard_Case_f2KeyMode, -1)), "f2KeyMode"), "passwordInput"),
booleanAttr(a, R.styleable.Keyboard_Case_clobberSettingsKey, booleanAttr(a, R.styleable.Keyboard_Case_hasSettingsKey,
"clobberSettingsKey"), "hasSettingsKey"),
booleanAttr(a, R.styleable.Keyboard_Case_shortcutKeyEnabled, textAttr(KeyboardId.f2KeyModeName(
"shortcutKeyEnabled"), a.getInt(R.styleable.Keyboard_Case_f2KeyMode, -1)),
booleanAttr(a, R.styleable.Keyboard_Case_hasShortcutKey, "hasShortcutKey"), "f2KeyMode"),
textAttr(EditorInfoCompatUtils.imeOptionsName( booleanAttr(a, R.styleable.Keyboard_Case_clobberSettingsKey,
a.getInt(R.styleable.Keyboard_Case_imeAction, -1)), "imeAction"), "clobberSettingsKey"),
textAttr(a.getString(R.styleable.Keyboard_Case_localeCode), "localeCode"), booleanAttr(a, R.styleable.Keyboard_Case_shortcutKeyEnabled,
textAttr(a.getString(R.styleable.Keyboard_Case_languageCode), "shortcutKeyEnabled"),
"languageCode"), booleanAttr(a, R.styleable.Keyboard_Case_hasShortcutKey,
textAttr(a.getString(R.styleable.Keyboard_Case_countryCode), "countryCode"), "hasShortcutKey"),
Boolean.toString(selected))); booleanAttr(a, R.styleable.Keyboard_Case_isMultiLine,
"isMultiLine"),
textAttr(a.getString(R.styleable.Keyboard_Case_imeAction),
"imeAction"),
textAttr(a.getString(R.styleable.Keyboard_Case_localeCode),
"localeCode"),
textAttr(a.getString(R.styleable.Keyboard_Case_languageCode),
"languageCode"),
textAttr(a.getString(R.styleable.Keyboard_Case_countryCode),
"countryCode"),
selected ? "" : " skipped");
}
return selected; return selected;
} finally { } finally {
@ -1148,7 +1184,7 @@ public class Keyboard {
private boolean parseDefault(XmlPullParser parser, Row row, boolean skip) private boolean parseDefault(XmlPullParser parser, Row row, boolean skip)
throws XmlPullParserException, IOException { throws XmlPullParserException, IOException {
if (DEBUG) Log.d(TAG, String.format("<%s>", TAG_DEFAULT)); if (DEBUG) startTag("<%s>", TAG_DEFAULT);
if (row == null) { if (row == null) {
parseKeyboardContent(parser, skip); parseKeyboardContent(parser, skip);
} else { } else {
@ -1158,7 +1194,7 @@ public class Keyboard {
} }
private void parseKeyStyle(XmlPullParser parser, boolean skip) private void parseKeyStyle(XmlPullParser parser, boolean skip)
throws XmlPullParserException { throws XmlPullParserException, IOException {
TypedArray keyStyleAttr = mResources.obtainAttributes(Xml.asAttributeSet(parser), TypedArray keyStyleAttr = mResources.obtainAttributes(Xml.asAttributeSet(parser),
R.styleable.Keyboard_KeyStyle); R.styleable.Keyboard_KeyStyle);
TypedArray keyAttrs = mResources.obtainAttributes(Xml.asAttributeSet(parser), TypedArray keyAttrs = mResources.obtainAttributes(Xml.asAttributeSet(parser),
@ -1167,12 +1203,18 @@ public class Keyboard {
if (!keyStyleAttr.hasValue(R.styleable.Keyboard_KeyStyle_styleName)) if (!keyStyleAttr.hasValue(R.styleable.Keyboard_KeyStyle_styleName))
throw new XmlParseUtils.ParseException("<" + TAG_KEY_STYLE throw new XmlParseUtils.ParseException("<" + TAG_KEY_STYLE
+ "/> needs styleName attribute", parser); + "/> needs styleName attribute", parser);
if (DEBUG) {
startEndTag("<%s styleName=%s />%s", TAG_KEY_STYLE,
keyStyleAttr.getString(R.styleable.Keyboard_KeyStyle_styleName),
skip ? " skipped" : "");
}
if (!skip) if (!skip)
mKeyStyles.parseKeyStyleAttributes(keyStyleAttr, keyAttrs, parser); mKeyStyles.parseKeyStyleAttributes(keyStyleAttr, keyAttrs, parser);
} finally { } finally {
keyStyleAttr.recycle(); keyStyleAttr.recycle();
keyAttrs.recycle(); keyAttrs.recycle();
} }
XmlParseUtils.checkEndTag(TAG_KEY_STYLE, parser);
} }
private void startKeyboard() { private void startKeyboard() {

View file

@ -16,6 +16,7 @@
package com.android.inputmethod.keyboard; package com.android.inputmethod.keyboard;
import android.text.InputType;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
@ -25,10 +26,8 @@ import com.android.inputmethod.compat.InputTypeCompatUtils;
import java.util.Arrays; import java.util.Arrays;
import java.util.Locale; import java.util.Locale;
// TODO: Move to com.android.inputmethod.keyboard.internal package.
/** /**
* Represents the parameters necessary to construct a new LatinKeyboard, * Unique identifier for each keyboard type.
* which also serve as a unique identifier for each keyboard type.
*/ */
public class KeyboardId { public class KeyboardId {
public static final int MODE_TEXT = 0; public static final int MODE_TEXT = 0;
@ -54,34 +53,37 @@ public class KeyboardId {
private static final int F2KEY_MODE_SHORTCUT_IME = 2; private static final int F2KEY_MODE_SHORTCUT_IME = 2;
private static final int F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS = 3; private static final int F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS = 3;
private static final int IME_ACTION_CUSTOM_LABEL = EditorInfo.IME_MASK_ACTION + 1;
public final Locale mLocale; public final Locale mLocale;
public final int mOrientation; public final int mOrientation;
public final int mWidth; public final int mWidth;
public final int mMode; public final int mMode;
public final int mElementId; public final int mElementId;
private final int mInputType; private final EditorInfo mEditorInfo;
private final int mImeOptions;
private final boolean mSettingsKeyEnabled; private final boolean mSettingsKeyEnabled;
public final boolean mClobberSettingsKey; public final boolean mClobberSettingsKey;
public final boolean mShortcutKeyEnabled; public final boolean mShortcutKeyEnabled;
public final boolean mHasShortcutKey; public final boolean mHasShortcutKey;
public final String mCustomActionLabel;
private final int mHashCode; private final int mHashCode;
public KeyboardId(int elementId, Locale locale, int orientation, int width, int mode, public KeyboardId(int elementId, Locale locale, int orientation, int width, int mode,
int inputType, int imeOptions, boolean settingsKeyEnabled, boolean clobberSettingsKey, EditorInfo editorInfo, boolean settingsKeyEnabled, boolean clobberSettingsKey,
boolean shortcutKeyEnabled, boolean hasShortcutKey) { boolean shortcutKeyEnabled, boolean hasShortcutKey) {
this.mLocale = locale; this.mLocale = locale;
this.mOrientation = orientation; this.mOrientation = orientation;
this.mWidth = width; this.mWidth = width;
this.mMode = mode; this.mMode = mode;
this.mElementId = elementId; this.mElementId = elementId;
this.mInputType = inputType; this.mEditorInfo = editorInfo;
this.mImeOptions = imeOptions;
this.mSettingsKeyEnabled = settingsKeyEnabled; this.mSettingsKeyEnabled = settingsKeyEnabled;
this.mClobberSettingsKey = clobberSettingsKey; this.mClobberSettingsKey = clobberSettingsKey;
this.mShortcutKeyEnabled = shortcutKeyEnabled; this.mShortcutKeyEnabled = shortcutKeyEnabled;
this.mHasShortcutKey = hasShortcutKey; this.mHasShortcutKey = hasShortcutKey;
this.mCustomActionLabel = (editorInfo.actionLabel != null)
? editorInfo.actionLabel.toString() : null;
this.mHashCode = hashCode(this); this.mHashCode = hashCode(this);
} }
@ -98,6 +100,7 @@ public class KeyboardId {
id.mClobberSettingsKey, id.mClobberSettingsKey,
id.mShortcutKeyEnabled, id.mShortcutKeyEnabled,
id.mHasShortcutKey, id.mHasShortcutKey,
id.isMultiLine(),
id.imeAction(), id.imeAction(),
id.mLocale id.mLocale
}); });
@ -116,6 +119,7 @@ public class KeyboardId {
&& other.mClobberSettingsKey == this.mClobberSettingsKey && other.mClobberSettingsKey == this.mClobberSettingsKey
&& other.mShortcutKeyEnabled == this.mShortcutKeyEnabled && other.mShortcutKeyEnabled == this.mShortcutKeyEnabled
&& other.mHasShortcutKey == this.mHasShortcutKey && other.mHasShortcutKey == this.mHasShortcutKey
&& other.isMultiLine() == this.isMultiLine()
&& other.imeAction() == this.imeAction() && other.imeAction() == this.imeAction()
&& other.mLocale.equals(this.mLocale); && other.mLocale.equals(this.mLocale);
} }
@ -151,22 +155,30 @@ public class KeyboardId {
public boolean navigateAction() { public boolean navigateAction() {
// Note: Turn off checking navigation flag to show TAB key for now. // Note: Turn off checking navigation flag to show TAB key for now.
boolean navigateAction = InputTypeCompatUtils.isWebInputType(mInputType); boolean navigateAction = InputTypeCompatUtils.isWebInputType(mEditorInfo.inputType);
// || EditorInfoCompatUtils.hasFlagNavigateNext(mImeOptions) // || EditorInfoCompatUtils.hasFlagNavigateNext(mImeOptions)
// || EditorInfoCompatUtils.hasFlagNavigatePrevious(mImeOptions); // || EditorInfoCompatUtils.hasFlagNavigatePrevious(mImeOptions);
return navigateAction; return navigateAction;
} }
public boolean passwordInput() { public boolean passwordInput() {
return InputTypeCompatUtils.isPasswordInputType(mInputType) final int inputType = mEditorInfo.inputType;
|| InputTypeCompatUtils.isVisiblePasswordInputType(mInputType); return InputTypeCompatUtils.isPasswordInputType(inputType)
|| InputTypeCompatUtils.isVisiblePasswordInputType(inputType);
}
public boolean isMultiLine() {
return (mEditorInfo.inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) != 0;
} }
public int imeAction() { public int imeAction() {
// We are interested only in {@link EditorInfo#IME_MASK_ACTION} enum value and if ((mEditorInfo.imeOptions & EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) {
// {@link EditorInfo#IME_FLAG_NO_ENTER_ACTION}. return EditorInfo.IME_ACTION_NONE;
return mImeOptions & ( } else if (mEditorInfo.actionLabel != null) {
EditorInfo.IME_MASK_ACTION | EditorInfo.IME_FLAG_NO_ENTER_ACTION); return IME_ACTION_CUSTOM_LABEL;
} else {
return mEditorInfo.imeOptions & EditorInfo.IME_MASK_ACTION;
}
} }
public boolean hasSettingsKey() { public boolean hasSettingsKey() {
@ -205,7 +217,7 @@ public class KeyboardId {
mLocale, mLocale,
(mOrientation == 1 ? "port" : "land"), mWidth, (mOrientation == 1 ? "port" : "land"), mWidth,
modeName(mMode), modeName(mMode),
EditorInfoCompatUtils.imeOptionsName(imeAction()), imeAction(),
f2KeyModeName(f2KeyMode()), f2KeyModeName(f2KeyMode()),
(mClobberSettingsKey ? " clobberSettingsKey" : ""), (mClobberSettingsKey ? " clobberSettingsKey" : ""),
(navigateAction() ? " navigateAction" : ""), (navigateAction() ? " navigateAction" : ""),
@ -252,6 +264,11 @@ public class KeyboardId {
} }
} }
public static String actionName(int actionId) {
return (actionId == IME_ACTION_CUSTOM_LABEL) ? "actionCustomLabel"
: EditorInfoCompatUtils.imeActionName(actionId);
}
public static String f2KeyModeName(int f2KeyMode) { public static String f2KeyModeName(int f2KeyMode) {
switch (f2KeyMode) { switch (f2KeyMode) {
case F2KEY_MODE_NONE: return "none"; case F2KEY_MODE_NONE: return "none";

View file

@ -62,6 +62,8 @@ public class KeyboardSet {
new HashMap<KeyboardId, SoftReference<Keyboard>>(); new HashMap<KeyboardId, SoftReference<Keyboard>>();
private static final KeysCache sKeysCache = new KeysCache(); private static final KeysCache sKeysCache = new KeysCache();
private static final EditorInfo EMPTY_EDITOR_INFO = new EditorInfo();
public static class KeyboardSetException extends RuntimeException { public static class KeyboardSetException extends RuntimeException {
public final KeyboardId mKeyboardId; public final KeyboardId mKeyboardId;
public KeyboardSetException(Throwable cause, KeyboardId keyboardId) { public KeyboardSetException(Throwable cause, KeyboardId keyboardId) {
@ -94,8 +96,7 @@ public class KeyboardSet {
static class Params { static class Params {
int mMode; int mMode;
int mInputType; EditorInfo mEditorInfo;
int mImeOptions;
boolean mTouchPositionCorrectionEnabled; boolean mTouchPositionCorrectionEnabled;
boolean mSettingsKeyEnabled; boolean mSettingsKeyEnabled;
boolean mVoiceKeyEnabled; boolean mVoiceKeyEnabled;
@ -192,9 +193,8 @@ public class KeyboardSet {
final boolean hasShortcutKey = params.mVoiceKeyEnabled final boolean hasShortcutKey = params.mVoiceKeyEnabled
&& (isSymbols != params.mVoiceKeyOnMain); && (isSymbols != params.mVoiceKeyOnMain);
return new KeyboardId(keyboardSetElementId, params.mLocale, params.mOrientation, return new KeyboardId(keyboardSetElementId, params.mLocale, params.mOrientation,
params.mWidth, params.mMode, params.mInputType, params.mImeOptions, params.mWidth, params.mMode, params.mEditorInfo, params.mSettingsKeyEnabled,
params.mSettingsKeyEnabled, params.mNoSettingsKey, params.mVoiceKeyEnabled, params.mNoSettingsKey, params.mVoiceKeyEnabled, hasShortcutKey);
hasShortcutKey);
} }
public static class Builder { public static class Builder {
@ -213,10 +213,7 @@ public class KeyboardSet {
final Params params = mParams; final Params params = mParams;
params.mMode = Utils.getKeyboardMode(editorInfo); params.mMode = Utils.getKeyboardMode(editorInfo);
if (editorInfo != null) { params.mEditorInfo = (editorInfo != null) ? editorInfo : EMPTY_EDITOR_INFO;
params.mInputType = editorInfo.inputType;
params.mImeOptions = editorInfo.imeOptions;
}
params.mNoSettingsKey = Utils.inPrivateImeOptions( params.mNoSettingsKey = Utils.inPrivateImeOptions(
mPackageName, LatinIME.IME_OPTION_NO_SETTINGS_KEY, mEditorInfo); mPackageName, LatinIME.IME_OPTION_NO_SETTINGS_KEY, mEditorInfo);
} }
@ -232,7 +229,8 @@ public class KeyboardSet {
boolean touchPositionCorrectionEnabled) { boolean touchPositionCorrectionEnabled) {
final boolean deprecatedForceAscii = Utils.inPrivateImeOptions( final boolean deprecatedForceAscii = Utils.inPrivateImeOptions(
mPackageName, LatinIME.IME_OPTION_FORCE_ASCII, mEditorInfo); mPackageName, LatinIME.IME_OPTION_FORCE_ASCII, mEditorInfo);
final boolean forceAscii = EditorInfoCompatUtils.hasFlagForceAscii(mParams.mImeOptions) final boolean forceAscii = EditorInfoCompatUtils.hasFlagForceAscii(
mParams.mEditorInfo.imeOptions)
|| deprecatedForceAscii; || deprecatedForceAscii;
mParams.mLocale = (forceAscii && !asciiCapable) ? Locale.US : inputLocale; mParams.mLocale = (forceAscii && !asciiCapable) ? Locale.US : inputLocale;
mParams.mTouchPositionCorrectionEnabled = touchPositionCorrectionEnabled; mParams.mTouchPositionCorrectionEnabled = touchPositionCorrectionEnabled;

View file

@ -1224,6 +1224,41 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
return mOptionsDialog != null && mOptionsDialog.isShowing(); return mOptionsDialog != null && mOptionsDialog.isShowing();
} }
private void insertPunctuationFromSuggestionStrip(final int code) {
onCodeInput(code, new int[] { code },
KeyboardActionListener.SUGGESTION_STRIP_COORDINATE,
KeyboardActionListener.SUGGESTION_STRIP_COORDINATE);
}
private static int getEditorActionId(EditorInfo editorInfo) {
if (editorInfo == null) return 0;
return (editorInfo.actionLabel != null)
? editorInfo.actionId
: (editorInfo.imeOptions & EditorInfo.IME_MASK_ACTION);
}
private void performeEditorAction(int actionId) {
final InputConnection ic = getCurrentInputConnection();
if (ic != null) {
ic.performEditorAction(actionId);
}
}
private void sendKeyCodePoint(int code) {
// TODO: Remove this special handling of digit letters.
// For backward compatibility. See {@link InputMethodService#sendKeyChar(char)}.
if (code >= '0' && code <= '9') {
super.sendKeyChar((char)code);
return;
}
final InputConnection ic = getCurrentInputConnection();
if (ic != null) {
final String text = new String(new int[] { code }, 0, 1);
ic.commitText(text, text.length());
}
}
// Implementation of {@link KeyboardActionListener}. // Implementation of {@link KeyboardActionListener}.
@Override @Override
public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) { public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) {
@ -1264,6 +1299,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
case Keyboard.CODE_SHORTCUT: case Keyboard.CODE_SHORTCUT:
mSubtypeSwitcher.switchToShortcutIME(); mSubtypeSwitcher.switchToShortcutIME();
break; break;
case Keyboard.CODE_ACTION_ENTER:
performeEditorAction(getEditorActionId(getCurrentInputEditorInfo()));
break;
case Keyboard.CODE_TAB: case Keyboard.CODE_TAB:
handleTab(); handleTab();
// There are two cases for tab. Either we send a "next" event, that may change the // There are two cases for tab. Either we send a "next" event, that may change the
@ -1301,7 +1339,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
commitTyped(ic); commitTyped(ic);
text = specificTldProcessingOnTextInput(ic, text); text = specificTldProcessingOnTextInput(ic, text);
if (SPACE_STATE_PHANTOM == mSpaceState) { if (SPACE_STATE_PHANTOM == mSpaceState) {
sendKeyChar((char)Keyboard.CODE_SPACE); sendKeyCodePoint(Keyboard.CODE_SPACE);
} }
ic.commitText(text, 1); ic.commitText(text, 1);
ic.endBatchEdit(); ic.endBatchEdit();
@ -1448,10 +1486,12 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
} }
} }
// TODO: Implement next and previous actions using other key code than tab's code.
private void handleTab() { private void handleTab() {
final int imeOptions = getCurrentInputEditorInfo().imeOptions; final int imeOptions = getCurrentInputEditorInfo().imeOptions;
if (!EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions) if (!EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions)
&& !EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions)) { && !EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions)) {
// TODO: This should be {@link #sendKeyCodePoint(int)}.
sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB); sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB);
return; return;
} }
@ -1513,7 +1553,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// Sanity check // Sanity check
throw new RuntimeException("Should not be composing here"); throw new RuntimeException("Should not be composing here");
} }
sendKeyChar((char)Keyboard.CODE_SPACE); sendKeyCodePoint(Keyboard.CODE_SPACE);
} }
if ((isAlphabet(primaryCode) if ((isAlphabet(primaryCode)
@ -1549,7 +1589,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
final boolean swapWeakSpace = maybeStripSpaceWhileInBatchEdit(ic, primaryCode, final boolean swapWeakSpace = maybeStripSpaceWhileInBatchEdit(ic, primaryCode,
spaceState, KeyboardActionListener.SUGGESTION_STRIP_COORDINATE == x); spaceState, KeyboardActionListener.SUGGESTION_STRIP_COORDINATE == x);
sendKeyChar((char)primaryCode); sendKeyCodePoint(primaryCode);
if (swapWeakSpace) { if (swapWeakSpace) {
swapSwapperAndSpaceWhileInBatchEdit(ic); swapSwapperAndSpaceWhileInBatchEdit(ic);
@ -1595,11 +1635,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
final boolean swapWeakSpace = maybeStripSpaceWhileInBatchEdit(ic, primaryCode, spaceState, final boolean swapWeakSpace = maybeStripSpaceWhileInBatchEdit(ic, primaryCode, spaceState,
KeyboardActionListener.SUGGESTION_STRIP_COORDINATE == x); KeyboardActionListener.SUGGESTION_STRIP_COORDINATE == x);
// TODO: rethink interactions of sendKeyChar, commitText("\n") and actions. sendKeyChar sendKeyCodePoint(primaryCode);
// with a CODE_ENTER parameter will have the default InputMethodService implementation
// possibly redirect on the keyboard action. That may be the right thing to do, but
// on Shift+Enter, it's generally not, so we may want to do the redirection right here.
sendKeyChar((char)primaryCode);
if (Keyboard.CODE_SPACE == primaryCode) { if (Keyboard.CODE_SPACE == primaryCode) {
if (isSuggestionsRequested()) { if (isSuggestionsRequested()) {