1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.inputmethod.keyboard;
18 
19 import android.content.Context;
20 import android.content.res.Resources;
21 import android.util.Log;
22 import android.view.ContextThemeWrapper;
23 import android.view.LayoutInflater;
24 import android.view.View;
25 import android.view.inputmethod.EditorInfo;
26 
27 import com.android.inputmethod.compat.InputMethodServiceCompatUtils;
28 import com.android.inputmethod.event.Event;
29 import com.android.inputmethod.keyboard.KeyboardLayoutSet.KeyboardLayoutSetException;
30 import com.android.inputmethod.keyboard.emoji.EmojiPalettesView;
31 import com.android.inputmethod.keyboard.internal.KeyboardState;
32 import com.android.inputmethod.keyboard.internal.KeyboardTextsSet;
33 import com.android.inputmethod.latin.InputView;
34 import com.android.inputmethod.latin.LatinIME;
35 import com.android.inputmethod.latin.R;
36 import com.android.inputmethod.latin.RichInputMethodManager;
37 import com.android.inputmethod.latin.WordComposer;
38 import com.android.inputmethod.latin.define.ProductionFlags;
39 import com.android.inputmethod.latin.settings.Settings;
40 import com.android.inputmethod.latin.settings.SettingsValues;
41 import com.android.inputmethod.latin.utils.CapsModeUtils;
42 import com.android.inputmethod.latin.utils.LanguageOnSpacebarUtils;
43 import com.android.inputmethod.latin.utils.RecapitalizeStatus;
44 import com.android.inputmethod.latin.utils.ResourceUtils;
45 import com.android.inputmethod.latin.utils.ScriptUtils;
46 
47 import javax.annotation.Nonnull;
48 
49 public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
50     private static final String TAG = KeyboardSwitcher.class.getSimpleName();
51 
52     private InputView mCurrentInputView;
53     private View mMainKeyboardFrame;
54     private MainKeyboardView mKeyboardView;
55     private EmojiPalettesView mEmojiPalettesView;
56     private LatinIME mLatinIME;
57     private RichInputMethodManager mRichImm;
58     private boolean mIsHardwareAcceleratedDrawingEnabled;
59 
60     private KeyboardState mState;
61 
62     private KeyboardLayoutSet mKeyboardLayoutSet;
63     // TODO: The following {@link KeyboardTextsSet} should be in {@link KeyboardLayoutSet}.
64     private final KeyboardTextsSet mKeyboardTextsSet = new KeyboardTextsSet();
65 
66     private KeyboardTheme mKeyboardTheme;
67     private Context mThemeContext;
68 
69     private static final KeyboardSwitcher sInstance = new KeyboardSwitcher();
70 
getInstance()71     public static KeyboardSwitcher getInstance() {
72         return sInstance;
73     }
74 
KeyboardSwitcher()75     private KeyboardSwitcher() {
76         // Intentional empty constructor for singleton.
77     }
78 
init(final LatinIME latinIme)79     public static void init(final LatinIME latinIme) {
80         sInstance.initInternal(latinIme);
81     }
82 
initInternal(final LatinIME latinIme)83     private void initInternal(final LatinIME latinIme) {
84         mLatinIME = latinIme;
85         mRichImm = RichInputMethodManager.getInstance();
86         mState = new KeyboardState(this);
87         mIsHardwareAcceleratedDrawingEnabled =
88                 InputMethodServiceCompatUtils.enableHardwareAcceleration(mLatinIME);
89     }
90 
updateKeyboardTheme()91     public void updateKeyboardTheme() {
92         final boolean themeUpdated = updateKeyboardThemeAndContextThemeWrapper(
93                 mLatinIME, KeyboardTheme.getKeyboardTheme(mLatinIME /* context */));
94         if (themeUpdated && mKeyboardView != null) {
95             mLatinIME.setInputView(onCreateInputView(mIsHardwareAcceleratedDrawingEnabled));
96         }
97     }
98 
updateKeyboardThemeAndContextThemeWrapper(final Context context, final KeyboardTheme keyboardTheme)99     private boolean updateKeyboardThemeAndContextThemeWrapper(final Context context,
100             final KeyboardTheme keyboardTheme) {
101         if (mThemeContext == null || !keyboardTheme.equals(mKeyboardTheme)) {
102             mKeyboardTheme = keyboardTheme;
103             mThemeContext = new ContextThemeWrapper(context, keyboardTheme.mStyleId);
104             KeyboardLayoutSet.onKeyboardThemeChanged();
105             return true;
106         }
107         return false;
108     }
109 
loadKeyboard(final EditorInfo editorInfo, final SettingsValues settingsValues, final int currentAutoCapsState, final int currentRecapitalizeState)110     public void loadKeyboard(final EditorInfo editorInfo, final SettingsValues settingsValues,
111             final int currentAutoCapsState, final int currentRecapitalizeState) {
112         final KeyboardLayoutSet.Builder builder = new KeyboardLayoutSet.Builder(
113                 mThemeContext, editorInfo);
114         final Resources res = mThemeContext.getResources();
115         final int keyboardWidth = ResourceUtils.getDefaultKeyboardWidth(res);
116         final int keyboardHeight = ResourceUtils.getKeyboardHeight(res, settingsValues);
117         builder.setKeyboardGeometry(keyboardWidth, keyboardHeight);
118         builder.setSubtype(mRichImm.getCurrentSubtype());
119         builder.setVoiceInputKeyEnabled(settingsValues.mShowsVoiceInputKey);
120         builder.setLanguageSwitchKeyEnabled(mLatinIME.shouldShowLanguageSwitchKey());
121         builder.setSplitLayoutEnabledByUser(ProductionFlags.IS_SPLIT_KEYBOARD_SUPPORTED
122                 && settingsValues.mIsSplitKeyboardEnabled);
123         mKeyboardLayoutSet = builder.build();
124         try {
125             mState.onLoadKeyboard(currentAutoCapsState, currentRecapitalizeState);
126             mKeyboardTextsSet.setLocale(mRichImm.getCurrentSubtypeLocale(), mThemeContext);
127         } catch (KeyboardLayoutSetException e) {
128             Log.w(TAG, "loading keyboard failed: " + e.mKeyboardId, e.getCause());
129         }
130     }
131 
saveKeyboardState()132     public void saveKeyboardState() {
133         if (getKeyboard() != null || isShowingEmojiPalettes()) {
134             mState.onSaveKeyboardState();
135         }
136     }
137 
onHideWindow()138     public void onHideWindow() {
139         if (mKeyboardView != null) {
140             mKeyboardView.onHideWindow();
141         }
142     }
143 
setKeyboard( @onnull final int keyboardId, @Nonnull final KeyboardSwitchState toggleState)144     private void setKeyboard(
145             @Nonnull final int keyboardId,
146             @Nonnull final KeyboardSwitchState toggleState) {
147         // Make {@link MainKeyboardView} visible and hide {@link EmojiPalettesView}.
148         final SettingsValues currentSettingsValues = Settings.getInstance().getCurrent();
149         setMainKeyboardFrame(currentSettingsValues, toggleState);
150         // TODO: pass this object to setKeyboard instead of getting the current values.
151         final MainKeyboardView keyboardView = mKeyboardView;
152         final Keyboard oldKeyboard = keyboardView.getKeyboard();
153         final Keyboard newKeyboard = mKeyboardLayoutSet.getKeyboard(keyboardId);
154         keyboardView.setKeyboard(newKeyboard);
155         mCurrentInputView.setKeyboardTopPadding(newKeyboard.mTopPadding);
156         keyboardView.setKeyPreviewPopupEnabled(
157                 currentSettingsValues.mKeyPreviewPopupOn,
158                 currentSettingsValues.mKeyPreviewPopupDismissDelay);
159         keyboardView.setKeyPreviewAnimationParams(
160                 currentSettingsValues.mHasCustomKeyPreviewAnimationParams,
161                 currentSettingsValues.mKeyPreviewShowUpStartXScale,
162                 currentSettingsValues.mKeyPreviewShowUpStartYScale,
163                 currentSettingsValues.mKeyPreviewShowUpDuration,
164                 currentSettingsValues.mKeyPreviewDismissEndXScale,
165                 currentSettingsValues.mKeyPreviewDismissEndYScale,
166                 currentSettingsValues.mKeyPreviewDismissDuration);
167         keyboardView.updateShortcutKey(mRichImm.isShortcutImeReady());
168         final boolean subtypeChanged = (oldKeyboard == null)
169                 || !newKeyboard.mId.mSubtype.equals(oldKeyboard.mId.mSubtype);
170         final int languageOnSpacebarFormatType = LanguageOnSpacebarUtils
171                 .getLanguageOnSpacebarFormatType(newKeyboard.mId.mSubtype);
172         final boolean hasMultipleEnabledIMEsOrSubtypes = mRichImm
173                 .hasMultipleEnabledIMEsOrSubtypes(true /* shouldIncludeAuxiliarySubtypes */);
174         keyboardView.startDisplayLanguageOnSpacebar(subtypeChanged, languageOnSpacebarFormatType,
175                 hasMultipleEnabledIMEsOrSubtypes);
176     }
177 
getKeyboard()178     public Keyboard getKeyboard() {
179         if (mKeyboardView != null) {
180             return mKeyboardView.getKeyboard();
181         }
182         return null;
183     }
184 
185     // TODO: Remove this method. Come up with a more comprehensive way to reset the keyboard layout
186     // when a keyboard layout set doesn't get reloaded in LatinIME.onStartInputViewInternal().
resetKeyboardStateToAlphabet(final int currentAutoCapsState, final int currentRecapitalizeState)187     public void resetKeyboardStateToAlphabet(final int currentAutoCapsState,
188             final int currentRecapitalizeState) {
189         mState.onResetKeyboardStateToAlphabet(currentAutoCapsState, currentRecapitalizeState);
190     }
191 
onPressKey(final int code, final boolean isSinglePointer, final int currentAutoCapsState, final int currentRecapitalizeState)192     public void onPressKey(final int code, final boolean isSinglePointer,
193             final int currentAutoCapsState, final int currentRecapitalizeState) {
194         mState.onPressKey(code, isSinglePointer, currentAutoCapsState, currentRecapitalizeState);
195     }
196 
onReleaseKey(final int code, final boolean withSliding, final int currentAutoCapsState, final int currentRecapitalizeState)197     public void onReleaseKey(final int code, final boolean withSliding,
198             final int currentAutoCapsState, final int currentRecapitalizeState) {
199         mState.onReleaseKey(code, withSliding, currentAutoCapsState, currentRecapitalizeState);
200     }
201 
onFinishSlidingInput(final int currentAutoCapsState, final int currentRecapitalizeState)202     public void onFinishSlidingInput(final int currentAutoCapsState,
203             final int currentRecapitalizeState) {
204         mState.onFinishSlidingInput(currentAutoCapsState, currentRecapitalizeState);
205     }
206 
207     // Implements {@link KeyboardState.SwitchActions}.
208     @Override
setAlphabetKeyboard()209     public void setAlphabetKeyboard() {
210         if (DEBUG_ACTION) {
211             Log.d(TAG, "setAlphabetKeyboard");
212         }
213         setKeyboard(KeyboardId.ELEMENT_ALPHABET, KeyboardSwitchState.OTHER);
214     }
215 
216     // Implements {@link KeyboardState.SwitchActions}.
217     @Override
setAlphabetManualShiftedKeyboard()218     public void setAlphabetManualShiftedKeyboard() {
219         if (DEBUG_ACTION) {
220             Log.d(TAG, "setAlphabetManualShiftedKeyboard");
221         }
222         setKeyboard(KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED, KeyboardSwitchState.OTHER);
223     }
224 
225     // Implements {@link KeyboardState.SwitchActions}.
226     @Override
setAlphabetAutomaticShiftedKeyboard()227     public void setAlphabetAutomaticShiftedKeyboard() {
228         if (DEBUG_ACTION) {
229             Log.d(TAG, "setAlphabetAutomaticShiftedKeyboard");
230         }
231         setKeyboard(KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED, KeyboardSwitchState.OTHER);
232     }
233 
234     // Implements {@link KeyboardState.SwitchActions}.
235     @Override
setAlphabetShiftLockedKeyboard()236     public void setAlphabetShiftLockedKeyboard() {
237         if (DEBUG_ACTION) {
238             Log.d(TAG, "setAlphabetShiftLockedKeyboard");
239         }
240         setKeyboard(KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED, KeyboardSwitchState.OTHER);
241     }
242 
243     // Implements {@link KeyboardState.SwitchActions}.
244     @Override
setAlphabetShiftLockShiftedKeyboard()245     public void setAlphabetShiftLockShiftedKeyboard() {
246         if (DEBUG_ACTION) {
247             Log.d(TAG, "setAlphabetShiftLockShiftedKeyboard");
248         }
249         setKeyboard(KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED, KeyboardSwitchState.OTHER);
250     }
251 
252     // Implements {@link KeyboardState.SwitchActions}.
253     @Override
setSymbolsKeyboard()254     public void setSymbolsKeyboard() {
255         if (DEBUG_ACTION) {
256             Log.d(TAG, "setSymbolsKeyboard");
257         }
258         setKeyboard(KeyboardId.ELEMENT_SYMBOLS, KeyboardSwitchState.OTHER);
259     }
260 
261     // Implements {@link KeyboardState.SwitchActions}.
262     @Override
setSymbolsShiftedKeyboard()263     public void setSymbolsShiftedKeyboard() {
264         if (DEBUG_ACTION) {
265             Log.d(TAG, "setSymbolsShiftedKeyboard");
266         }
267         setKeyboard(KeyboardId.ELEMENT_SYMBOLS_SHIFTED, KeyboardSwitchState.SYMBOLS_SHIFTED);
268     }
269 
isImeSuppressedByHardwareKeyboard( @onnull final SettingsValues settingsValues, @Nonnull final KeyboardSwitchState toggleState)270     public boolean isImeSuppressedByHardwareKeyboard(
271             @Nonnull final SettingsValues settingsValues,
272             @Nonnull final KeyboardSwitchState toggleState) {
273         return settingsValues.mHasHardwareKeyboard && toggleState == KeyboardSwitchState.HIDDEN;
274     }
275 
setMainKeyboardFrame( @onnull final SettingsValues settingsValues, @Nonnull final KeyboardSwitchState toggleState)276     private void setMainKeyboardFrame(
277             @Nonnull final SettingsValues settingsValues,
278             @Nonnull final KeyboardSwitchState toggleState) {
279         final int visibility =  isImeSuppressedByHardwareKeyboard(settingsValues, toggleState)
280                 ? View.GONE : View.VISIBLE;
281         mKeyboardView.setVisibility(visibility);
282         // The visibility of {@link #mKeyboardView} must be aligned with {@link #MainKeyboardFrame}.
283         // @see #getVisibleKeyboardView() and
284         // @see LatinIME#onComputeInset(android.inputmethodservice.InputMethodService.Insets)
285         mMainKeyboardFrame.setVisibility(visibility);
286         mEmojiPalettesView.setVisibility(View.GONE);
287         mEmojiPalettesView.stopEmojiPalettes();
288     }
289 
290     // Implements {@link KeyboardState.SwitchActions}.
291     @Override
setEmojiKeyboard()292     public void setEmojiKeyboard() {
293         if (DEBUG_ACTION) {
294             Log.d(TAG, "setEmojiKeyboard");
295         }
296         final Keyboard keyboard = mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET);
297         mMainKeyboardFrame.setVisibility(View.GONE);
298         // The visibility of {@link #mKeyboardView} must be aligned with {@link #MainKeyboardFrame}.
299         // @see #getVisibleKeyboardView() and
300         // @see LatinIME#onComputeInset(android.inputmethodservice.InputMethodService.Insets)
301         mKeyboardView.setVisibility(View.GONE);
302         mEmojiPalettesView.startEmojiPalettes(
303                 mKeyboardTextsSet.getText(KeyboardTextsSet.SWITCH_TO_ALPHA_KEY_LABEL),
304                 mKeyboardView.getKeyVisualAttribute(), keyboard.mIconsSet);
305         mEmojiPalettesView.setVisibility(View.VISIBLE);
306     }
307 
308     public enum KeyboardSwitchState {
309         HIDDEN(-1),
310         SYMBOLS_SHIFTED(KeyboardId.ELEMENT_SYMBOLS_SHIFTED),
311         EMOJI(KeyboardId.ELEMENT_EMOJI_RECENTS),
312         OTHER(-1);
313 
314         final int mKeyboardId;
315 
KeyboardSwitchState(int keyboardId)316         KeyboardSwitchState(int keyboardId) {
317             mKeyboardId = keyboardId;
318         }
319     }
320 
getKeyboardSwitchState()321     public KeyboardSwitchState getKeyboardSwitchState() {
322         boolean hidden = !isShowingEmojiPalettes()
323                 && (mKeyboardLayoutSet == null
324                 || mKeyboardView == null
325                 || !mKeyboardView.isShown());
326         KeyboardSwitchState state;
327         if (hidden) {
328             return KeyboardSwitchState.HIDDEN;
329         } else if (isShowingEmojiPalettes()) {
330             return KeyboardSwitchState.EMOJI;
331         } else if (isShowingKeyboardId(KeyboardId.ELEMENT_SYMBOLS_SHIFTED)) {
332             return KeyboardSwitchState.SYMBOLS_SHIFTED;
333         }
334         return KeyboardSwitchState.OTHER;
335     }
336 
onToggleKeyboard(@onnull final KeyboardSwitchState toggleState)337     public void onToggleKeyboard(@Nonnull final KeyboardSwitchState toggleState) {
338         KeyboardSwitchState currentState = getKeyboardSwitchState();
339         Log.w(TAG, "onToggleKeyboard() : Current = " + currentState + " : Toggle = " + toggleState);
340         if (currentState == toggleState) {
341             mLatinIME.stopShowingInputView();
342             mLatinIME.hideWindow();
343             setAlphabetKeyboard();
344         } else {
345             mLatinIME.startShowingInputView(true);
346             if (toggleState == KeyboardSwitchState.EMOJI) {
347                 setEmojiKeyboard();
348             } else {
349                 mEmojiPalettesView.stopEmojiPalettes();
350                 mEmojiPalettesView.setVisibility(View.GONE);
351 
352                 mMainKeyboardFrame.setVisibility(View.VISIBLE);
353                 mKeyboardView.setVisibility(View.VISIBLE);
354                 setKeyboard(toggleState.mKeyboardId, toggleState);
355             }
356         }
357     }
358 
359     // Future method for requesting an updating to the shift state.
360     @Override
requestUpdatingShiftState(final int autoCapsFlags, final int recapitalizeMode)361     public void requestUpdatingShiftState(final int autoCapsFlags, final int recapitalizeMode) {
362         if (DEBUG_ACTION) {
363             Log.d(TAG, "requestUpdatingShiftState: "
364                     + " autoCapsFlags=" + CapsModeUtils.flagsToString(autoCapsFlags)
365                     + " recapitalizeMode=" + RecapitalizeStatus.modeToString(recapitalizeMode));
366         }
367         mState.onUpdateShiftState(autoCapsFlags, recapitalizeMode);
368     }
369 
370     // Implements {@link KeyboardState.SwitchActions}.
371     @Override
startDoubleTapShiftKeyTimer()372     public void startDoubleTapShiftKeyTimer() {
373         if (DEBUG_TIMER_ACTION) {
374             Log.d(TAG, "startDoubleTapShiftKeyTimer");
375         }
376         final MainKeyboardView keyboardView = getMainKeyboardView();
377         if (keyboardView != null) {
378             keyboardView.startDoubleTapShiftKeyTimer();
379         }
380     }
381 
382     // Implements {@link KeyboardState.SwitchActions}.
383     @Override
cancelDoubleTapShiftKeyTimer()384     public void cancelDoubleTapShiftKeyTimer() {
385         if (DEBUG_TIMER_ACTION) {
386             Log.d(TAG, "setAlphabetKeyboard");
387         }
388         final MainKeyboardView keyboardView = getMainKeyboardView();
389         if (keyboardView != null) {
390             keyboardView.cancelDoubleTapShiftKeyTimer();
391         }
392     }
393 
394     // Implements {@link KeyboardState.SwitchActions}.
395     @Override
isInDoubleTapShiftKeyTimeout()396     public boolean isInDoubleTapShiftKeyTimeout() {
397         if (DEBUG_TIMER_ACTION) {
398             Log.d(TAG, "isInDoubleTapShiftKeyTimeout");
399         }
400         final MainKeyboardView keyboardView = getMainKeyboardView();
401         return keyboardView != null && keyboardView.isInDoubleTapShiftKeyTimeout();
402     }
403 
404     /**
405      * Updates state machine to figure out when to automatically switch back to the previous mode.
406      */
onEvent(final Event event, final int currentAutoCapsState, final int currentRecapitalizeState)407     public void onEvent(final Event event, final int currentAutoCapsState,
408             final int currentRecapitalizeState) {
409         mState.onEvent(event, currentAutoCapsState, currentRecapitalizeState);
410     }
411 
isShowingKeyboardId(@onnull int... keyboardIds)412     public boolean isShowingKeyboardId(@Nonnull int... keyboardIds) {
413         if (mKeyboardView == null || !mKeyboardView.isShown()) {
414             return false;
415         }
416         int activeKeyboardId = mKeyboardView.getKeyboard().mId.mElementId;
417         for (int keyboardId : keyboardIds) {
418             if (activeKeyboardId == keyboardId) {
419                 return true;
420             }
421         }
422         return false;
423     }
424 
isShowingEmojiPalettes()425     public boolean isShowingEmojiPalettes() {
426         return mEmojiPalettesView != null && mEmojiPalettesView.isShown();
427     }
428 
isShowingMoreKeysPanel()429     public boolean isShowingMoreKeysPanel() {
430         if (isShowingEmojiPalettes()) {
431             return false;
432         }
433         return mKeyboardView.isShowingMoreKeysPanel();
434     }
435 
getVisibleKeyboardView()436     public View getVisibleKeyboardView() {
437         if (isShowingEmojiPalettes()) {
438             return mEmojiPalettesView;
439         }
440         return mKeyboardView;
441     }
442 
getMainKeyboardView()443     public MainKeyboardView getMainKeyboardView() {
444         return mKeyboardView;
445     }
446 
deallocateMemory()447     public void deallocateMemory() {
448         if (mKeyboardView != null) {
449             mKeyboardView.cancelAllOngoingEvents();
450             mKeyboardView.deallocateMemory();
451         }
452         if (mEmojiPalettesView != null) {
453             mEmojiPalettesView.stopEmojiPalettes();
454         }
455     }
456 
onCreateInputView(final boolean isHardwareAcceleratedDrawingEnabled)457     public View onCreateInputView(final boolean isHardwareAcceleratedDrawingEnabled) {
458         if (mKeyboardView != null) {
459             mKeyboardView.closing();
460         }
461 
462         updateKeyboardThemeAndContextThemeWrapper(
463                 mLatinIME, KeyboardTheme.getKeyboardTheme(mLatinIME /* context */));
464         mCurrentInputView = (InputView)LayoutInflater.from(mThemeContext).inflate(
465                 R.layout.input_view, null);
466         mMainKeyboardFrame = mCurrentInputView.findViewById(R.id.main_keyboard_frame);
467         mEmojiPalettesView = (EmojiPalettesView)mCurrentInputView.findViewById(
468                 R.id.emoji_palettes_view);
469 
470         mKeyboardView = (MainKeyboardView) mCurrentInputView.findViewById(R.id.keyboard_view);
471         mKeyboardView.setHardwareAcceleratedDrawingEnabled(isHardwareAcceleratedDrawingEnabled);
472         mKeyboardView.setKeyboardActionListener(mLatinIME);
473         mEmojiPalettesView.setHardwareAcceleratedDrawingEnabled(
474                 isHardwareAcceleratedDrawingEnabled);
475         mEmojiPalettesView.setKeyboardActionListener(mLatinIME);
476         return mCurrentInputView;
477     }
478 
getKeyboardShiftMode()479     public int getKeyboardShiftMode() {
480         final Keyboard keyboard = getKeyboard();
481         if (keyboard == null) {
482             return WordComposer.CAPS_MODE_OFF;
483         }
484         switch (keyboard.mId.mElementId) {
485         case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED:
486         case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED:
487             return WordComposer.CAPS_MODE_MANUAL_SHIFT_LOCKED;
488         case KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED:
489             return WordComposer.CAPS_MODE_MANUAL_SHIFTED;
490         case KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED:
491             return WordComposer.CAPS_MODE_AUTO_SHIFTED;
492         default:
493             return WordComposer.CAPS_MODE_OFF;
494         }
495     }
496 
getCurrentKeyboardScriptId()497     public int getCurrentKeyboardScriptId() {
498         if (null == mKeyboardLayoutSet) {
499             return ScriptUtils.SCRIPT_UNKNOWN;
500         }
501         return mKeyboardLayoutSet.getScriptId();
502     }
503 }
504