LatinIME.java revision 6780b898ec2647a21319601a03ae1c393c0e1b29
1923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/*
2923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Copyright (C) 2008-2009 Google Inc.
3a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker *
4923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * use this file except in compliance with the License. You may obtain a copy of
6923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * the License at
7a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker *
8923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0
9a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker *
10923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * License for the specific language governing permissions and limitations under
14923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * the License.
15923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */
16923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
17923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectpackage com.android.inputmethod.latin;
18923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
19960ea65f3f2162e7f8f387380924162d42fef4dcValentin Kravtsovimport com.android.inputmethod.voice.EditingUtil;
20960ea65f3f2162e7f8f387380924162d42fef4dcValentin Kravtsovimport com.android.inputmethod.voice.FieldContext;
21960ea65f3f2162e7f8f387380924162d42fef4dcValentin Kravtsovimport com.android.inputmethod.voice.SettingsUtil;
22960ea65f3f2162e7f8f387380924162d42fef4dcValentin Kravtsovimport com.android.inputmethod.voice.VoiceInput;
23388ce92ab8a635c5ad44620dad59baf05dfea510Amith Yamasani
24923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.app.AlertDialog;
25923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.BroadcastReceiver;
26923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.Context;
27923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.DialogInterface;
28923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.Intent;
29923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.IntentFilter;
30923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.SharedPreferences;
31923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.content.res.Configuration;
3236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasaniimport android.content.res.Resources;
33923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.inputmethodservice.InputMethodService;
34923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.inputmethodservice.Keyboard;
35923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.inputmethodservice.KeyboardView;
36923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.media.AudioManager;
37923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Debug;
38923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Handler;
39923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.Message;
40923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.os.SystemClock;
41923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.preference.PreferenceManager;
42960ea65f3f2162e7f8f387380924162d42fef4dcValentin Kravtsovimport android.speech.RecognitionManager;
436e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasaniimport android.text.AutoText;
44923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.text.ClipboardManager;
45923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.text.TextUtils;
46923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.Log;
47923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.PrintWriterPrinter;
48923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.util.Printer;
4966a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasaniimport android.view.HapticFeedbackConstants;
50923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.KeyEvent;
51466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport android.view.LayoutInflater;
52923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.View;
5381c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasaniimport android.view.ViewParent;
5481c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasaniimport android.view.ViewGroup;
55923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.Window;
56923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.WindowManager;
57923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.CompletionInfo;
58923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.EditorInfo;
59466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport android.view.inputmethod.ExtractedText;
60466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport android.view.inputmethod.ExtractedTextRequest;
61923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.InputConnection;
62923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport android.view.inputmethod.InputMethodManager;
63923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
64466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.io.FileDescriptor;
65466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.io.PrintWriter;
66466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.util.ArrayList;
67db84e0318cbbfa364abb364d961cb5e0d6015012Amith Yamasaniimport java.util.Collections;
68466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.util.HashMap;
69466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.util.List;
70466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.util.Locale;
71466741d8a78965b8509bf527344f289e50873092Mike LeBeauimport java.util.Map;
72466741d8a78965b8509bf527344f289e50873092Mike LeBeau
73923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/**
74923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Input method implementation for Qwerty'ish keyboard.
75923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */
76466741d8a78965b8509bf527344f289e50873092Mike LeBeaupublic class LatinIME extends InputMethodService
7736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        implements KeyboardView.OnKeyboardActionListener,
78466741d8a78965b8509bf527344f289e50873092Mike LeBeau        VoiceInput.UiListener,
79466741d8a78965b8509bf527344f289e50873092Mike LeBeau        SharedPreferences.OnSharedPreferenceChangeListener {
80466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private static final String TAG = "LatinIME";
81923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    static final boolean DEBUG = false;
82923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    static final boolean TRACE = false;
83466741d8a78965b8509bf527344f289e50873092Mike LeBeau    static final boolean VOICE_INSTALLED = true;
84466741d8a78965b8509bf527344f289e50873092Mike LeBeau    static final boolean ENABLE_VOICE_BUTTON = true;
85a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
86923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private static final String PREF_VIBRATE_ON = "vibrate_on";
87923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private static final String PREF_SOUND_ON = "sound_on";
88923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private static final String PREF_AUTO_CAP = "auto_cap";
896e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani    private static final String PREF_QUICK_FIXES = "quick_fixes";
906e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani    private static final String PREF_SHOW_SUGGESTIONS = "show_suggestions";
916e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani    private static final String PREF_AUTO_COMPLETE = "auto_complete";
92457fdffce4550b5597435f030483dcafffecf714Amith Yamasani    private static final String PREF_VOICE_MODE = "voice_mode";
93b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani
94466741d8a78965b8509bf527344f289e50873092Mike LeBeau    // Whether or not the user has used voice input before (and thus, whether to show the
95a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker    // first-run warning dialog or not).
96466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private static final String PREF_HAS_USED_VOICE_INPUT = "has_used_voice_input";
97a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
98466741d8a78965b8509bf527344f289e50873092Mike LeBeau    // Whether or not the user has used voice input from an unsupported locale UI before.
99466741d8a78965b8509bf527344f289e50873092Mike LeBeau    // For example, the user has a Chinese UI but activates voice input.
100466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private static final String PREF_HAS_USED_VOICE_INPUT_UNSUPPORTED_LOCALE =
101466741d8a78965b8509bf527344f289e50873092Mike LeBeau            "has_used_voice_input_unsupported_locale";
102466741d8a78965b8509bf527344f289e50873092Mike LeBeau
103466741d8a78965b8509bf527344f289e50873092Mike LeBeau    // A list of locales which are supported by default for voice input, unless we get a
104466741d8a78965b8509bf527344f289e50873092Mike LeBeau    // different list from Gservices.
105466741d8a78965b8509bf527344f289e50873092Mike LeBeau    public static final String DEFAULT_VOICE_INPUT_SUPPORTED_LOCALES =
106466741d8a78965b8509bf527344f289e50873092Mike LeBeau            "en " +
107466741d8a78965b8509bf527344f289e50873092Mike LeBeau            "en_US " +
108466741d8a78965b8509bf527344f289e50873092Mike LeBeau            "en_GB " +
109466741d8a78965b8509bf527344f289e50873092Mike LeBeau            "en_AU " +
110466741d8a78965b8509bf527344f289e50873092Mike LeBeau            "en_CA " +
111466741d8a78965b8509bf527344f289e50873092Mike LeBeau            "en_IE " +
112466741d8a78965b8509bf527344f289e50873092Mike LeBeau            "en_IN " +
113466741d8a78965b8509bf527344f289e50873092Mike LeBeau            "en_NZ " +
114466741d8a78965b8509bf527344f289e50873092Mike LeBeau            "en_SG " +
115466741d8a78965b8509bf527344f289e50873092Mike LeBeau            "en_ZA ";
116a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
117466741d8a78965b8509bf527344f289e50873092Mike LeBeau    // The private IME option used to indicate that no microphone should be shown for a
118466741d8a78965b8509bf527344f289e50873092Mike LeBeau    // given text field. For instance this is specified by the search dialog when the
119466741d8a78965b8509bf527344f289e50873092Mike LeBeau    // dialog is already showing a voice search button.
120466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private static final String IME_OPTION_NO_MICROPHONE = "nm";
121a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
12236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani    public static final String PREF_SELECTED_LANGUAGES = "selected_languages";
12336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani    public static final String PREF_INPUT_LANGUAGE = "input_language";
124923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
125923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private static final int MSG_UPDATE_SUGGESTIONS = 0;
1266e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani    private static final int MSG_START_TUTORIAL = 1;
1274a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani    private static final int MSG_UPDATE_SHIFT_STATE = 2;
128466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private static final int MSG_VOICE_RESULTS = 3;
129466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private static final int MSG_START_LISTENING_AFTER_SWIPE = 4;
130466741d8a78965b8509bf527344f289e50873092Mike LeBeau
131466741d8a78965b8509bf527344f289e50873092Mike LeBeau    // If we detect a swipe gesture within N ms of typing, then swipe is
132466741d8a78965b8509bf527344f289e50873092Mike LeBeau    // ignored, since it may in fact be two key presses in quick succession.
133466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private static final long MIN_MILLIS_AFTER_TYPING_BEFORE_SWIPE = 1000;
134466741d8a78965b8509bf527344f289e50873092Mike LeBeau
135923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    // How many continuous deletes at which to start deleting at a higher speed.
136923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private static final int DELETE_ACCELERATE_AT = 20;
137923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    // Key events coming any faster than this are long-presses.
138d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani    private static final int QUICK_PRESS = 200;
139a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
140d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani    static final int KEYCODE_ENTER = '\n';
141d67fe0e7583f1be18b35b33b7658e4427f1e3dedAmith Yamasani    static final int KEYCODE_SPACE = ' ';
1424ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa    static final int KEYCODE_PERIOD = '.';
143923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
144923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    // Contextual menu positions
145923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private static final int POS_SETTINGS = 0;
146923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private static final int POS_METHOD = 1;
147466741d8a78965b8509bf527344f289e50873092Mike LeBeau
148923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private LatinKeyboardView mInputView;
149923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private CandidateViewContainer mCandidateViewContainer;
150923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private CandidateView mCandidateView;
151923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private Suggest mSuggest;
152923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private CompletionInfo[] mCompletions;
153a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
154923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private AlertDialog mOptionsDialog;
155466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private AlertDialog mVoiceWarningDialog;
156a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
1576e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani    KeyboardSwitcher mKeyboardSwitcher;
158a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
159923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private UserDictionary mUserDictionary;
1602bed1531c2c9bd48096bfa97dd1a39e04bd15e7bEric Fischer    private ContactsDictionary mContactsDictionary;
16134386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani    private ExpandableDictionary mAutoDictionary;
16236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani
163466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private Hints mHints;
164a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
16536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani    Resources mResources;
16636fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani
1676c2f9f5ba7afedc183086d4ee3a7aa50b3866edcAmith Yamasani    private String mInputLocale;
1686c2f9f5ba7afedc183086d4ee3a7aa50b3866edcAmith Yamasani    private String mSystemLocale;
1693f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    private LanguageSwitcher mLanguageSwitcher;
170923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
171923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private StringBuilder mComposing = new StringBuilder();
172923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private WordComposer mWord = new WordComposer();
173923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private int mCommittedLength;
174923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private boolean mPredicting;
175466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private boolean mRecognizing;
176466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private boolean mAfterVoiceInput;
177466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private boolean mImmediatelyAfterVoiceInput;
178466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private boolean mShowingVoiceSuggestions;
179466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private boolean mImmediatelyAfterVoiceSuggestions;
180466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private boolean mVoiceInputHighlighted;
181466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private boolean mEnableVoiceButton;
182923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private CharSequence mBestWord;
183923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private boolean mPredictionOn;
184923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private boolean mCompletionOn;
185e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani    private boolean mHasDictionary;
186923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private boolean mAutoSpace;
1879a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa    private boolean mJustAddedAutoSpace;
188e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani    private boolean mAutoCorrectEnabled;
189923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private boolean mAutoCorrectOn;
190923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private boolean mCapsLock;
191466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private boolean mPasswordText;
192466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private boolean mEmailText;
193923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private boolean mVibrateOn;
194923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private boolean mSoundOn;
195923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private boolean mAutoCap;
1966e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani    private boolean mQuickFixes;
197466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private boolean mHasUsedVoiceInput;
198466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private boolean mHasUsedVoiceInputUnsupportedLocale;
199466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private boolean mLocaleSupportedForVoiceInput;
2006e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani    private boolean mShowSuggestions;
201466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private boolean mSuggestionShouldReplaceCurrentWord;
202466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private boolean mIsShowingHint;
2036e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani    private int     mCorrectionMode;
204466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private boolean mEnableVoice = true;
205b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani    private boolean mVoiceOnPrimary;
206b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani    private int     mOrientation;
2076a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani    private List<CharSequence> mSuggestPuncList;
208a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
209923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    // Indicates whether the suggestion strip is to be on in landscape
210923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private boolean mJustAccepted;
211923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private CharSequence mJustRevertedSeparator;
212923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private int mDeleteCount;
213923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private long mLastKeyTime;
214a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
215923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private Tutorial mTutorial;
216923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
217923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private AudioManager mAudioManager;
2182296317b8f0209789f797ac8a2fcb70e03f6d001Eric Laurent    // Align sound effect volume on music volume
2192296317b8f0209789f797ac8a2fcb70e03f6d001Eric Laurent    private final float FX_VOLUME = -1.0f;
220923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private boolean mSilentMode;
221923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
222923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private String mWordSeparators;
223923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private String mSentenceSeparators;
224466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private VoiceInput mVoiceInput;
225466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private VoiceResults mVoiceResults = new VoiceResults();
226466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private long mSwipeTriggerTimeMillis;
22781c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani    private boolean mConfigurationChanging;
228466741d8a78965b8509bf527344f289e50873092Mike LeBeau
229466741d8a78965b8509bf527344f289e50873092Mike LeBeau    // For each word, a list of potential replacements, usually from voice.
23066a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani    private Map<String, List<CharSequence>> mWordToSuggestions =
23166a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani            new HashMap<String, List<CharSequence>>();
232466741d8a78965b8509bf527344f289e50873092Mike LeBeau
233466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private class VoiceResults {
234466741d8a78965b8509bf527344f289e50873092Mike LeBeau        List<String> candidates;
235466741d8a78965b8509bf527344f289e50873092Mike LeBeau        Map<String, List<CharSequence>> alternatives;
236466741d8a78965b8509bf527344f289e50873092Mike LeBeau    }
2374f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett
23836fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani    private boolean mRefreshKeyboardRequired;
23936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani
240923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    Handler mHandler = new Handler() {
241923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        @Override
242923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        public void handleMessage(Message msg) {
243923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            switch (msg.what) {
244923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                case MSG_UPDATE_SUGGESTIONS:
245923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    updateSuggestions();
246923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    break;
2476e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani                case MSG_START_TUTORIAL:
2486e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani                    if (mTutorial == null) {
2496e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani                        if (mInputView.isShown()) {
2506e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani                            mTutorial = new Tutorial(LatinIME.this, mInputView);
2516e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani                            mTutorial.start();
2526e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani                        } else {
2536e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani                            // Try again soon if the view is not yet showing
2546e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani                            sendMessageDelayed(obtainMessage(MSG_START_TUTORIAL), 100);
2556e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani                        }
256923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    }
257923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    break;
2584a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani                case MSG_UPDATE_SHIFT_STATE:
2594a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani                    updateShiftKeyState(getCurrentInputEditorInfo());
2604a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani                    break;
261466741d8a78965b8509bf527344f289e50873092Mike LeBeau                case MSG_VOICE_RESULTS:
262466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    handleVoiceResults();
263466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    break;
264466741d8a78965b8509bf527344f289e50873092Mike LeBeau                case MSG_START_LISTENING_AFTER_SWIPE:
265466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    if (mLastKeyTime < mSwipeTriggerTimeMillis) {
266466741d8a78965b8509bf527344f289e50873092Mike LeBeau                        startListening(true);
267466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    }
268923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            }
269923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
270923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    };
271923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
272923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    @Override public void onCreate() {
273923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        super.onCreate();
274923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        //setStatusIcon(R.drawable.ime_qwerty);
27536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        mResources = getResources();
27636fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        final Configuration conf = mResources.getConfiguration();
2773f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
2783f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        mLanguageSwitcher = new LanguageSwitcher(this);
2793f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        mLanguageSwitcher.loadLocales(prefs);
2803f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        mKeyboardSwitcher = new KeyboardSwitcher(this, this);
2813f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        mKeyboardSwitcher.setLanguageSwitcher(mLanguageSwitcher);
2826c2f9f5ba7afedc183086d4ee3a7aa50b3866edcAmith Yamasani        mSystemLocale = conf.locale.toString();
2833f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        String inputLanguage = mLanguageSwitcher.getInputLanguage();
2843f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        if (inputLanguage == null) {
2853f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            inputLanguage = conf.locale.toString();
2863f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        }
2873f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        initSuggest(inputLanguage);
288b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani        mOrientation = conf.orientation;
2896a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani        initSuggestPuncList();
290b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani
291923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        // register to receive ringer mode changes for silent mode
292923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION);
293923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        registerReceiver(mReceiver, filter);
294466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (VOICE_INSTALLED) {
295466741d8a78965b8509bf527344f289e50873092Mike LeBeau            mVoiceInput = new VoiceInput(this, this);
296466741d8a78965b8509bf527344f289e50873092Mike LeBeau            mHints = new Hints(this, new Hints.Display() {
297466741d8a78965b8509bf527344f289e50873092Mike LeBeau                public void showHint(int viewResource) {
298466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    LayoutInflater inflater = (LayoutInflater) getSystemService(
299466741d8a78965b8509bf527344f289e50873092Mike LeBeau                            Context.LAYOUT_INFLATER_SERVICE);
300466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    View view = inflater.inflate(viewResource, null);
301466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    setCandidatesView(view);
302466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    setCandidatesViewShown(true);
303466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    mIsShowingHint = true;
304466741d8a78965b8509bf527344f289e50873092Mike LeBeau                }
305466741d8a78965b8509bf527344f289e50873092Mike LeBeau              });
306466741d8a78965b8509bf527344f289e50873092Mike LeBeau        }
3073f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        prefs.registerOnSharedPreferenceChangeListener(this);
308923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
30936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani
310923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private void initSuggest(String locale) {
3116c2f9f5ba7afedc183086d4ee3a7aa50b3866edcAmith Yamasani        mInputLocale = locale;
31236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani
31336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        Resources orig = getResources();
31436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        Configuration conf = orig.getConfiguration();
31536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        Locale saveLocale = conf.locale;
31636fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        conf.locale = new Locale(locale);
31736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        orig.updateConfiguration(conf, orig.getDisplayMetrics());
31836fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        if (mSuggest != null) {
31936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani            mSuggest.close();
32036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        }
32132e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
32232e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani        mQuickFixes = sp.getBoolean(PREF_QUICK_FIXES, true);
323923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mSuggest = new Suggest(this, R.raw.main);
32432e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani        updateAutoTextEnabled(saveLocale);
325d8564506124fe6a683ef0adf8ca5cf5348756f8dMike LeBeau        if (mUserDictionary != null) mUserDictionary.close();
3266c2f9f5ba7afedc183086d4ee3a7aa50b3866edcAmith Yamasani        mUserDictionary = new UserDictionary(this, mInputLocale);
32736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        if (mContactsDictionary == null) {
32836fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani            mContactsDictionary = new ContactsDictionary(this);
32936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        }
3306516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani        if (mAutoDictionary != null) {
3316516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani            mAutoDictionary.close();
33236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        }
3336c2f9f5ba7afedc183086d4ee3a7aa50b3866edcAmith Yamasani        mAutoDictionary = new AutoDictionary(this, this, mInputLocale);
334923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mSuggest.setUserDictionary(mUserDictionary);
3352bed1531c2c9bd48096bfa97dd1a39e04bd15e7bEric Fischer        mSuggest.setContactsDictionary(mContactsDictionary);
33634386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani        mSuggest.setAutoDictionary(mAutoDictionary);
337e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani        updateCorrectionMode();
33836fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        mWordSeparators = mResources.getString(R.string.word_separators);
33936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        mSentenceSeparators = mResources.getString(R.string.sentence_separators);
34036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani
34136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        conf.locale = saveLocale;
34236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        orig.updateConfiguration(conf, orig.getDisplayMetrics());
343923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
34436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani
345466741d8a78965b8509bf527344f289e50873092Mike LeBeau    @Override
346466741d8a78965b8509bf527344f289e50873092Mike LeBeau    public void onDestroy() {
347923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mUserDictionary.close();
3482bed1531c2c9bd48096bfa97dd1a39e04bd15e7bEric Fischer        mContactsDictionary.close();
349923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        unregisterReceiver(mReceiver);
350466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (VOICE_INSTALLED) {
351466741d8a78965b8509bf527344f289e50873092Mike LeBeau            mVoiceInput.destroy();
352466741d8a78965b8509bf527344f289e50873092Mike LeBeau        }
353923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        super.onDestroy();
354923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
355923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
356923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    @Override
357923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public void onConfigurationChanged(Configuration conf) {
358a9f4b19ca409f55a88f7dbe0e8b1c17a37717ac7Amith Yamasani        // If the system locale changes and is different from the saved
3596c2f9f5ba7afedc183086d4ee3a7aa50b3866edcAmith Yamasani        // locale (mSystemLocale), then reload the input locale list from the
360a9f4b19ca409f55a88f7dbe0e8b1c17a37717ac7Amith Yamasani        // latin ime settings (shared prefs) and reset the input locale
361a9f4b19ca409f55a88f7dbe0e8b1c17a37717ac7Amith Yamasani        // to the first one.
3626c2f9f5ba7afedc183086d4ee3a7aa50b3866edcAmith Yamasani        final String systemLocale = conf.locale.toString();
3636c2f9f5ba7afedc183086d4ee3a7aa50b3866edcAmith Yamasani        if (!TextUtils.equals(systemLocale, mSystemLocale)) {
3646c2f9f5ba7afedc183086d4ee3a7aa50b3866edcAmith Yamasani            mSystemLocale = systemLocale;
365a9f4b19ca409f55a88f7dbe0e8b1c17a37717ac7Amith Yamasani            if (mLanguageSwitcher != null) {
366a9f4b19ca409f55a88f7dbe0e8b1c17a37717ac7Amith Yamasani                mLanguageSwitcher.loadLocales(
367a9f4b19ca409f55a88f7dbe0e8b1c17a37717ac7Amith Yamasani                        PreferenceManager.getDefaultSharedPreferences(this));
368a9f4b19ca409f55a88f7dbe0e8b1c17a37717ac7Amith Yamasani                toggleLanguage(true, true);
369a9f4b19ca409f55a88f7dbe0e8b1c17a37717ac7Amith Yamasani            } else {
370a9f4b19ca409f55a88f7dbe0e8b1c17a37717ac7Amith Yamasani                reloadKeyboards();
371a9f4b19ca409f55a88f7dbe0e8b1c17a37717ac7Amith Yamasani            }
372923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
373b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani        // If orientation changed while predicting, commit the change
374b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani        if (conf.orientation != mOrientation) {
375466741d8a78965b8509bf527344f289e50873092Mike LeBeau            InputConnection ic = getCurrentInputConnection();
376466741d8a78965b8509bf527344f289e50873092Mike LeBeau            commitTyped(ic);
377466741d8a78965b8509bf527344f289e50873092Mike LeBeau            if (ic != null) ic.finishComposingText(); // For voice input
378b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani            mOrientation = conf.orientation;
379a9f4b19ca409f55a88f7dbe0e8b1c17a37717ac7Amith Yamasani            reloadKeyboards();
380b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani        }
38181c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani        mConfigurationChanging = true;
382923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        super.onConfigurationChanged(conf);
38381c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani        if (mRecognizing) {
38481c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani            switchToRecognitionStatusView();
38581c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani        }
38681c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani        mConfigurationChanging = false;
387923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
388b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani
389923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    @Override
390923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public View onCreateInputView() {
391923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mInputView = (LatinKeyboardView) getLayoutInflater().inflate(
392923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                R.layout.input, null);
393923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mKeyboardSwitcher.setInputView(mInputView);
39412e582c79c4e8028bb03971377633440aa95cefbAmith Yamasani        mKeyboardSwitcher.makeKeyboards(true);
395923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mInputView.setOnKeyboardActionListener(this);
396466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mKeyboardSwitcher.setKeyboardMode(
397466741d8a78965b8509bf527344f289e50873092Mike LeBeau                KeyboardSwitcher.MODE_TEXT, 0,
398466741d8a78965b8509bf527344f289e50873092Mike LeBeau                shouldShowVoiceButton(makeFieldContext(), getCurrentInputEditorInfo()));
399923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        return mInputView;
400923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
401923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
402923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    @Override
403923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public View onCreateCandidatesView() {
40412e582c79c4e8028bb03971377633440aa95cefbAmith Yamasani        mKeyboardSwitcher.makeKeyboards(true);
405923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mCandidateViewContainer = (CandidateViewContainer) getLayoutInflater().inflate(
406923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                R.layout.candidates, null);
407923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mCandidateViewContainer.initViews();
408923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mCandidateView = (CandidateView) mCandidateViewContainer.findViewById(R.id.candidates);
409923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mCandidateView.setService(this);
410923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        setCandidatesViewShown(true);
411923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        return mCandidateViewContainer;
412923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
413923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
414a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker    @Override
415923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public void onStartInputView(EditorInfo attribute, boolean restarting) {
416923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        // In landscape mode, this method gets called without the input view being created.
417923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mInputView == null) {
418923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            return;
419923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
420923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
42136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        if (mRefreshKeyboardRequired) {
42236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani            mRefreshKeyboardRequired = false;
4233f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            toggleLanguage(true, true);
42436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        }
42536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani
42612e582c79c4e8028bb03971377633440aa95cefbAmith Yamasani        mKeyboardSwitcher.makeKeyboards(false);
4276c7c8f5b477e7aea207d41417092e8b92db2e24fAmith Yamasani
428923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        TextEntryState.newSession(this);
4296c7c8f5b477e7aea207d41417092e8b92db2e24fAmith Yamasani
430466741d8a78965b8509bf527344f289e50873092Mike LeBeau        // Most such things we decide below in the switch statement, but we need to know
431466741d8a78965b8509bf527344f289e50873092Mike LeBeau        // now whether this is a password text field, because we need to know now (before
432466741d8a78965b8509bf527344f289e50873092Mike LeBeau        // the switch statement) whether we want to enable the voice button.
433466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mPasswordText = false;
434466741d8a78965b8509bf527344f289e50873092Mike LeBeau        int variation = attribute.inputType & EditorInfo.TYPE_MASK_VARIATION;
435466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (variation == EditorInfo.TYPE_TEXT_VARIATION_PASSWORD ||
436466741d8a78965b8509bf527344f289e50873092Mike LeBeau                variation == EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD) {
437466741d8a78965b8509bf527344f289e50873092Mike LeBeau            mPasswordText = true;
438466741d8a78965b8509bf527344f289e50873092Mike LeBeau        }
439a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
440466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mEnableVoiceButton = shouldShowVoiceButton(makeFieldContext(), attribute);
441b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani        final boolean enableVoiceButton = mEnableVoiceButton && mEnableVoice;
442466741d8a78965b8509bf527344f289e50873092Mike LeBeau
443466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mAfterVoiceInput = false;
444466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mImmediatelyAfterVoiceInput = false;
445466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mShowingVoiceSuggestions = false;
446466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mImmediatelyAfterVoiceSuggestions = false;
447466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mVoiceInputHighlighted = false;
448466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mWordToSuggestions.clear();
449e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani        mInputTypeNoAutoCorrect = false;
450923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mPredictionOn = false;
451923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mCompletionOn = false;
452923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mCompletions = null;
453923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mCapsLock = false;
454466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mEmailText = false;
455466741d8a78965b8509bf527344f289e50873092Mike LeBeau        switch (attribute.inputType & EditorInfo.TYPE_MASK_CLASS) {
456923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            case EditorInfo.TYPE_CLASS_NUMBER:
457923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            case EditorInfo.TYPE_CLASS_DATETIME:
458e3803800c53cc813e27dd1e7c31bdb4d075f0252Amith Yamasani                mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_SYMBOLS,
459b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani                        attribute.imeOptions, enableVoiceButton);
460923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                break;
461923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            case EditorInfo.TYPE_CLASS_PHONE:
462923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_PHONE,
463b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani                        attribute.imeOptions, enableVoiceButton);
464923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                break;
465923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            case EditorInfo.TYPE_CLASS_TEXT:
466923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_TEXT,
467b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani                        attribute.imeOptions, enableVoiceButton);
468923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                //startPrediction();
469923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mPredictionOn = true;
470923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                // Make sure that passwords are not displayed in candidate view
471923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                if (variation == EditorInfo.TYPE_TEXT_VARIATION_PASSWORD ||
472923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                        variation == EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD ) {
473923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mPredictionOn = false;
474923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                }
475466741d8a78965b8509bf527344f289e50873092Mike LeBeau                if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS) {
476466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    mEmailText = true;
477466741d8a78965b8509bf527344f289e50873092Mike LeBeau                }
478923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
479923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                        || variation == EditorInfo.TYPE_TEXT_VARIATION_PERSON_NAME) {
480923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mAutoSpace = false;
481923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                } else {
482923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mAutoSpace = true;
483923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                }
484923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS) {
485923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mPredictionOn = false;
486923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_EMAIL,
487b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani                            attribute.imeOptions, enableVoiceButton);
488923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                } else if (variation == EditorInfo.TYPE_TEXT_VARIATION_URI) {
489923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mPredictionOn = false;
490923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_URL,
491b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani                            attribute.imeOptions, enableVoiceButton);
492923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                } else if (variation == EditorInfo.TYPE_TEXT_VARIATION_SHORT_MESSAGE) {
493923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_IM,
494b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani                            attribute.imeOptions, enableVoiceButton);
495923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                } else if (variation == EditorInfo.TYPE_TEXT_VARIATION_FILTER) {
496923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mPredictionOn = false;
4976c7c8f5b477e7aea207d41417092e8b92db2e24fAmith Yamasani                } else if (variation == EditorInfo.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) {
498cf02653097893b06f24551b790b0f7ec288e704dAmith Yamasani                    mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_WEB,
499b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani                            attribute.imeOptions, enableVoiceButton);
5006c7c8f5b477e7aea207d41417092e8b92db2e24fAmith Yamasani                    // If it's a browser edit field and auto correct is not ON explicitly, then
5016c7c8f5b477e7aea207d41417092e8b92db2e24fAmith Yamasani                    // disable auto correction, but keep suggestions on.
5026c7c8f5b477e7aea207d41417092e8b92db2e24fAmith Yamasani                    if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) {
503e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani                        mInputTypeNoAutoCorrect = true;
5046c7c8f5b477e7aea207d41417092e8b92db2e24fAmith Yamasani                    }
505923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                }
50636ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani
50736ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani                // If NO_SUGGESTIONS is set, don't do prediction.
50836ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani                if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0) {
50936ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani                    mPredictionOn = false;
510e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani                    mInputTypeNoAutoCorrect = true;
51136ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani                }
51236ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani                // If it's not multiline and the autoCorrect flag is not set, then don't correct
51336ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani                if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0 &&
51436ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani                        (attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE) == 0) {
515e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani                    mInputTypeNoAutoCorrect = true;
51636ebae2e8d58d36d3f8dd2f8a2d34c0c06522a8eAmith Yamasani                }
517923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                if ((attribute.inputType&EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) {
518923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mPredictionOn = false;
519923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mCompletionOn = true && isFullscreenMode();
520923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                }
521923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                updateShiftKeyState(attribute);
522923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                break;
523923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            default:
524923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_TEXT,
525b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani                        attribute.imeOptions, enableVoiceButton);
526923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                updateShiftKeyState(attribute);
527923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
528923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mInputView.closing();
529923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mComposing.setLength(0);
530923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mPredicting = false;
531923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mDeleteCount = 0;
5329a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa        mJustAddedAutoSpace = false;
533923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        loadSettings();
5344032c24b7360e8d0ba5cd1e0e605cf3b7b1e3e29Amith Yamasani        updateShiftKeyState(attribute);
535e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani
536466741d8a78965b8509bf527344f289e50873092Mike LeBeau        setCandidatesViewShown(false);
537466741d8a78965b8509bf527344f289e50873092Mike LeBeau        setSuggestions(null, false, false, false);
538466741d8a78965b8509bf527344f289e50873092Mike LeBeau
539e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani        // If the dictionary is not big enough, don't auto correct
540e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani        mHasDictionary = mSuggest.hasMainDictionary();
541e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani
542e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani        updateCorrectionMode();
543e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani
5446e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani        mInputView.setProximityCorrectionEnabled(true);
54532e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani        mPredictionOn = mPredictionOn && (mCorrectionMode > 0 || mShowSuggestions);
5466e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani        checkTutorial(attribute.privateImeOptions);
5474a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani        if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
548923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
549923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
550923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    @Override
551923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public void onFinishInput() {
552923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        super.onFinishInput();
553a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
55481c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani        if (VOICE_INSTALLED && !mConfigurationChanging) {
55581c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani            if (mAfterVoiceInput) {
5564f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett                mVoiceInput.flushAllTextModificationCounters();
55781c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani                mVoiceInput.logInputEnded();
55881c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani            }
5591322b7f899e9d3ccfb91d9e3ede99b3ad336c354Kristian Monsen            mVoiceInput.flushLogs();
56081c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani            mVoiceInput.cancel();
5611322b7f899e9d3ccfb91d9e3ede99b3ad336c354Kristian Monsen        }
562923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mInputView != null) {
563923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mInputView.closing();
564923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
565466741d8a78965b8509bf527344f289e50873092Mike LeBeau    }
566466741d8a78965b8509bf527344f289e50873092Mike LeBeau
567466741d8a78965b8509bf527344f289e50873092Mike LeBeau    @Override
568466741d8a78965b8509bf527344f289e50873092Mike LeBeau    public void onUpdateExtractedText(int token, ExtractedText text) {
569466741d8a78965b8509bf527344f289e50873092Mike LeBeau        super.onUpdateExtractedText(token, text);
570466741d8a78965b8509bf527344f289e50873092Mike LeBeau        InputConnection ic = getCurrentInputConnection();
571466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (!mImmediatelyAfterVoiceInput && mAfterVoiceInput && ic != null) {
572466741d8a78965b8509bf527344f289e50873092Mike LeBeau            if (mHints.showPunctuationHintIfNecessary(ic)) {
573466741d8a78965b8509bf527344f289e50873092Mike LeBeau                mVoiceInput.logPunctuationHintDisplayed();
574466741d8a78965b8509bf527344f289e50873092Mike LeBeau            }
575466741d8a78965b8509bf527344f289e50873092Mike LeBeau        }
576466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mImmediatelyAfterVoiceInput = false;
577923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
578923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
579923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    @Override
580923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public void onUpdateSelection(int oldSelStart, int oldSelEnd,
581923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            int newSelStart, int newSelEnd,
582923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            int candidatesStart, int candidatesEnd) {
583923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd,
584923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                candidatesStart, candidatesEnd);
585466741d8a78965b8509bf527344f289e50873092Mike LeBeau
586466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (DEBUG) {
587466741d8a78965b8509bf527344f289e50873092Mike LeBeau            Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart
588466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    + ", ose=" + oldSelEnd
589466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    + ", nss=" + newSelStart
590466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    + ", nse=" + newSelEnd
591466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    + ", cs=" + candidatesStart
592466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    + ", ce=" + candidatesEnd);
593466741d8a78965b8509bf527344f289e50873092Mike LeBeau        }
594466741d8a78965b8509bf527344f289e50873092Mike LeBeau
5954f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett        if (mAfterVoiceInput) {
5964f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett            mVoiceInput.setCursorPos(newSelEnd);
5974f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett            mVoiceInput.setSelectionSpan(newSelEnd - newSelStart);
5984f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett        }
5994f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett
600466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mSuggestionShouldReplaceCurrentWord = false;
601923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        // If the current selection in the text view changes, we should
602923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        // clear whatever candidate text we have.
603466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if ((((mComposing.length() > 0 && mPredicting) || mVoiceInputHighlighted)
604466741d8a78965b8509bf527344f289e50873092Mike LeBeau                && (newSelStart != candidatesEnd
605466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    || newSelEnd != candidatesEnd))) {
606923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mComposing.setLength(0);
607923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mPredicting = false;
608923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            updateSuggestions();
609923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            TextEntryState.reset();
610923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            InputConnection ic = getCurrentInputConnection();
611923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            if (ic != null) {
612923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                ic.finishComposingText();
613923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            }
614466741d8a78965b8509bf527344f289e50873092Mike LeBeau            mVoiceInputHighlighted = false;
6159a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa        } else if (!mPredicting && !mJustAccepted) {
6169a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa            switch (TextEntryState.getState()) {
6179a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa                case TextEntryState.STATE_ACCEPTED_DEFAULT:
6189a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa                    TextEntryState.reset();
6199a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa                    // fall through
6209a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa                case TextEntryState.STATE_SPACE_AFTER_PICKED:
6219a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa                    mJustAddedAutoSpace = false;  // The user moved the cursor.
6229a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa                    break;
6239a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa            }
624923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
625923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mJustAccepted = false;
6263263841911dc3dbbf4ffe26d2f046e38a1896f72Amith Yamasani        postUpdateShiftKeyState();
627466741d8a78965b8509bf527344f289e50873092Mike LeBeau
628466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (VOICE_INSTALLED) {
629466741d8a78965b8509bf527344f289e50873092Mike LeBeau            if (mShowingVoiceSuggestions) {
630466741d8a78965b8509bf527344f289e50873092Mike LeBeau                if (mImmediatelyAfterVoiceSuggestions) {
631466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    mImmediatelyAfterVoiceSuggestions = false;
632466741d8a78965b8509bf527344f289e50873092Mike LeBeau                } else {
633466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    updateSuggestions();
634466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    mShowingVoiceSuggestions = false;
635466741d8a78965b8509bf527344f289e50873092Mike LeBeau                }
636466741d8a78965b8509bf527344f289e50873092Mike LeBeau            }
637466741d8a78965b8509bf527344f289e50873092Mike LeBeau            if (VoiceInput.ENABLE_WORD_CORRECTIONS) {
638466741d8a78965b8509bf527344f289e50873092Mike LeBeau                // If we have alternatives for the current word, then show them.
639466741d8a78965b8509bf527344f289e50873092Mike LeBeau                String word = EditingUtil.getWordAtCursor(
640466741d8a78965b8509bf527344f289e50873092Mike LeBeau                        getCurrentInputConnection(), getWordSeparators());
641466741d8a78965b8509bf527344f289e50873092Mike LeBeau                if (word != null && mWordToSuggestions.containsKey(word.trim())) {
642466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    mSuggestionShouldReplaceCurrentWord = true;
643466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    final List<CharSequence> suggestions = mWordToSuggestions.get(word.trim());
644466741d8a78965b8509bf527344f289e50873092Mike LeBeau
645466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    setSuggestions(suggestions, false, true, true);
646466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    setCandidatesViewShown(true);
647466741d8a78965b8509bf527344f289e50873092Mike LeBeau                }
648466741d8a78965b8509bf527344f289e50873092Mike LeBeau            }
649466741d8a78965b8509bf527344f289e50873092Mike LeBeau        }
650923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
651923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
652923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    @Override
653923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public void hideWindow() {
654923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (TRACE) Debug.stopMethodTracing();
6556e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani        if (mOptionsDialog != null && mOptionsDialog.isShowing()) {
6566e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani            mOptionsDialog.dismiss();
6576e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani            mOptionsDialog = null;
6586e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani        }
65981c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani        if (!mConfigurationChanging) {
66081c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani            if (mAfterVoiceInput) mVoiceInput.logInputEnded();
66181c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani            if (mVoiceWarningDialog != null && mVoiceWarningDialog.isShowing()) {
66281c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani                mVoiceInput.logKeyboardWarningDialogDismissed();
66381c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani                mVoiceWarningDialog.dismiss();
66481c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani                mVoiceWarningDialog = null;
66581c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani            }
66681c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani            if (VOICE_INSTALLED & mRecognizing) {
66781c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani                mVoiceInput.cancel();
66881c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani            }
669466741d8a78965b8509bf527344f289e50873092Mike LeBeau        }
670923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        super.hideWindow();
671923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        TextEntryState.endSession();
672923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
673923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
674923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    @Override
675923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public void onDisplayCompletions(CompletionInfo[] completions) {
676923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (false) {
677923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            Log.i("foo", "Received completions:");
678923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            for (int i=0; i<(completions != null ? completions.length : 0); i++) {
679923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                Log.i("foo", "  #" + i + ": " + completions[i]);
680923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            }
681923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
682923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mCompletionOn) {
683923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mCompletions = completions;
684923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            if (completions == null) {
685466741d8a78965b8509bf527344f289e50873092Mike LeBeau                setSuggestions(null, false, false, false);
686923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                return;
687923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            }
688a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
689923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            List<CharSequence> stringList = new ArrayList<CharSequence>();
690923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            for (int i=0; i<(completions != null ? completions.length : 0); i++) {
691923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                CompletionInfo ci = completions[i];
692923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                if (ci != null) stringList.add(ci.getText());
693923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            }
694923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            //CharSequence typedWord = mWord.getTypedWord();
695466741d8a78965b8509bf527344f289e50873092Mike LeBeau            setSuggestions(stringList, true, true, true);
696923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mBestWord = null;
697923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            setCandidatesViewShown(isCandidateStripVisible() || mCompletionOn);
698923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
699923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
700923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
701923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    @Override
702923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public void setCandidatesViewShown(boolean shown) {
703923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        // TODO: Remove this if we support candidates with hard keyboard
704923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (onEvaluateInputViewShown()) {
7058102ae79417448de25142ad328b74b0ee15bea1aAmith Yamasani            // Show the candidates view only if input view is showing
7068102ae79417448de25142ad328b74b0ee15bea1aAmith Yamasani            super.setCandidatesViewShown(shown && mInputView != null && mInputView.isShown());
707923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
708923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
709a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
710923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    @Override
711923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public void onComputeInsets(InputMethodService.Insets outInsets) {
712923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        super.onComputeInsets(outInsets);
713264b19a6853ab3d13d26270e99a13dc015b01bebThe Android Open Source Project        if (!isFullscreenMode()) {
714264b19a6853ab3d13d26270e99a13dc015b01bebThe Android Open Source Project            outInsets.contentTopInsets = outInsets.visibleTopInsets;
715264b19a6853ab3d13d26270e99a13dc015b01bebThe Android Open Source Project        }
716923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
717a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
718923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    @Override
719923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public boolean onKeyDown(int keyCode, KeyEvent event) {
720923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        switch (keyCode) {
721923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            case KeyEvent.KEYCODE_BACK:
722923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                if (event.getRepeatCount() == 0 && mInputView != null) {
723923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    if (mInputView.handleBack()) {
724923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                        return true;
7256e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani                    } else if (mTutorial != null) {
7266e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani                        mTutorial.close();
7276e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani                        mTutorial = null;
728923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    }
729923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                }
730923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                break;
7316e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani            case KeyEvent.KEYCODE_DPAD_DOWN:
7326e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani            case KeyEvent.KEYCODE_DPAD_UP:
7336e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani            case KeyEvent.KEYCODE_DPAD_LEFT:
7346e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani            case KeyEvent.KEYCODE_DPAD_RIGHT:
7356e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani                // If tutorial is visible, don't allow dpad to work
7366e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani                if (mTutorial != null) {
7376e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani                    return true;
7386e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani                }
7396e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani                break;
740923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
741923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        return super.onKeyDown(keyCode, event);
742923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
743923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
744923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    @Override
745923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public boolean onKeyUp(int keyCode, KeyEvent event) {
746923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        switch (keyCode) {
747923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_DOWN:
748923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_UP:
749923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_LEFT:
750923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_RIGHT:
7516e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani                // If tutorial is visible, don't allow dpad to work
7526e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani                if (mTutorial != null) {
7536e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani                    return true;
7546e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani                }
755923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                // Enable shift key and DPAD to do selections
756923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                if (mInputView != null && mInputView.isShown() && mInputView.isShifted()) {
757a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker                    event = new KeyEvent(event.getDownTime(), event.getEventTime(),
758923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                            event.getAction(), event.getKeyCode(), event.getRepeatCount(),
759923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                            event.getDeviceId(), event.getScanCode(),
760923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                            KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON);
761923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    InputConnection ic = getCurrentInputConnection();
762923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    if (ic != null) ic.sendKeyEvent(event);
763923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    return true;
764923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                }
765923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                break;
766923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
767923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        return super.onKeyUp(keyCode, event);
768923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
769923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
770466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private void revertVoiceInput() {
771466741d8a78965b8509bf527344f289e50873092Mike LeBeau        InputConnection ic = getCurrentInputConnection();
772466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (ic != null) ic.commitText("", 1);
773466741d8a78965b8509bf527344f289e50873092Mike LeBeau        updateSuggestions();
774466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mVoiceInputHighlighted = false;
775466741d8a78965b8509bf527344f289e50873092Mike LeBeau    }
776466741d8a78965b8509bf527344f289e50873092Mike LeBeau
777466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private void commitVoiceInput() {
778466741d8a78965b8509bf527344f289e50873092Mike LeBeau        InputConnection ic = getCurrentInputConnection();
779466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (ic != null) ic.finishComposingText();
780466741d8a78965b8509bf527344f289e50873092Mike LeBeau        updateSuggestions();
781466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mVoiceInputHighlighted = false;
782466741d8a78965b8509bf527344f289e50873092Mike LeBeau    }
783466741d8a78965b8509bf527344f289e50873092Mike LeBeau
78436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani    private void reloadKeyboards() {
78536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        if (mKeyboardSwitcher == null) {
78636fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani            mKeyboardSwitcher = new KeyboardSwitcher(this, this);
78736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        }
7883f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        mKeyboardSwitcher.setLanguageSwitcher(mLanguageSwitcher);
789b8f98ad014ac6f1d453128f902dba67ebebff1d3Amith Yamasani        if (mInputView != null) {
7901ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani            mKeyboardSwitcher.setVoiceMode(mEnableVoice && mEnableVoiceButton, mVoiceOnPrimary);
791b8f98ad014ac6f1d453128f902dba67ebebff1d3Amith Yamasani        }
79236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        mKeyboardSwitcher.makeKeyboards(true);
79336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani    }
79436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani
795923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private void commitTyped(InputConnection inputConnection) {
796923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mPredicting) {
797923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mPredicting = false;
798923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            if (mComposing.length() > 0) {
799923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                if (inputConnection != null) {
800923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    inputConnection.commitText(mComposing, 1);
801923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                }
802923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mCommittedLength = mComposing.length();
803923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                TextEntryState.acceptedTyped(mComposing);
8046516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani                checkAddToDictionary(mComposing, AutoDictionary.FREQUENCY_FOR_TYPED);
805923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            }
806923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            updateSuggestions();
807923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
808923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
809923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
8103263841911dc3dbbf4ffe26d2f046e38a1896f72Amith Yamasani    private void postUpdateShiftKeyState() {
8113263841911dc3dbbf4ffe26d2f046e38a1896f72Amith Yamasani        mHandler.removeMessages(MSG_UPDATE_SHIFT_STATE);
8123263841911dc3dbbf4ffe26d2f046e38a1896f72Amith Yamasani        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_UPDATE_SHIFT_STATE), 300);
8133263841911dc3dbbf4ffe26d2f046e38a1896f72Amith Yamasani    }
8143263841911dc3dbbf4ffe26d2f046e38a1896f72Amith Yamasani
815923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public void updateShiftKeyState(EditorInfo attr) {
816923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        InputConnection ic = getCurrentInputConnection();
817923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (attr != null && mInputView != null && mKeyboardSwitcher.isAlphabetMode()
818923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                && ic != null) {
8191c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani            mInputView.setShifted(mCapsLock || getCursorCapsMode(ic, attr) != 0);
820923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
821923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
8221c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani
8231c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani    private int getCursorCapsMode(InputConnection ic, EditorInfo attr) {
8241c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani        int caps = 0;
8251c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani        EditorInfo ei = getCurrentInputEditorInfo();
8261c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani        if (mAutoCap && ei != null && ei.inputType != EditorInfo.TYPE_NULL) {
8271c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani            caps = ic.getCursorCapsMode(attr.inputType);
8281c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani        }
8291c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani        return caps;
8301c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani    }
8311c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani
832923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private void swapPunctuationAndSpace() {
833923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        final InputConnection ic = getCurrentInputConnection();
834923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (ic == null) return;
835923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        CharSequence lastTwo = ic.getTextBeforeCursor(2, 0);
836923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (lastTwo != null && lastTwo.length() == 2
837923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                && lastTwo.charAt(0) == KEYCODE_SPACE && isSentenceSeparator(lastTwo.charAt(1))) {
838923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            ic.beginBatchEdit();
839923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            ic.deleteSurroundingText(2, 0);
840923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            ic.commitText(lastTwo.charAt(1) + " ", 1);
841923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            ic.endBatchEdit();
842923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            updateShiftKeyState(getCurrentInputEditorInfo());
8439a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa            mJustAddedAutoSpace = true;
844923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
845923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
8461c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani
8474ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa    private void reswapPeriodAndSpace() {
8484ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa        final InputConnection ic = getCurrentInputConnection();
8494ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa        if (ic == null) return;
8504ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa        CharSequence lastThree = ic.getTextBeforeCursor(3, 0);
8514ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa        if (lastThree != null && lastThree.length() == 3
8524ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa                && lastThree.charAt(0) == KEYCODE_PERIOD
8534ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa                && lastThree.charAt(1) == KEYCODE_SPACE
8544ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa                && lastThree.charAt(2) == KEYCODE_PERIOD) {
8554ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa            ic.beginBatchEdit();
8564ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa            ic.deleteSurroundingText(3, 0);
8574ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa            ic.commitText(" ..", 1);
8584ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa            ic.endBatchEdit();
8594ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa            updateShiftKeyState(getCurrentInputEditorInfo());
8604ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa        }
8614ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa    }
8624ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa
863923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private void doubleSpace() {
864923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        //if (!mAutoPunctuate) return;
865923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mCorrectionMode == Suggest.CORRECTION_NONE) return;
866923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        final InputConnection ic = getCurrentInputConnection();
867923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (ic == null) return;
868923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        CharSequence lastThree = ic.getTextBeforeCursor(3, 0);
869923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (lastThree != null && lastThree.length() == 3
870923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                && Character.isLetterOrDigit(lastThree.charAt(0))
871923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                && lastThree.charAt(1) == KEYCODE_SPACE && lastThree.charAt(2) == KEYCODE_SPACE) {
872923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            ic.beginBatchEdit();
873923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            ic.deleteSurroundingText(2, 0);
874923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            ic.commitText(". ", 1);
875923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            ic.endBatchEdit();
876923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            updateShiftKeyState(getCurrentInputEditorInfo());
8779a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa            mJustAddedAutoSpace = true;
878923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
879923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
880a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
88141a519729505a877844f2c57a33509c302dddbceKen Wakasa    private void maybeRemovePreviousPeriod(CharSequence text) {
88241a519729505a877844f2c57a33509c302dddbceKen Wakasa        final InputConnection ic = getCurrentInputConnection();
88341a519729505a877844f2c57a33509c302dddbceKen Wakasa        if (ic == null) return;
88441a519729505a877844f2c57a33509c302dddbceKen Wakasa
88541a519729505a877844f2c57a33509c302dddbceKen Wakasa        // When the text's first character is '.', remove the previous period
88641a519729505a877844f2c57a33509c302dddbceKen Wakasa        // if there is one.
88741a519729505a877844f2c57a33509c302dddbceKen Wakasa        CharSequence lastOne = ic.getTextBeforeCursor(1, 0);
8884ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa        if (lastOne != null && lastOne.length() == 1
8894ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa                && lastOne.charAt(0) == KEYCODE_PERIOD
8904ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa                && text.charAt(0) == KEYCODE_PERIOD) {
89141a519729505a877844f2c57a33509c302dddbceKen Wakasa            ic.deleteSurroundingText(1, 0);
89241a519729505a877844f2c57a33509c302dddbceKen Wakasa        }
89341a519729505a877844f2c57a33509c302dddbceKen Wakasa    }
89441a519729505a877844f2c57a33509c302dddbceKen Wakasa
8959a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa    private void removeTrailingSpace() {
8969a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa        final InputConnection ic = getCurrentInputConnection();
8979a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa        if (ic == null) return;
8989a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa
8999a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa        CharSequence lastOne = ic.getTextBeforeCursor(1, 0);
9009a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa        if (lastOne != null && lastOne.length() == 1
9019a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa                && lastOne.charAt(0) == KEYCODE_SPACE) {
9029a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa            ic.deleteSurroundingText(1, 0);
9039a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa        }
9049a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa    }
9059a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa
906923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public boolean addWordToDictionary(String word) {
907923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mUserDictionary.addWord(word, 128);
908923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        return true;
909923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
910923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
911923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private boolean isAlphabet(int code) {
912923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (Character.isLetter(code)) {
913923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            return true;
914923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        } else {
915923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            return false;
916923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
917923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
918a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
919923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    // Implementation of KeyboardViewListener
920923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
921923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public void onKey(int primaryCode, int[] keyCodes) {
922923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        long when = SystemClock.uptimeMillis();
923a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker        if (primaryCode != Keyboard.KEYCODE_DELETE ||
924923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                when > mLastKeyTime + QUICK_PRESS) {
925923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mDeleteCount = 0;
926923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
927923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mLastKeyTime = when;
928923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        switch (primaryCode) {
929923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            case Keyboard.KEYCODE_DELETE:
930923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                handleBackspace();
931923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mDeleteCount++;
932923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                break;
933923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            case Keyboard.KEYCODE_SHIFT:
934923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                handleShift();
935923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                break;
936923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            case Keyboard.KEYCODE_CANCEL:
937923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                if (mOptionsDialog == null || !mOptionsDialog.isShowing()) {
938923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    handleClose();
939923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                }
940923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                break;
941923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            case LatinKeyboardView.KEYCODE_OPTIONS:
942923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                showOptionsMenu();
943923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                break;
9448eb2e34d5b2def57c9548f88e37e5c9e5a0bea59Amith Yamasani            case LatinKeyboardView.KEYCODE_NEXT_LANGUAGE:
9453f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                toggleLanguage(false, true);
9463f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                break;
9473f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            case LatinKeyboardView.KEYCODE_PREV_LANGUAGE:
9483f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                toggleLanguage(false, false);
94936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani                break;
950923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            case LatinKeyboardView.KEYCODE_SHIFT_LONGPRESS:
951923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                if (mCapsLock) {
952923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    handleShift();
953923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                } else {
954923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    toggleCapsLock();
955923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                }
956923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                break;
957923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            case Keyboard.KEYCODE_MODE_CHANGE:
958923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                changeKeyboardMode();
959923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                break;
960466741d8a78965b8509bf527344f289e50873092Mike LeBeau            case LatinKeyboardView.KEYCODE_VOICE:
961466741d8a78965b8509bf527344f289e50873092Mike LeBeau                if (VOICE_INSTALLED) {
962466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    startListening(false /* was a button press, was not a swipe */);
963466741d8a78965b8509bf527344f289e50873092Mike LeBeau                }
964466741d8a78965b8509bf527344f289e50873092Mike LeBeau                break;
965cf02653097893b06f24551b790b0f7ec288e704dAmith Yamasani            case 9 /*Tab*/:
9668fa317a61a2152347c59dda7eb1b8e2979f6cc1dLeon Scroggins                sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB);
967cf02653097893b06f24551b790b0f7ec288e704dAmith Yamasani                break;
968923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            default:
9699a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa                if (primaryCode != KEYCODE_ENTER) {
9709a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa                    mJustAddedAutoSpace = false;
9719a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa                }
972923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                if (isWordSeparator(primaryCode)) {
973923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    handleSeparator(primaryCode);
974923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                } else {
975923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    handleCharacter(primaryCode, keyCodes);
976923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                }
977923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                // Cancel the just reverted state
978923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mJustRevertedSeparator = null;
979923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
980b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani        if (mKeyboardSwitcher.onKey(primaryCode)) {
981b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani            changeKeyboardMode();
982b19668cfc17ad30afcc3c8c0407d47238ce1a90dAmith Yamasani        }
983923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
984a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
985923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public void onText(CharSequence text) {
9868472bb611e774ea16846dc05973cb7169b7bcaa6Amith Yamasani        if (VOICE_INSTALLED && mVoiceInputHighlighted) {
9878472bb611e774ea16846dc05973cb7169b7bcaa6Amith Yamasani            commitVoiceInput();
9888472bb611e774ea16846dc05973cb7169b7bcaa6Amith Yamasani        }
989923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        InputConnection ic = getCurrentInputConnection();
990923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (ic == null) return;
991923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        ic.beginBatchEdit();
992923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mPredicting) {
993923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            commitTyped(ic);
994923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
99541a519729505a877844f2c57a33509c302dddbceKen Wakasa        maybeRemovePreviousPeriod(text);
996923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        ic.commitText(text, 1);
997923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        ic.endBatchEdit();
998923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        updateShiftKeyState(getCurrentInputEditorInfo());
999923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mJustRevertedSeparator = null;
10009a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa        mJustAddedAutoSpace = false;
1001923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1002923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1003923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private void handleBackspace() {
1004466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (VOICE_INSTALLED && mVoiceInputHighlighted) {
10054f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett            mVoiceInput.incrementTextModificationDeleteCount(
10064f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett                    mVoiceResults.candidates.get(0).toString().length());
1007466741d8a78965b8509bf527344f289e50873092Mike LeBeau            revertVoiceInput();
1008466741d8a78965b8509bf527344f289e50873092Mike LeBeau            return;
1009466741d8a78965b8509bf527344f289e50873092Mike LeBeau        }
1010923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        boolean deleteChar = false;
1011923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        InputConnection ic = getCurrentInputConnection();
1012923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (ic == null) return;
10134f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett
10144f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett        if (mAfterVoiceInput) {
10154f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett            // Don't log delete if the user is pressing delete at
10164f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett            // the beginning of the text box (hence not deleting anything)
10174f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett            if (mVoiceInput.getCursorPos() > 0) {
10184f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett                // If anything was selected before the delete was pressed, increment the
10194f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett                // delete count by the length of the selection
10204f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett                int deleteLen  =  mVoiceInput.getSelectionSpan() > 0 ?
10214f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett                        mVoiceInput.getSelectionSpan() : 1;
10224f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett                mVoiceInput.incrementTextModificationDeleteCount(deleteLen);
10234f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett            }
10244f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett        }
10254f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett
1026923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mPredicting) {
1027923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            final int length = mComposing.length();
1028923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            if (length > 0) {
1029923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mComposing.delete(length - 1, length);
1030923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mWord.deleteLast();
1031923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                ic.setComposingText(mComposing, 1);
1032923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                if (mComposing.length() == 0) {
1033923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    mPredicting = false;
1034923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                }
1035923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                postUpdateSuggestions();
1036923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            } else {
1037923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                ic.deleteSurroundingText(1, 0);
1038923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            }
1039923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        } else {
1040923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            deleteChar = true;
1041923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
10423263841911dc3dbbf4ffe26d2f046e38a1896f72Amith Yamasani        postUpdateShiftKeyState();
1043923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        TextEntryState.backspace();
1044923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (TextEntryState.getState() == TextEntryState.STATE_UNDO_COMMIT) {
1045923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            revertLastWord(deleteChar);
1046923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            return;
1047923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        } else if (deleteChar) {
1048923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
1049923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            if (mDeleteCount > DELETE_ACCELERATE_AT) {
1050923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
1051923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            }
1052923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1053923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mJustRevertedSeparator = null;
1054923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1055923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1056923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private void handleShift() {
105782c68bfbfc9442ebb7d8be842aaf8dedf5ffc76eAmith Yamasani        mHandler.removeMessages(MSG_UPDATE_SHIFT_STATE);
1058923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mKeyboardSwitcher.isAlphabetMode()) {
1059923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            // Alphabet keyboard
1060923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            checkToggleCapsLock();
1061923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mInputView.setShifted(mCapsLock || !mInputView.isShifted());
1062923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        } else {
1063923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mKeyboardSwitcher.toggleShift();
1064923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1065923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1066a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
1067923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private void handleCharacter(int primaryCode, int[] keyCodes) {
1068466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (VOICE_INSTALLED && mVoiceInputHighlighted) {
1069466741d8a78965b8509bf527344f289e50873092Mike LeBeau            commitVoiceInput();
1070466741d8a78965b8509bf527344f289e50873092Mike LeBeau        }
10714f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett
10724f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett        if (mAfterVoiceInput) {
10734f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett            // Assume input length is 1. This assumption fails for smiley face insertions.
10744f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett            mVoiceInput.incrementTextModificationInsertCount(1);
10754f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett        }
10764f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett
1077923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (isAlphabet(primaryCode) && isPredictionOn() && !isCursorTouchingWord()) {
1078923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            if (!mPredicting) {
1079923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mPredicting = true;
1080923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mComposing.setLength(0);
1081923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mWord.reset();
1082923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            }
1083923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1084923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mInputView.isShifted()) {
108556f96fe05b2b01c488ce569eb2eefc13ee917fd3Amith Yamasani            // TODO: This doesn't work with ß, need to fix it in the next release.
1086eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani            if (keyCodes == null || keyCodes[0] < Character.MIN_CODE_POINT
1087eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani                    || keyCodes[0] > Character.MAX_CODE_POINT) {
1088eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani                return;
1089eef539c3f2b60af74a3ce05ac68288e7f86709aeAmith Yamasani            }
109056f96fe05b2b01c488ce569eb2eefc13ee917fd3Amith Yamasani            primaryCode = new String(keyCodes, 0, 1).toUpperCase().charAt(0);
1091923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1092923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mPredicting) {
1093923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            if (mInputView.isShifted() && mComposing.length() == 0) {
1094923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mWord.setCapitalized(true);
1095923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            }
1096923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mComposing.append((char) primaryCode);
1097923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mWord.add(primaryCode, keyCodes);
1098923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            InputConnection ic = getCurrentInputConnection();
1099923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            if (ic != null) {
11001c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani                // If it's the first letter, make note of auto-caps state
11011c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani                if (mWord.size() == 1) {
11021c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani                    mWord.setAutoCapitalized(
11031c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani                            getCursorCapsMode(ic, getCurrentInputEditorInfo()) != 0);
11041c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani                }
1105923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                ic.setComposingText(mComposing, 1);
1106923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            }
1107923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            postUpdateSuggestions();
1108923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        } else {
1109923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            sendKeyChar((char)primaryCode);
1110923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
11118850bdc7e4c1da7049231bc1e21f17213562f9b6Amith Yamasani        updateShiftKeyState(getCurrentInputEditorInfo());
1112923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        measureCps();
1113923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        TextEntryState.typedCharacter((char) primaryCode, isWordSeparator(primaryCode));
1114923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1115923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1116923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private void handleSeparator(int primaryCode) {
1117466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (VOICE_INSTALLED && mVoiceInputHighlighted) {
1118466741d8a78965b8509bf527344f289e50873092Mike LeBeau            commitVoiceInput();
1119466741d8a78965b8509bf527344f289e50873092Mike LeBeau        }
11204f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett
11214f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett        if (mAfterVoiceInput){
11224f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett            // Assume input length is 1. This assumption fails for smiley face insertions.
11234f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett            mVoiceInput.incrementTextModificationInsertPunctuationCount(1);
11244f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett        }
11254f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett
1126923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        boolean pickedDefault = false;
1127923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        // Handle separator
1128923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        InputConnection ic = getCurrentInputConnection();
1129923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (ic != null) {
1130923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            ic.beginBatchEdit();
1131923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1132923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mPredicting) {
1133923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            // In certain languages where single quote is a separator, it's better
1134a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker            // not to auto correct, but accept the typed word. For instance,
1135923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            // in Italian dov' should not be expanded to dove' because the elision
1136923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            // requires the last vowel to be removed.
1137a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker            if (mAutoCorrectOn && primaryCode != '\'' &&
1138a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker                    (mJustRevertedSeparator == null
1139a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker                            || mJustRevertedSeparator.length() == 0
1140923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                            || mJustRevertedSeparator.charAt(0) != primaryCode)) {
1141923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                pickDefaultSuggestion();
1142923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                pickedDefault = true;
11439a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa                // Picked the suggestion by the space key.  We consider this
11449a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa                // as "added an auto space".
11459a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa                if (primaryCode == KEYCODE_SPACE) {
11469a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa                    mJustAddedAutoSpace = true;
11479a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa                }
1148923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            } else {
1149923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                commitTyped(ic);
1150923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            }
1151923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
11529a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa        if (mJustAddedAutoSpace && primaryCode == KEYCODE_ENTER) {
11539a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa            removeTrailingSpace();
11549a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa            mJustAddedAutoSpace = false;
11559a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa        }
1156923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        sendKeyChar((char)primaryCode);
11574ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa
11584ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa        // Handle the case of ". ." -> " .." with auto-space if necessary
11594ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa        // before changing the TextEntryState.
11604ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa        if (TextEntryState.getState() == TextEntryState.STATE_PUNCTUATION_AFTER_ACCEPTED
11614ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa                && primaryCode == KEYCODE_PERIOD) {
11624ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa            reswapPeriodAndSpace();
11634ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa        }
11644ca6d9dc09cf7635c9283e42f155957021b9f9acKen Wakasa
1165923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        TextEntryState.typedCharacter((char) primaryCode, true);
1166a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker        if (TextEntryState.getState() == TextEntryState.STATE_PUNCTUATION_AFTER_ACCEPTED
1167923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                && primaryCode != KEYCODE_ENTER) {
1168923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            swapPunctuationAndSpace();
11699a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa        } else if (isPredictionOn() && primaryCode == KEYCODE_SPACE) {
1170923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        //else if (TextEntryState.STATE_SPACE_AFTER_ACCEPTED) {
1171923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            doubleSpace();
1172923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1173923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (pickedDefault && mBestWord != null) {
1174923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            TextEntryState.acceptedDefault(mWord.getTypedWord(), mBestWord);
1175923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1176923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        updateShiftKeyState(getCurrentInputEditorInfo());
1177923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (ic != null) {
1178923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            ic.endBatchEdit();
1179923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1180923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1181466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1182923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private void handleClose() {
1183923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        commitTyped(getCurrentInputConnection());
1184466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (VOICE_INSTALLED & mRecognizing) {
1185466741d8a78965b8509bf527344f289e50873092Mike LeBeau            mVoiceInput.cancel();
1186466741d8a78965b8509bf527344f289e50873092Mike LeBeau        }
1187923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        requestHideSelf(0);
1188923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mInputView.closing();
1189923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        TextEntryState.endSession();
1190923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1191923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1192923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private void checkToggleCapsLock() {
1193923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mInputView.getKeyboard().isShifted()) {
1194923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            toggleCapsLock();
1195923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1196923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1197a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
1198923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private void toggleCapsLock() {
1199923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mCapsLock = !mCapsLock;
1200923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mKeyboardSwitcher.isAlphabetMode()) {
1201923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            ((LatinKeyboard) mInputView.getKeyboard()).setShiftLocked(mCapsLock);
1202923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1203923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1204923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1205923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private void postUpdateSuggestions() {
1206923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mHandler.removeMessages(MSG_UPDATE_SUGGESTIONS);
1207923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_UPDATE_SUGGESTIONS), 100);
1208923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1209a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
1210923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private boolean isPredictionOn() {
1211923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        boolean predictionOn = mPredictionOn;
1212923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        return predictionOn;
1213923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1214a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
1215923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private boolean isCandidateStripVisible() {
12166e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani        return isPredictionOn() && mShowSuggestions;
1217923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1218923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1219466741d8a78965b8509bf527344f289e50873092Mike LeBeau    public void onCancelVoice() {
1220466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (mRecognizing) {
1221466741d8a78965b8509bf527344f289e50873092Mike LeBeau            switchToKeyboardView();
1222466741d8a78965b8509bf527344f289e50873092Mike LeBeau        }
1223466741d8a78965b8509bf527344f289e50873092Mike LeBeau    }
1224466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1225466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private void switchToKeyboardView() {
1226466741d8a78965b8509bf527344f289e50873092Mike LeBeau      mHandler.post(new Runnable() {
1227466741d8a78965b8509bf527344f289e50873092Mike LeBeau          public void run() {
1228466741d8a78965b8509bf527344f289e50873092Mike LeBeau              mRecognizing = false;
1229466741d8a78965b8509bf527344f289e50873092Mike LeBeau              if (mInputView != null) {
1230466741d8a78965b8509bf527344f289e50873092Mike LeBeau                setInputView(mInputView);
1231466741d8a78965b8509bf527344f289e50873092Mike LeBeau              }
1232466741d8a78965b8509bf527344f289e50873092Mike LeBeau              updateInputViewShown();
1233466741d8a78965b8509bf527344f289e50873092Mike LeBeau          }});
1234466741d8a78965b8509bf527344f289e50873092Mike LeBeau    }
1235466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1236466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private void switchToRecognitionStatusView() {
123781c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani        final boolean configChanged = mConfigurationChanging;
123881c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani        mHandler.post(new Runnable() {
123981c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani            public void run() {
124081c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani                mRecognizing = true;
124181c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani                View v = mVoiceInput.getView();
124281c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani                ViewParent p = v.getParent();
124381c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani                if (p != null && p instanceof ViewGroup) {
124481c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani                    ((ViewGroup)v.getParent()).removeView(v);
124581c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani                }
124681c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani                setInputView(v);
124781c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani                updateInputViewShown();
124881c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani                if (configChanged) {
124981c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani                    mVoiceInput.onConfigurationChanged();
125081c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani                }
125181c52293f84ce475ac6b1661f4a4b92703405247Amith Yamasani        }});
1252466741d8a78965b8509bf527344f289e50873092Mike LeBeau    }
1253466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1254466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private void startListening(boolean swipe) {
1255466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (!mHasUsedVoiceInput ||
1256466741d8a78965b8509bf527344f289e50873092Mike LeBeau                (!mLocaleSupportedForVoiceInput && !mHasUsedVoiceInputUnsupportedLocale)) {
1257466741d8a78965b8509bf527344f289e50873092Mike LeBeau            // Calls reallyStartListening if user clicks OK, does nothing if user clicks Cancel.
1258466741d8a78965b8509bf527344f289e50873092Mike LeBeau            showVoiceWarningDialog(swipe);
1259466741d8a78965b8509bf527344f289e50873092Mike LeBeau        } else {
1260466741d8a78965b8509bf527344f289e50873092Mike LeBeau            reallyStartListening(swipe);
1261466741d8a78965b8509bf527344f289e50873092Mike LeBeau        }
1262466741d8a78965b8509bf527344f289e50873092Mike LeBeau    }
1263a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
1264466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private void reallyStartListening(boolean swipe) {
1265466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (!mHasUsedVoiceInput) {
1266466741d8a78965b8509bf527344f289e50873092Mike LeBeau            // The user has started a voice input, so remember that in the
1267466741d8a78965b8509bf527344f289e50873092Mike LeBeau            // future (so we don't show the warning dialog after the first run).
1268466741d8a78965b8509bf527344f289e50873092Mike LeBeau            SharedPreferences.Editor editor =
1269466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    PreferenceManager.getDefaultSharedPreferences(this).edit();
1270466741d8a78965b8509bf527344f289e50873092Mike LeBeau            editor.putBoolean(PREF_HAS_USED_VOICE_INPUT, true);
1271466741d8a78965b8509bf527344f289e50873092Mike LeBeau            editor.commit();
1272466741d8a78965b8509bf527344f289e50873092Mike LeBeau            mHasUsedVoiceInput = true;
1273466741d8a78965b8509bf527344f289e50873092Mike LeBeau        }
1274a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
1275466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (!mLocaleSupportedForVoiceInput && !mHasUsedVoiceInputUnsupportedLocale) {
1276466741d8a78965b8509bf527344f289e50873092Mike LeBeau            // The user has started a voice input from an unsupported locale, so remember that
1277466741d8a78965b8509bf527344f289e50873092Mike LeBeau            // in the future (so we don't show the warning dialog the next time they do this).
1278466741d8a78965b8509bf527344f289e50873092Mike LeBeau            SharedPreferences.Editor editor =
1279466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    PreferenceManager.getDefaultSharedPreferences(this).edit();
1280466741d8a78965b8509bf527344f289e50873092Mike LeBeau            editor.putBoolean(PREF_HAS_USED_VOICE_INPUT_UNSUPPORTED_LOCALE, true);
1281466741d8a78965b8509bf527344f289e50873092Mike LeBeau            editor.commit();
1282466741d8a78965b8509bf527344f289e50873092Mike LeBeau            mHasUsedVoiceInputUnsupportedLocale = true;
1283466741d8a78965b8509bf527344f289e50873092Mike LeBeau        }
1284a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
1285466741d8a78965b8509bf527344f289e50873092Mike LeBeau        // Clear N-best suggestions
1286466741d8a78965b8509bf527344f289e50873092Mike LeBeau        setSuggestions(null, false, false, true);
1287466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1288466741d8a78965b8509bf527344f289e50873092Mike LeBeau        FieldContext context = new FieldContext(
12892e3aa86cf389236c085ab4758239b01e80c3b2dcMike LeBeau            getCurrentInputConnection(),
12902e3aa86cf389236c085ab4758239b01e80c3b2dcMike LeBeau            getCurrentInputEditorInfo(),
12912e3aa86cf389236c085ab4758239b01e80c3b2dcMike LeBeau            mLanguageSwitcher.getInputLanguage(),
12922e3aa86cf389236c085ab4758239b01e80c3b2dcMike LeBeau            mLanguageSwitcher.getEnabledLanguages());
1293466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mVoiceInput.startListening(context, swipe);
1294466741d8a78965b8509bf527344f289e50873092Mike LeBeau        switchToRecognitionStatusView();
1295466741d8a78965b8509bf527344f289e50873092Mike LeBeau    }
1296a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
1297466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private void showVoiceWarningDialog(final boolean swipe) {
1298466741d8a78965b8509bf527344f289e50873092Mike LeBeau        AlertDialog.Builder builder = new AlertDialog.Builder(this);
1299466741d8a78965b8509bf527344f289e50873092Mike LeBeau        builder.setCancelable(true);
1300466741d8a78965b8509bf527344f289e50873092Mike LeBeau        builder.setIcon(R.drawable.ic_mic_dialog);
1301466741d8a78965b8509bf527344f289e50873092Mike LeBeau        builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
1302466741d8a78965b8509bf527344f289e50873092Mike LeBeau            public void onClick(DialogInterface dialog, int whichButton) {
1303466741d8a78965b8509bf527344f289e50873092Mike LeBeau                mVoiceInput.logKeyboardWarningDialogOk();
1304466741d8a78965b8509bf527344f289e50873092Mike LeBeau                reallyStartListening(swipe);
1305466741d8a78965b8509bf527344f289e50873092Mike LeBeau            }
1306466741d8a78965b8509bf527344f289e50873092Mike LeBeau        });
1307466741d8a78965b8509bf527344f289e50873092Mike LeBeau        builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
1308466741d8a78965b8509bf527344f289e50873092Mike LeBeau            public void onClick(DialogInterface dialog, int whichButton) {
1309466741d8a78965b8509bf527344f289e50873092Mike LeBeau                mVoiceInput.logKeyboardWarningDialogCancel();
1310466741d8a78965b8509bf527344f289e50873092Mike LeBeau            }
1311466741d8a78965b8509bf527344f289e50873092Mike LeBeau        });
1312a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
1313466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (mLocaleSupportedForVoiceInput) {
1314466741d8a78965b8509bf527344f289e50873092Mike LeBeau            String message = getString(R.string.voice_warning_may_not_understand) + "\n\n" +
1315466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    getString(R.string.voice_warning_how_to_turn_off);
1316466741d8a78965b8509bf527344f289e50873092Mike LeBeau            builder.setMessage(message);
1317466741d8a78965b8509bf527344f289e50873092Mike LeBeau        } else {
1318466741d8a78965b8509bf527344f289e50873092Mike LeBeau            String message = getString(R.string.voice_warning_locale_not_supported) + "\n\n" +
1319466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    getString(R.string.voice_warning_may_not_understand) + "\n\n" +
1320466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    getString(R.string.voice_warning_how_to_turn_off);
1321466741d8a78965b8509bf527344f289e50873092Mike LeBeau            builder.setMessage(message);
1322466741d8a78965b8509bf527344f289e50873092Mike LeBeau        }
1323a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
1324466741d8a78965b8509bf527344f289e50873092Mike LeBeau        builder.setTitle(R.string.voice_warning_title);
1325466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mVoiceWarningDialog = builder.create();
1326a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
1327466741d8a78965b8509bf527344f289e50873092Mike LeBeau        Window window = mVoiceWarningDialog.getWindow();
1328466741d8a78965b8509bf527344f289e50873092Mike LeBeau        WindowManager.LayoutParams lp = window.getAttributes();
1329466741d8a78965b8509bf527344f289e50873092Mike LeBeau        lp.token = mInputView.getWindowToken();
1330466741d8a78965b8509bf527344f289e50873092Mike LeBeau        lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
1331466741d8a78965b8509bf527344f289e50873092Mike LeBeau        window.setAttributes(lp);
1332466741d8a78965b8509bf527344f289e50873092Mike LeBeau        window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
1333466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mVoiceInput.logKeyboardWarningDialogShown();
1334466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mVoiceWarningDialog.show();
1335466741d8a78965b8509bf527344f289e50873092Mike LeBeau    }
1336466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1337466741d8a78965b8509bf527344f289e50873092Mike LeBeau    public void onVoiceResults(List<String> candidates,
1338466741d8a78965b8509bf527344f289e50873092Mike LeBeau            Map<String, List<CharSequence>> alternatives) {
1339466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (!mRecognizing) {
1340466741d8a78965b8509bf527344f289e50873092Mike LeBeau            return;
1341466741d8a78965b8509bf527344f289e50873092Mike LeBeau        }
1342466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mVoiceResults.candidates = candidates;
1343466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mVoiceResults.alternatives = alternatives;
1344466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mHandler.sendMessage(mHandler.obtainMessage(MSG_VOICE_RESULTS));
1345466741d8a78965b8509bf527344f289e50873092Mike LeBeau    }
1346466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1347466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private void handleVoiceResults() {
1348466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mAfterVoiceInput = true;
1349466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mImmediatelyAfterVoiceInput = true;
1350466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1351466741d8a78965b8509bf527344f289e50873092Mike LeBeau        InputConnection ic = getCurrentInputConnection();
1352466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (!isFullscreenMode()) {
1353466741d8a78965b8509bf527344f289e50873092Mike LeBeau            // Start listening for updates to the text from typing, etc.
1354466741d8a78965b8509bf527344f289e50873092Mike LeBeau            if (ic != null) {
1355466741d8a78965b8509bf527344f289e50873092Mike LeBeau                ExtractedTextRequest req = new ExtractedTextRequest();
1356466741d8a78965b8509bf527344f289e50873092Mike LeBeau                ic.getExtractedText(req, InputConnection.GET_EXTRACTED_TEXT_MONITOR);
1357466741d8a78965b8509bf527344f289e50873092Mike LeBeau            }
1358466741d8a78965b8509bf527344f289e50873092Mike LeBeau        }
1359466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1360466741d8a78965b8509bf527344f289e50873092Mike LeBeau        vibrate();
1361466741d8a78965b8509bf527344f289e50873092Mike LeBeau        switchToKeyboardView();
1362466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1363466741d8a78965b8509bf527344f289e50873092Mike LeBeau        final List<CharSequence> nBest = new ArrayList<CharSequence>();
1364466741d8a78965b8509bf527344f289e50873092Mike LeBeau        boolean capitalizeFirstWord = preferCapitalization()
1365466741d8a78965b8509bf527344f289e50873092Mike LeBeau                || (mKeyboardSwitcher.isAlphabetMode() && mInputView.isShifted());
1366466741d8a78965b8509bf527344f289e50873092Mike LeBeau        for (String c : mVoiceResults.candidates) {
1367466741d8a78965b8509bf527344f289e50873092Mike LeBeau            if (capitalizeFirstWord) {
1368466741d8a78965b8509bf527344f289e50873092Mike LeBeau                c = Character.toUpperCase(c.charAt(0)) + c.substring(1, c.length());
1369466741d8a78965b8509bf527344f289e50873092Mike LeBeau            }
1370466741d8a78965b8509bf527344f289e50873092Mike LeBeau            nBest.add(c);
1371466741d8a78965b8509bf527344f289e50873092Mike LeBeau        }
1372466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1373466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (nBest.size() == 0) {
1374466741d8a78965b8509bf527344f289e50873092Mike LeBeau            return;
1375466741d8a78965b8509bf527344f289e50873092Mike LeBeau        }
1376466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1377466741d8a78965b8509bf527344f289e50873092Mike LeBeau        String bestResult = nBest.get(0).toString();
1378466741d8a78965b8509bf527344f289e50873092Mike LeBeau
13794f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett        mVoiceInput.logVoiceInputDelivered(bestResult.length());
1380466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1381466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mHints.registerVoiceResult(bestResult);
1382466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1383466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (ic != null) ic.beginBatchEdit(); // To avoid extra updates on committing older text
1384466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1385466741d8a78965b8509bf527344f289e50873092Mike LeBeau        commitTyped(ic);
1386466741d8a78965b8509bf527344f289e50873092Mike LeBeau        EditingUtil.appendText(ic, bestResult);
1387466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1388466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (ic != null) ic.endBatchEdit();
1389466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1390466741d8a78965b8509bf527344f289e50873092Mike LeBeau        // Show N-Best alternates, if there is more than one choice.
1391466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (nBest.size() > 1) {
1392466741d8a78965b8509bf527344f289e50873092Mike LeBeau            mImmediatelyAfterVoiceSuggestions = true;
1393466741d8a78965b8509bf527344f289e50873092Mike LeBeau            mShowingVoiceSuggestions = true;
1394466741d8a78965b8509bf527344f289e50873092Mike LeBeau            setSuggestions(nBest.subList(1, nBest.size()), false, true, true);
1395466741d8a78965b8509bf527344f289e50873092Mike LeBeau            setCandidatesViewShown(true);
1396466741d8a78965b8509bf527344f289e50873092Mike LeBeau        }
1397466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mVoiceInputHighlighted = true;
1398466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mWordToSuggestions.putAll(mVoiceResults.alternatives);
1399466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1400466741d8a78965b8509bf527344f289e50873092Mike LeBeau    }
1401466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1402466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private void setSuggestions(
1403466741d8a78965b8509bf527344f289e50873092Mike LeBeau            List<CharSequence> suggestions,
1404466741d8a78965b8509bf527344f289e50873092Mike LeBeau            boolean completions,
1405466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1406466741d8a78965b8509bf527344f289e50873092Mike LeBeau            boolean typedWordValid,
1407466741d8a78965b8509bf527344f289e50873092Mike LeBeau            boolean haveMinimalSuggestion) {
1408466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1409466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (mIsShowingHint) {
1410466741d8a78965b8509bf527344f289e50873092Mike LeBeau             setCandidatesView(mCandidateViewContainer);
1411466741d8a78965b8509bf527344f289e50873092Mike LeBeau             mIsShowingHint = false;
1412466741d8a78965b8509bf527344f289e50873092Mike LeBeau        }
1413466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1414466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (mCandidateView != null) {
1415466741d8a78965b8509bf527344f289e50873092Mike LeBeau            mCandidateView.setSuggestions(
1416466741d8a78965b8509bf527344f289e50873092Mike LeBeau                    suggestions, completions, typedWordValid, haveMinimalSuggestion);
1417466741d8a78965b8509bf527344f289e50873092Mike LeBeau        }
1418466741d8a78965b8509bf527344f289e50873092Mike LeBeau    }
1419466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1420923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private void updateSuggestions() {
1421466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mSuggestionShouldReplaceCurrentWord = false;
1422466741d8a78965b8509bf527344f289e50873092Mike LeBeau
14231b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani        ((LatinKeyboard) mInputView.getKeyboard()).setPreferredLetters(null);
14241b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani
1425923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        // Check if we have a suggestion engine attached.
1426466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if ((mSuggest == null || !isPredictionOn()) && !mVoiceInputHighlighted) {
1427923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            return;
1428923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1429466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1430923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (!mPredicting) {
14316a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani            setNextSuggestions();
1432923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            return;
1433923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1434923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1435923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        List<CharSequence> stringList = mSuggest.getSuggestions(mInputView, mWord, false);
14361b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani        int[] nextLettersFrequencies = mSuggest.getNextLettersFrequencies();
14371b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani
14381b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani        ((LatinKeyboard) mInputView.getKeyboard()).setPreferredLetters(nextLettersFrequencies);
14391b62ff1a3d61cd44ab88acdfcbdf0fc70a7e1b10Amith Yamasani
1440923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        boolean correctionAvailable = mSuggest.hasMinimalCorrection();
1441923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        //|| mCorrectionMode == mSuggest.CORRECTION_FULL;
1442923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        CharSequence typedWord = mWord.getTypedWord();
1443923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        // If we're in basic correct
1444f590a497393eb77875017010e9a36cf33b095e3cAmith Yamasani        boolean typedWordValid = mSuggest.isValidWord(typedWord) ||
1445f590a497393eb77875017010e9a36cf33b095e3cAmith Yamasani                (preferCapitalization() && mSuggest.isValidWord(typedWord.toString().toLowerCase()));
1446923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mCorrectionMode == Suggest.CORRECTION_FULL) {
1447923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            correctionAvailable |= typedWordValid;
1448923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
14494a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani        // Don't auto-correct words with multiple capital letter
14504a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani        correctionAvailable &= !mWord.isMostlyCaps();
14514a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani
1452466741d8a78965b8509bf527344f289e50873092Mike LeBeau        setSuggestions(stringList, false, typedWordValid, correctionAvailable);
1453923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (stringList.size() > 0) {
1454923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            if (correctionAvailable && !typedWordValid && stringList.size() > 1) {
1455923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mBestWord = stringList.get(1);
1456923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            } else {
1457923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mBestWord = typedWord;
1458923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            }
1459923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        } else {
1460923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mBestWord = null;
1461923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1462923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        setCandidatesViewShown(isCandidateStripVisible() || mCompletionOn);
1463923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1464923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1465923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private void pickDefaultSuggestion() {
1466923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        // Complete any pending candidate query first
1467923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mHandler.hasMessages(MSG_UPDATE_SUGGESTIONS)) {
1468923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mHandler.removeMessages(MSG_UPDATE_SUGGESTIONS);
1469923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            updateSuggestions();
1470923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
14716780b898ec2647a21319601a03ae1c393c0e1b29Amith Yamasani        if (mBestWord != null && mBestWord.length() > 0) {
1472923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            TextEntryState.acceptedDefault(mWord.getTypedWord(), mBestWord);
1473923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mJustAccepted = true;
1474923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            pickSuggestion(mBestWord);
14759468335a06d2b0e3ef15f4f57f8c1b0857b34ebeAmith Yamasani            // Add the word to the auto dictionary if it's not a known word
14769468335a06d2b0e3ef15f4f57f8c1b0857b34ebeAmith Yamasani            checkAddToDictionary(mBestWord, AutoDictionary.FREQUENCY_FOR_TYPED);
1477923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1478923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1479923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1480923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public void pickSuggestionManually(int index, CharSequence suggestion) {
1481466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (mAfterVoiceInput && mShowingVoiceSuggestions) mVoiceInput.logNBestChoose(index);
1482466741d8a78965b8509bf527344f289e50873092Mike LeBeau
14834f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett        if (mAfterVoiceInput && !mShowingVoiceSuggestions) {
14844f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett            mVoiceInput.flushAllTextModificationCounters();
14854f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett            // send this intent AFTER logging any prior aggregated edits.
14864f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett            mVoiceInput.logTextModifiedByChooseSuggestion(suggestion.length());
14874f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett        }
14884f1f2201bdd0e63a19e686caa3d17b16eb134f5eMaryam Garrett
14899a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa        InputConnection ic = getCurrentInputConnection();
14909a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa        if (ic != null) {
14919a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa            ic.beginBatchEdit();
14929a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa        }
1493923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mCompletionOn && mCompletions != null && index >= 0
1494923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                && index < mCompletions.length) {
1495923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            CompletionInfo ci = mCompletions[index];
1496923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            if (ic != null) {
1497923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                ic.commitCompletion(ci);
1498923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            }
1499923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mCommittedLength = suggestion.length();
1500923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            if (mCandidateView != null) {
1501923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mCandidateView.clear();
1502923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            }
1503923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            updateShiftKeyState(getCurrentInputEditorInfo());
15049a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa            if (ic != null) {
15059a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa                ic.endBatchEdit();
15069a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa            }
1507923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            return;
1508923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
15096a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani
15106a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani        // If this is a punctuation, apply it through the normal key press
15116a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani        if (suggestion.length() == 1 && isWordSeparator(suggestion.charAt(0))) {
15126a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani            onKey(suggestion.charAt(0), null);
15139a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa            if (ic != null) {
15149a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa                ic.endBatchEdit();
15159a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa            }
15166a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani            return;
15176a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani        }
15189a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa        mJustAccepted = true;
1519923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        pickSuggestion(suggestion);
15209468335a06d2b0e3ef15f4f57f8c1b0857b34ebeAmith Yamasani        // Add the word to the auto dictionary if it's not a known word
15219468335a06d2b0e3ef15f4f57f8c1b0857b34ebeAmith Yamasani        checkAddToDictionary(suggestion, AutoDictionary.FREQUENCY_FOR_PICKED);
1522923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        TextEntryState.acceptedSuggestion(mComposing.toString(), suggestion);
1523923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        // Follow it with a space
1524923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mAutoSpace) {
1525923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            sendSpace();
15269a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa            mJustAddedAutoSpace = true;
1527923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1528923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        // Fool the state watcher so that a subsequent backspace will not do a revert
1529923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        TextEntryState.typedCharacter((char) KEYCODE_SPACE, true);
153032e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani        if (index == 0 && mCorrectionMode > 0 && !mSuggest.isValidWord(suggestion)) {
153166a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani            mCandidateView.showAddToDictionaryHint(suggestion);
153266a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani        }
15339a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa        if (ic != null) {
15349a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa            ic.endBatchEdit();
15359a503e07d594ddf3cd0c31609c5311440b975906Ken Wakasa        }
1536923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1537a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
1538923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private void pickSuggestion(CharSequence suggestion) {
1539923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mCapsLock) {
1540923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            suggestion = suggestion.toString().toUpperCase();
1541a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker        } else if (preferCapitalization()
1542923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                || (mKeyboardSwitcher.isAlphabetMode() && mInputView.isShifted())) {
154356f96fe05b2b01c488ce569eb2eefc13ee917fd3Amith Yamasani            suggestion = suggestion.toString().toUpperCase().charAt(0)
1544923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    + suggestion.subSequence(1, suggestion.length()).toString();
1545923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1546923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        InputConnection ic = getCurrentInputConnection();
1547923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (ic != null) {
1548466741d8a78965b8509bf527344f289e50873092Mike LeBeau            if (mSuggestionShouldReplaceCurrentWord) {
1549466741d8a78965b8509bf527344f289e50873092Mike LeBeau                EditingUtil.deleteWordAtCursor(ic, getWordSeparators());
1550466741d8a78965b8509bf527344f289e50873092Mike LeBeau            }
1551466741d8a78965b8509bf527344f289e50873092Mike LeBeau            if (!VoiceInput.DELETE_SYMBOL.equals(suggestion)) {
1552466741d8a78965b8509bf527344f289e50873092Mike LeBeau                ic.commitText(suggestion, 1);
1553466741d8a78965b8509bf527344f289e50873092Mike LeBeau            }
1554923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1555923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mPredicting = false;
1556923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mCommittedLength = suggestion.length();
15579468335a06d2b0e3ef15f4f57f8c1b0857b34ebeAmith Yamasani        ((LatinKeyboard) mInputView.getKeyboard()).setPreferredLetters(null);
15586a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani        setNextSuggestions();
1559923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        updateShiftKeyState(getCurrentInputEditorInfo());
1560923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1561923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
15626a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani    private void setNextSuggestions() {
15636a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani        setSuggestions(mSuggestPuncList, false, false, false);
15646a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani    }
15656a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani
156632e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani    private void checkAddToDictionary(CharSequence suggestion, int frequencyDelta) {
156732e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani        if (mAutoDictionary.isValidWord(suggestion)
156832e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani                || !mSuggest.isValidWord(suggestion.toString().toLowerCase())) {
156932e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani            mAutoDictionary.addWord(suggestion.toString(), frequencyDelta);
157032e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani        }
157132e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani    }
157232e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani
1573923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private boolean isCursorTouchingWord() {
1574923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        InputConnection ic = getCurrentInputConnection();
1575923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (ic == null) return false;
1576923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        CharSequence toLeft = ic.getTextBeforeCursor(1, 0);
1577923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        CharSequence toRight = ic.getTextAfterCursor(1, 0);
1578923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (!TextUtils.isEmpty(toLeft)
1579923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                && !isWordSeparator(toLeft.charAt(0))) {
1580923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            return true;
1581923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1582a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker        if (!TextUtils.isEmpty(toRight)
1583923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                && !isWordSeparator(toRight.charAt(0))) {
1584923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            return true;
1585923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1586923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        return false;
1587923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1588a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
1589923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public void revertLastWord(boolean deleteChar) {
1590923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        final int length = mComposing.length();
1591923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (!mPredicting && length > 0) {
1592923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            final InputConnection ic = getCurrentInputConnection();
1593923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mPredicting = true;
1594923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            ic.beginBatchEdit();
1595923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mJustRevertedSeparator = ic.getTextBeforeCursor(1, 0);
1596923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            if (deleteChar) ic.deleteSurroundingText(1, 0);
1597923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            int toDelete = mCommittedLength;
1598923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            CharSequence toTheLeft = ic.getTextBeforeCursor(mCommittedLength, 0);
1599a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker            if (toTheLeft != null && toTheLeft.length() > 0
1600923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    && isWordSeparator(toTheLeft.charAt(0))) {
1601923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                toDelete--;
1602923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            }
1603923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            ic.deleteSurroundingText(toDelete, 0);
1604923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            ic.setComposingText(mComposing, 1);
1605923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            TextEntryState.backspace();
1606923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            ic.endBatchEdit();
1607923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            postUpdateSuggestions();
1608923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        } else {
1609923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
1610923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mJustRevertedSeparator = null;
1611923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1612923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1613923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1614923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    protected String getWordSeparators() {
1615923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        return mWordSeparators;
1616923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1617a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
1618923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public boolean isWordSeparator(int code) {
1619923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        String separators = getWordSeparators();
1620923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        return separators.contains(String.valueOf((char)code));
1621923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1622923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1623923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public boolean isSentenceSeparator(int code) {
1624923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        return mSentenceSeparators.contains(String.valueOf((char)code));
1625923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1626923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1627923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private void sendSpace() {
1628923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        sendKeyChar((char)KEYCODE_SPACE);
1629923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        updateShiftKeyState(getCurrentInputEditorInfo());
1630923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        //onKey(KEY_SPACE[0], KEY_SPACE);
1631923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1632923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1633923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public boolean preferCapitalization() {
1634923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        return mWord.isCapitalized();
1635923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1636923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1637923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public void swipeRight() {
1638466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (userHasNotTypedRecently() && VOICE_INSTALLED && mEnableVoice &&
1639466741d8a78965b8509bf527344f289e50873092Mike LeBeau                fieldCanDoVoice(makeFieldContext())) {
1640466741d8a78965b8509bf527344f289e50873092Mike LeBeau            startListening(true /* was a swipe */);
1641466741d8a78965b8509bf527344f289e50873092Mike LeBeau        }
1642466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1643923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (LatinKeyboardView.DEBUG_AUTO_PLAY) {
1644923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            ClipboardManager cm = ((ClipboardManager)getSystemService(CLIPBOARD_SERVICE));
1645923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            CharSequence text = cm.getText();
1646923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            if (!TextUtils.isEmpty(text)) {
1647923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                mInputView.startPlaying(text.toString());
1648923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            }
1649923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1650923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
165136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani
16523f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani    private void toggleLanguage(boolean reset, boolean next) {
16533f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        if (reset) {
16543f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            mLanguageSwitcher.reset();
16553f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        } else {
16563f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            if (next) {
16573f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                mLanguageSwitcher.next();
16583f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            } else {
16593f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani                mLanguageSwitcher.prev();
16603f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            }
16613f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        }
166236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        int currentKeyboardMode = mKeyboardSwitcher.getKeyboardMode();
166336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        reloadKeyboards();
166436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        mKeyboardSwitcher.makeKeyboards(true);
1665b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani        mKeyboardSwitcher.setKeyboardMode(currentKeyboardMode, 0,
1666b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani                mEnableVoiceButton && mEnableVoice);
16673f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        initSuggest(mLanguageSwitcher.getInputLanguage());
16683f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        mLanguageSwitcher.persist();
166936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        updateShiftKeyState(getCurrentInputEditorInfo());
167036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani    }
167136fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani
167236fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
167336fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani            String key) {
167436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        if (PREF_SELECTED_LANGUAGES.equals(key)) {
16753f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani            mLanguageSwitcher.loadLocales(sharedPreferences);
167636fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani            mRefreshKeyboardRequired = true;
167736fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        }
167836fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani    }
167936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani
1680923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public void swipeLeft() {
1681923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1682923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1683923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public void swipeDown() {
16845d11ccc27d9e06a174b5f027109e29b34eea751eAmith Yamasani        handleClose();
1685923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1686923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1687923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public void swipeUp() {
1688923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        //launchSettings();
1689923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1690923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1691923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public void onPress(int primaryCode) {
1692923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        vibrate();
1693923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        playKeyClick(primaryCode);
1694923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1695923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1696923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    public void onRelease(int primaryCode) {
16973f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        // Reset any drag flags in the keyboard
16983f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        ((LatinKeyboard) mInputView.getKeyboard()).keyReleased();
1699923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        //vibrate();
1700923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1701a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
1702466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private FieldContext makeFieldContext() {
17032e3aa86cf389236c085ab4758239b01e80c3b2dcMike LeBeau        return new FieldContext(
17042e3aa86cf389236c085ab4758239b01e80c3b2dcMike LeBeau                getCurrentInputConnection(),
17052e3aa86cf389236c085ab4758239b01e80c3b2dcMike LeBeau                getCurrentInputEditorInfo(),
17062e3aa86cf389236c085ab4758239b01e80c3b2dcMike LeBeau                mLanguageSwitcher.getInputLanguage(),
17072e3aa86cf389236c085ab4758239b01e80c3b2dcMike LeBeau                mLanguageSwitcher.getEnabledLanguages());
1708466741d8a78965b8509bf527344f289e50873092Mike LeBeau    }
1709a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
1710466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private boolean fieldCanDoVoice(FieldContext fieldContext) {
1711466741d8a78965b8509bf527344f289e50873092Mike LeBeau        return !mPasswordText
1712466741d8a78965b8509bf527344f289e50873092Mike LeBeau                && mVoiceInput != null
1713466741d8a78965b8509bf527344f289e50873092Mike LeBeau                && !mVoiceInput.isBlacklistedField(fieldContext);
1714466741d8a78965b8509bf527344f289e50873092Mike LeBeau    }
1715466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1716466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private boolean shouldShowVoiceButton(FieldContext fieldContext, EditorInfo attribute) {
1717960ea65f3f2162e7f8f387380924162d42fef4dcValentin Kravtsov        return ENABLE_VOICE_BUTTON && fieldCanDoVoice(fieldContext)
1718466741d8a78965b8509bf527344f289e50873092Mike LeBeau                && !(attribute != null && attribute.privateImeOptions != null
1719960ea65f3f2162e7f8f387380924162d42fef4dcValentin Kravtsov                        && attribute.privateImeOptions.equals(IME_OPTION_NO_MICROPHONE))
1720960ea65f3f2162e7f8f387380924162d42fef4dcValentin Kravtsov                && RecognitionManager.isRecognitionAvailable(this);
1721466741d8a78965b8509bf527344f289e50873092Mike LeBeau    }
1722a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
1723923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    // receive ringer mode changes to detect silent mode
1724923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
1725923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        @Override
1726923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        public void onReceive(Context context, Intent intent) {
1727923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            updateRingerMode();
1728923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1729923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    };
1730923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1731923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    // update flags for silent mode
1732923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private void updateRingerMode() {
1733923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mAudioManager == null) {
1734923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
1735923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1736923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mAudioManager != null) {
1737923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mSilentMode = (mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL);
1738923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1739923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1740923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1741466741d8a78965b8509bf527344f289e50873092Mike LeBeau    private boolean userHasNotTypedRecently() {
1742466741d8a78965b8509bf527344f289e50873092Mike LeBeau        return (SystemClock.uptimeMillis() - mLastKeyTime)
1743466741d8a78965b8509bf527344f289e50873092Mike LeBeau            > MIN_MILLIS_AFTER_TYPING_BEFORE_SWIPE;
1744466741d8a78965b8509bf527344f289e50873092Mike LeBeau    }
1745466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1746923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private void playKeyClick(int primaryCode) {
1747923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        // if mAudioManager is null, we don't have the ringer state yet
1748923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        // mAudioManager will be set by updateRingerMode
1749923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mAudioManager == null) {
1750923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            if (mInputView != null) {
1751923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                updateRingerMode();
1752923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            }
1753923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1754923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mSoundOn && !mSilentMode) {
1755923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            // FIXME: Volume and enable should come from UI settings
1756923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            // FIXME: These should be triggered after auto-repeat logic
1757923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            int sound = AudioManager.FX_KEYPRESS_STANDARD;
1758923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            switch (primaryCode) {
1759923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                case Keyboard.KEYCODE_DELETE:
1760923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    sound = AudioManager.FX_KEYPRESS_DELETE;
1761923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    break;
1762923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                case KEYCODE_ENTER:
1763923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    sound = AudioManager.FX_KEYPRESS_RETURN;
1764923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    break;
1765923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                case KEYCODE_SPACE:
1766923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    sound = AudioManager.FX_KEYPRESS_SPACEBAR;
1767923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    break;
1768923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            }
1769923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            mAudioManager.playSoundEffect(sound, FX_VOLUME);
1770923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1771923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1772923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1773923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private void vibrate() {
1774923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (!mVibrateOn) {
1775923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            return;
1776923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
177766a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani        if (mInputView != null) {
1778abd5e5867c25273f32a6ffa63812b62b69d91f2dAmith Yamasani            mInputView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP,
177966a787b953d703201c6b827abbee74e8cd9bb063Amith Yamasani                    HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
1780923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1781923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1782923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
17836e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani    private void checkTutorial(String privateImeOptions) {
17846e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani        if (privateImeOptions == null) return;
17856e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani        if (privateImeOptions.equals("com.android.setupwizard:ShowTutorial")) {
17866e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani            if (mTutorial == null) startTutorial();
17876e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani        } else if (privateImeOptions.equals("com.android.setupwizard:HideTutorial")) {
17886e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani            if (mTutorial != null) {
17896e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani                if (mTutorial.close()) {
17906e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani                    mTutorial = null;
17916e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani                }
17926e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani            }
17936e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani        }
17946e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani    }
1795a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
17966e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani    private void startTutorial() {
17976e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_START_TUTORIAL), 500);
17986e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani    }
17996e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani
18006e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani    void tutorialDone() {
18016e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani        mTutorial = null;
18026e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani    }
180334386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani
180434386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani    void promoteToUserDictionary(String word, int frequency) {
180534386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani        if (mUserDictionary.isValidWord(word)) return;
180634386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani        mUserDictionary.addWord(word, frequency);
180734386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani    }
180834386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani
18096516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani    WordComposer getCurrentWord() {
18106516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani        return mWord;
18116516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani    }
18126516d0fdfcbaa4eb809a8a69bd876293043a68a4Amith Yamasani
1813e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani    private void updateCorrectionMode() {
1814e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani        mHasDictionary = mSuggest != null ? mSuggest.hasMainDictionary() : false;
1815e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani        mAutoCorrectOn = (mAutoCorrectEnabled || mQuickFixes)
1816e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani                && !mInputTypeNoAutoCorrect && mHasDictionary;
181732e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani        mCorrectionMode = (mAutoCorrectOn && mAutoCorrectEnabled)
1818e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani                ? Suggest.CORRECTION_FULL
181932e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani                : (mAutoCorrectOn ? Suggest.CORRECTION_BASIC : Suggest.CORRECTION_NONE);
1820e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani        if (mSuggest != null) {
1821e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani            mSuggest.setCorrectionMode(mCorrectionMode);
1822e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani        }
1823e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani    }
1824e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani
182532e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani    private void updateAutoTextEnabled(Locale systemLocale) {
182632e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani        if (mSuggest == null) return;
18276c2f9f5ba7afedc183086d4ee3a7aa50b3866edcAmith Yamasani        boolean different =
18286c2f9f5ba7afedc183086d4ee3a7aa50b3866edcAmith Yamasani                !systemLocale.getLanguage().equalsIgnoreCase(mInputLocale.substring(0, 2));
182932e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani        mSuggest.setAutoTextEnabled(!different && mQuickFixes);
183032e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani    }
183132e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani
1832466741d8a78965b8509bf527344f289e50873092Mike LeBeau    protected void launchSettings() {
1833466741d8a78965b8509bf527344f289e50873092Mike LeBeau        launchSettings(LatinIMESettings.class);
1834466741d8a78965b8509bf527344f289e50873092Mike LeBeau    }
1835466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1836466741d8a78965b8509bf527344f289e50873092Mike LeBeau    protected void launchSettings(Class settingsClass) {
1837923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        handleClose();
1838923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        Intent intent = new Intent();
1839466741d8a78965b8509bf527344f289e50873092Mike LeBeau        intent.setClass(LatinIME.this, settingsClass);
1840923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1841923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        startActivity(intent);
1842923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1843923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1844923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private void loadSettings() {
1845923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        // Get the settings preferences
1846923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
18475ff5160ff89231ceb55d4d248fb529743d3f8e16Amith Yamasani        mVibrateOn = sp.getBoolean(PREF_VIBRATE_ON, false);
1848923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mSoundOn = sp.getBoolean(PREF_SOUND_ON, false);
1849923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mAutoCap = sp.getBoolean(PREF_AUTO_CAP, true);
18506e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani        mQuickFixes = sp.getBoolean(PREF_QUICK_FIXES, true);
1851466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mHasUsedVoiceInput = sp.getBoolean(PREF_HAS_USED_VOICE_INPUT, false);
1852466741d8a78965b8509bf527344f289e50873092Mike LeBeau        mHasUsedVoiceInputUnsupportedLocale =
1853466741d8a78965b8509bf527344f289e50873092Mike LeBeau                sp.getBoolean(PREF_HAS_USED_VOICE_INPUT_UNSUPPORTED_LOCALE, false);
1854a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
1855466741d8a78965b8509bf527344f289e50873092Mike LeBeau        // Get the current list of supported locales and check the current locale against that
1856466741d8a78965b8509bf527344f289e50873092Mike LeBeau        // list. We cache this value so as not to check it every time the user starts a voice
1857466741d8a78965b8509bf527344f289e50873092Mike LeBeau        // input. Because this method is called by onStartInputView, this should mean that as
1858466741d8a78965b8509bf527344f289e50873092Mike LeBeau        // long as the locale doesn't change while the user is keeping the IME open, the
1859466741d8a78965b8509bf527344f289e50873092Mike LeBeau        // value should never be stale.
1860a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker        String supportedLocalesString = SettingsUtil.getSettingsString(
1861466741d8a78965b8509bf527344f289e50873092Mike LeBeau                getContentResolver(),
1862a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker                SettingsUtil.LATIN_IME_VOICE_INPUT_SUPPORTED_LOCALES,
1863466741d8a78965b8509bf527344f289e50873092Mike LeBeau                DEFAULT_VOICE_INPUT_SUPPORTED_LOCALES);
1864466741d8a78965b8509bf527344f289e50873092Mike LeBeau        ArrayList<String> voiceInputSupportedLocales =
1865db84e0318cbbfa364abb364d961cb5e0d6015012Amith Yamasani                newArrayList(supportedLocalesString.split("\\s+"));
1866a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
18676c2f9f5ba7afedc183086d4ee3a7aa50b3866edcAmith Yamasani        mLocaleSupportedForVoiceInput = voiceInputSupportedLocales.contains(mInputLocale);
1868a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
186932e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani        mShowSuggestions = sp.getBoolean(PREF_SHOW_SUGGESTIONS, true);
1870466741d8a78965b8509bf527344f289e50873092Mike LeBeau
1871466741d8a78965b8509bf527344f289e50873092Mike LeBeau        if (VOICE_INSTALLED) {
18721ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani            final String voiceMode = sp.getString(PREF_VOICE_MODE,
18731ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani                    getString(R.string.voice_mode_main));
18741ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani            boolean enableVoice = !voiceMode.equals(getString(R.string.voice_mode_off))
18751ca22671191f5079a104bd7c73078561a5f48ef6Amith Yamasani                    && mEnableVoiceButton;
1876457fdffce4550b5597435f030483dcafffecf714Amith Yamasani            boolean voiceOnPrimary = voiceMode.equals(getString(R.string.voice_mode_main));
1877b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani            if (mKeyboardSwitcher != null &&
1878b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani                    (enableVoice != mEnableVoice || voiceOnPrimary != mVoiceOnPrimary)) {
1879b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani                mKeyboardSwitcher.setVoiceMode(enableVoice, voiceOnPrimary);
1880466741d8a78965b8509bf527344f289e50873092Mike LeBeau            }
1881466741d8a78965b8509bf527344f289e50873092Mike LeBeau            mEnableVoice = enableVoice;
1882b1cd7016028f5770da2688f1ec51e0601fc5b9ebAmith Yamasani            mVoiceOnPrimary = voiceOnPrimary;
1883466741d8a78965b8509bf527344f289e50873092Mike LeBeau        }
1884e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani        mAutoCorrectEnabled = sp.getBoolean(PREF_AUTO_COMPLETE,
188536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani                mResources.getBoolean(R.bool.enable_autocorrect)) & mShowSuggestions;
1886e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani        updateCorrectionMode();
188732e1c1c338155f8a83646d725a8512b95edad4f8Amith Yamasani        updateAutoTextEnabled(mResources.getConfiguration().locale);
18883f7d75060afb2bb7e74879bcbbdcb9700ec5c2d6Amith Yamasani        mLanguageSwitcher.loadLocales(sp);
188936fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani    }
189036fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani
18916a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani    private void initSuggestPuncList() {
18926a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani        mSuggestPuncList = new ArrayList<CharSequence>();
18936a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani        String suggestPuncs = mResources.getString(R.string.suggested_punctuations);
18946a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani        if (suggestPuncs != null) {
18956a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani            for (int i = 0; i < suggestPuncs.length(); i++) {
18966a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani                mSuggestPuncList.add(suggestPuncs.subSequence(i, i + 1));
18976a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani            }
18986a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani        }
18996a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani    }
19006a6075caba3865383eeeb52cccc63a28e4ae5900Amith Yamasani
1901923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private void showOptionsMenu() {
1902923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        AlertDialog.Builder builder = new AlertDialog.Builder(this);
1903923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        builder.setCancelable(true);
1904923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        builder.setIcon(R.drawable.ic_dialog_keyboard);
1905923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        builder.setNegativeButton(android.R.string.cancel, null);
1906923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        CharSequence itemSettings = getString(R.string.english_ime_settings);
1907466741d8a78965b8509bf527344f289e50873092Mike LeBeau        CharSequence itemInputMethod = getString(R.string.inputMethod);
1908923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        builder.setItems(new CharSequence[] {
1909923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                itemSettings, itemInputMethod},
1910923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                new DialogInterface.OnClickListener() {
1911923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1912923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            public void onClick(DialogInterface di, int position) {
1913923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                di.dismiss();
1914923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                switch (position) {
1915923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    case POS_SETTINGS:
1916923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                        launchSettings();
1917923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                        break;
1918923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                    case POS_METHOD:
191971351469e3af45a2ee89b017089f9e850e973a19Brandon Ballinger                        ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE))
192071351469e3af45a2ee89b017089f9e850e973a19Brandon Ballinger                            .showInputMethodPicker();
1921923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                        break;
1922923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project                }
1923923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            }
1924923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        });
192536fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani        builder.setTitle(mResources.getString(R.string.english_ime_name));
1926923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mOptionsDialog = builder.create();
1927923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        Window window = mOptionsDialog.getWindow();
1928923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        WindowManager.LayoutParams lp = window.getAttributes();
1929923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        lp.token = mInputView.getWindowToken();
1930923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
1931923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        window.setAttributes(lp);
1932923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
1933923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mOptionsDialog.show();
1934923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
1935923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1936923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private void changeKeyboardMode() {
1937923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mKeyboardSwitcher.toggleSymbols();
1938923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mCapsLock && mKeyboardSwitcher.isAlphabetMode()) {
1939923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project            ((LatinKeyboard) mInputView.getKeyboard()).setShiftLocked(mCapsLock);
1940923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        }
1941923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project
1942923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        updateShiftKeyState(getCurrentInputEditorInfo());
1943923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
194436fcf25833f7c8876cbc8286e0c159b052dc2626Amith Yamasani
1945db84e0318cbbfa364abb364d961cb5e0d6015012Amith Yamasani    public static <E> ArrayList<E> newArrayList(E... elements) {
1946db84e0318cbbfa364abb364d961cb5e0d6015012Amith Yamasani        int capacity = (elements.length * 110) / 100 + 5;
1947db84e0318cbbfa364abb364d961cb5e0d6015012Amith Yamasani        ArrayList<E> list = new ArrayList<E>(capacity);
1948db84e0318cbbfa364abb364d961cb5e0d6015012Amith Yamasani        Collections.addAll(list, elements);
1949db84e0318cbbfa364abb364d961cb5e0d6015012Amith Yamasani        return list;
1950db84e0318cbbfa364abb364d961cb5e0d6015012Amith Yamasani    }
1951db84e0318cbbfa364abb364d961cb5e0d6015012Amith Yamasani
1952923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    @Override protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
1953923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        super.dump(fd, fout, args);
1954a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
1955923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        final Printer p = new PrintWriterPrinter(fout);
1956923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        p.println("LatinIME state :");
1957923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        p.println("  Keyboard mode = " + mKeyboardSwitcher.getKeyboardMode());
1958923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        p.println("  mCapsLock=" + mCapsLock);
1959923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        p.println("  mComposing=" + mComposing.toString());
1960923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        p.println("  mPredictionOn=" + mPredictionOn);
1961923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        p.println("  mCorrectionMode=" + mCorrectionMode);
1962923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        p.println("  mPredicting=" + mPredicting);
1963923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        p.println("  mAutoCorrectOn=" + mAutoCorrectOn);
1964923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        p.println("  mAutoSpace=" + mAutoSpace);
1965923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        p.println("  mCompletionOn=" + mCompletionOn);
1966923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        p.println("  TextEntryState.state=" + TextEntryState.getState());
1967923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        p.println("  mSoundOn=" + mSoundOn);
1968923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        p.println("  mVibrateOn=" + mVibrateOn);
1969923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
19706e3d427c320e89c6155cbcf4045e399b9b55f48fAmith Yamasani
1971923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    // Characters per second measurement
1972a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
1973923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private static final boolean PERF_DEBUG = false;
1974923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private long mLastCpsTime;
1975923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private static final int CPS_BUFFER_SIZE = 16;
1976923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private long[] mCpsIntervals = new long[CPS_BUFFER_SIZE];
1977923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private int mCpsIndex;
1978e8f1edefeb2375a253d742c7f95e8d91677c7073Amith Yamasani    private boolean mInputTypeNoAutoCorrect;
1979a16ff1b19e8e012cf37a234bae67b994e805bfb1Doug Zongker
1980923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    private void measureCps() {
1981923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (!LatinIME.PERF_DEBUG) return;
1982923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        long now = System.currentTimeMillis();
1983923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        if (mLastCpsTime == 0) mLastCpsTime = now - 100; // Initial
1984923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mCpsIntervals[mCpsIndex] = now - mLastCpsTime;
1985923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mLastCpsTime = now;
1986923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        mCpsIndex = (mCpsIndex + 1) % CPS_BUFFER_SIZE;
1987923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        long total = 0;
1988923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        for (int i = 0; i < CPS_BUFFER_SIZE; i++) total += mCpsIntervals[i];
1989923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project        System.out.println("CPS = " + ((CPS_BUFFER_SIZE * 1000f) / total));
1990923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project    }
199134386e698876c0f29b2d5b54b44db1e32b562c47Amith Yamasani
1992923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project}
1993