MainKeyboardView.java revision bb476be4e62b3bed7848d37df42f8fa7363b58d1
15f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka/* 25f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka * Copyright (C) 2011 The Android Open Source Project 35f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka * 45f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka * Licensed under the Apache License, Version 2.0 (the "License"); 55f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka * you may not use this file except in compliance with the License. 65f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka * You may obtain a copy of the License at 75f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka * 85f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka * http://www.apache.org/licenses/LICENSE-2.0 95f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka * 105f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka * Unless required by applicable law or agreed to in writing, software 115f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka * distributed under the License is distributed on an "AS IS" BASIS, 125f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka * See the License for the specific language governing permissions and 145f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka * limitations under the License. 155f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka */ 165f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka 175f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaokapackage com.android.inputmethod.keyboard; 185f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka 19d7c4ba170982ddce5ac12ea92c3c3d8b53d524baTadashi G. Takaokaimport android.animation.AnimatorInflater; 2031c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaokaimport android.animation.ObjectAnimator; 215f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaokaimport android.content.Context; 2213ae76d7a342581160c172cd21706b3d57d32dadTadashi G. Takaokaimport android.content.SharedPreferences; 235f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaokaimport android.content.pm.PackageManager; 244112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaokaimport android.content.res.TypedArray; 256dde878d515f7bf5268d16a8fe4921d8821c5ae7Tadashi G. Takaokaimport android.graphics.Canvas; 26f3c4cd45a5df6f90b922ea44db259e53117bb25aTadashi G. Takaokaimport android.graphics.Color; 2722b48de11ce6f31a0edf90e1308073e67a7a2adbTadashi G. Takaokaimport android.graphics.Paint; 284112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaokaimport android.graphics.Paint.Align; 29bd93eddb52816acedd5242864e467781d4adfd71Tadashi G. Takaokaimport android.graphics.Typeface; 304112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaokaimport android.graphics.drawable.Drawable; 3113ae76d7a342581160c172cd21706b3d57d32dadTadashi G. Takaokaimport android.preference.PreferenceManager; 325f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaokaimport android.util.AttributeSet; 33375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaokaimport android.util.DisplayMetrics; 345f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaokaimport android.util.Log; 355f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaokaimport android.view.LayoutInflater; 365f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaokaimport android.view.MotionEvent; 375f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaokaimport android.view.View; 38b8dc67466339dc14653ad634c86851025373326bTadashi G. Takaokaimport android.view.ViewGroup; 39f6972561fcb45310f18230ce217f0c6bb57e7eeeTadashi G. Takaokaimport android.view.inputmethod.InputMethodSubtype; 400e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaokaimport android.widget.TextView; 415f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka 425f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaokaimport com.android.inputmethod.accessibility.AccessibilityUtils; 435f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaokaimport com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy; 4415f6d4ae34664ea3d92827a2c3003198c0bac70bTadashi G. Takaokaimport com.android.inputmethod.annotations.ExternallyReferenced; 452fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasaimport com.android.inputmethod.keyboard.internal.DrawingHandler; 46cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.DrawingPreviewPlacerView; 47cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.GestureFloatingTextDrawingPreview; 48cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.GestureTrailsDrawingPreview; 4949d8af8a4e900f3c68c333aba7fde0a11fd368b1Tadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.KeyDrawParams; 50bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.KeyPreviewChoreographer; 510e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.KeyPreviewDrawParams; 52b6cc3a85ab68cff2fae4c3858b48d9c5d7b45690Tadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.NonDistinctMultitouchHelper; 53cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.SlidingKeyInputDrawingPreview; 542fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasaimport com.android.inputmethod.keyboard.internal.TimerHandler; 554daf32b6c0358f0273a99b622a259ecdf6b44fa4Tom Ouyangimport com.android.inputmethod.latin.Constants; 5615d4793911fa305e0a58aced925961e948582979satokimport com.android.inputmethod.latin.LatinImeLogger; 575f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaokaimport com.android.inputmethod.latin.R; 58375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaokaimport com.android.inputmethod.latin.SuggestedWords; 59c166697e3f5ec600089987dbbff0be7f3e308565Ken Wakasaimport com.android.inputmethod.latin.define.ProductionFlag; 60a7d2fc6befa1b16883200a653fc01deb4d94944dKen Wakasaimport com.android.inputmethod.latin.settings.DebugSettings; 61e28eba5074664d5716b8e58b8d0a235746b261ebKen Wakasaimport com.android.inputmethod.latin.utils.CollectionUtils; 62e28eba5074664d5716b8e58b8d0a235746b261ebKen Wakasaimport com.android.inputmethod.latin.utils.CoordinateUtils; 63a410cb48eab0cd75aa27e20f60e47a29a59fb9ffTadashi G. Takaokaimport com.android.inputmethod.latin.utils.SubtypeLocaleUtils; 64ccf4a310279b13bbf0b6aac76a0878178c1dfb7dTadashi G. Takaokaimport com.android.inputmethod.latin.utils.TypefaceUtils; 654be6198cb73cc24e10834153c4e049644ed187e3Tadashi G. Takaokaimport com.android.inputmethod.latin.utils.UsabilityStudyLogUtils; 66ccf4a310279b13bbf0b6aac76a0878178c1dfb7dTadashi G. Takaokaimport com.android.inputmethod.latin.utils.ViewLayoutUtils; 676b966160ac8570271547bf63217efa5e228d4accKurt Partridgeimport com.android.inputmethod.research.ResearchLogger; 685f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka 695f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaokaimport java.util.WeakHashMap; 705f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka 715f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka/** 725f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka * A view that is responsible for detecting key presses and touch movements. 735f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka * 74dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_autoCorrectionSpacebarLedEnabled 75dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_autoCorrectionSpacebarLedIcon 762fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa * @attr ref R.styleable#MainKeyboardView_languageOnSpacebarTextRatio 772fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa * @attr ref R.styleable#MainKeyboardView_languageOnSpacebarTextColor 782fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa * @attr ref R.styleable#MainKeyboardView_languageOnSpacebarTextShadowColor 792fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa * @attr ref R.styleable#MainKeyboardView_spacebarBackground 80dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_languageOnSpacebarFinalAlpha 81dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_languageOnSpacebarFadeoutAnimator 82dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_altCodeKeyWhileTypingFadeoutAnimator 83dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_altCodeKeyWhileTypingFadeinAnimator 84dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_keyHysteresisDistance 85dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_touchNoiseThresholdTime 86dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_touchNoiseThresholdDistance 872fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa * @attr ref R.styleable#MainKeyboardView_keySelectionByDraggingFinger 88dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_keyRepeatStartTimeout 89dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_keyRepeatInterval 90dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_longPressKeyTimeout 91dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_longPressShiftKeyTimeout 92dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_ignoreAltCodeKeyTimeout 93375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_keyPreviewLayout 940e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_keyPreviewOffset 950e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_keyPreviewHeight 960e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_keyPreviewLingerTimeout 97d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_moreKeysKeyboardLayout 98f3c4cd45a5df6f90b922ea44db259e53117bb25aTadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_backgroundDimAlpha 99dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_showMoreKeysKeyboardAtTouchPoint 100375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_gestureFloatingPreviewTextLingerTimeout 1013623b9767b3d5f122f574d4c4d14aa79ed305752Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_gestureStaticTimeThresholdAfterFastTyping 1023623b9767b3d5f122f574d4c4d14aa79ed305752Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_gestureDetectFastMoveSpeedThreshold 1033623b9767b3d5f122f574d4c4d14aa79ed305752Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_gestureDynamicThresholdDecayDuration 1043623b9767b3d5f122f574d4c4d14aa79ed305752Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_gestureDynamicTimeThresholdFrom 1053623b9767b3d5f122f574d4c4d14aa79ed305752Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_gestureDynamicTimeThresholdTo 1063623b9767b3d5f122f574d4c4d14aa79ed305752Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_gestureDynamicDistanceThresholdFrom 1073623b9767b3d5f122f574d4c4d14aa79ed305752Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_gestureDynamicDistanceThresholdTo 1083623b9767b3d5f122f574d4c4d14aa79ed305752Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_gestureSamplingMinimumDistance 1093623b9767b3d5f122f574d4c4d14aa79ed305752Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_gestureRecognitionMinimumTime 1103623b9767b3d5f122f574d4c4d14aa79ed305752Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_gestureRecognitionSpeedThreshold 1113623b9767b3d5f122f574d4c4d14aa79ed305752Tadashi G. Takaoka * @attr ref R.styleable#MainKeyboardView_suppressKeyPreviewAfterBatchInputDuration 1125f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka */ 1132fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasapublic final class MainKeyboardView extends KeyboardView implements PointerTracker.DrawingProxy, 1142fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa MoreKeysPanel.Controller, DrawingHandler.Callbacks, TimerHandler.Callbacks { 115c8e45ddb032554f4e9d4411d8ef47d98db62d77bTadashi G. Takaoka private static final String TAG = MainKeyboardView.class.getSimpleName(); 1165f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka 117bd93eddb52816acedd5242864e467781d4adfd71Tadashi G. Takaoka /** Listener for {@link KeyboardActionListener}. */ 118bd93eddb52816acedd5242864e467781d4adfd71Tadashi G. Takaoka private KeyboardActionListener mKeyboardActionListener; 119bd93eddb52816acedd5242864e467781d4adfd71Tadashi G. Takaoka 1202fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa /* Space key and its icon and background. */ 1214112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka private Key mSpaceKey; 1222fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa private Drawable mSpacebarIcon; 1232fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa private final Drawable mSpacebarBackground; 124bd93eddb52816acedd5242864e467781d4adfd71Tadashi G. Takaoka // Stuff to draw language name on spacebar. 12531c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka private final int mLanguageOnSpacebarFinalAlpha; 12631c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka private ObjectAnimator mLanguageOnSpacebarFadeoutAnimator; 127bd93eddb52816acedd5242864e467781d4adfd71Tadashi G. Takaoka private boolean mNeedsToDisplayLanguage; 128fd60b2f97035382b14dce207b3613711982a613eTadashi G. Takaoka private boolean mHasMultipleEnabledIMEsOrSubtypes; 1294daf32b6c0358f0273a99b622a259ecdf6b44fa4Tom Ouyang private int mLanguageOnSpacebarAnimAlpha = Constants.Color.ALPHA_OPAQUE; 1302fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa private final float mLanguageOnSpacebarTextRatio; 1312fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa private float mLanguageOnSpacebarTextSize; 1322fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa private final int mLanguageOnSpacebarTextColor; 1332fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa private final int mLanguageOnSpacebarTextShadowColor; 134bd2ca9c0214ea80fa860f4a9d118f866e16b03caTadashi G. Takaoka // The minimum x-scale to fit the language name on spacebar. 135bd2ca9c0214ea80fa860f4a9d118f866e16b03caTadashi G. Takaoka private static final float MINIMUM_XSCALE_OF_LANGUAGE_NAME = 0.8f; 136bd93eddb52816acedd5242864e467781d4adfd71Tadashi G. Takaoka // Stuff to draw auto correction LED on spacebar. 137bd93eddb52816acedd5242864e467781d4adfd71Tadashi G. Takaoka private boolean mAutoCorrectionSpacebarLedOn; 138bd93eddb52816acedd5242864e467781d4adfd71Tadashi G. Takaoka private final boolean mAutoCorrectionSpacebarLedEnabled; 139bd93eddb52816acedd5242864e467781d4adfd71Tadashi G. Takaoka private final Drawable mAutoCorrectionSpacebarLedIcon; 140bd93eddb52816acedd5242864e467781d4adfd71Tadashi G. Takaoka private static final int SPACE_LED_LENGTH_PERCENT = 80; 14115d4793911fa305e0a58aced925961e948582979satok 14273a46bfeb7a109b49be196e5d679e44c9e66a2e8Tadashi G. Takaoka // Stuff to draw altCodeWhileTyping keys. 1432fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa private final ObjectAnimator mAltCodeKeyWhileTypingFadeoutAnimator; 1442fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa private final ObjectAnimator mAltCodeKeyWhileTypingFadeinAnimator; 1454daf32b6c0358f0273a99b622a259ecdf6b44fa4Tom Ouyang private int mAltCodeKeyWhileTypingAnimAlpha = Constants.Color.ALPHA_OPAQUE; 14673a46bfeb7a109b49be196e5d679e44c9e66a2e8Tadashi G. Takaoka 147cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka // Drawing preview placer view 148cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka private final DrawingPreviewPlacerView mDrawingPreviewPlacerView; 149375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka private final int[] mOriginCoords = CoordinateUtils.newInstance(); 150cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka private final GestureFloatingTextDrawingPreview mGestureFloatingTextDrawingPreview; 151cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka private final GestureTrailsDrawingPreview mGestureTrailsDrawingPreview; 152cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka private final SlidingKeyInputDrawingPreview mSlidingKeyInputDrawingPreview; 153375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka 1540e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka // Key preview 1552fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa private static final boolean FADE_OUT_KEY_TOP_LETTER_WHEN_KEY_IS_PRESSED = false; 156992c5219092ccafe66363451fbf4ca7c5a43fb20Tadashi G. Takaoka private final KeyPreviewDrawParams mKeyPreviewDrawParams; 157bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka private final KeyPreviewChoreographer mKeyPreviewChoreographer; 1580e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka 1592affaf91a04d63e0994102299816014a8bbe11e1Tadashi G. Takaoka // More keys keyboard 160f3c4cd45a5df6f90b922ea44db259e53117bb25aTadashi G. Takaoka private final Paint mBackgroundDimAlphaPaint = new Paint(); 161f3c4cd45a5df6f90b922ea44db259e53117bb25aTadashi G. Takaoka private boolean mNeedsToDimEntireKeyboard; 162a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka private final View mMoreKeysKeyboardContainer; 163a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka private final WeakHashMap<Key, Keyboard> mMoreKeysKeyboardCache = 164a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka CollectionUtils.newWeakHashMap(); 1652affaf91a04d63e0994102299816014a8bbe11e1Tadashi G. Takaoka private final boolean mConfigShowMoreKeysKeyboardAtTouchedPoint; 166d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka // More keys panel (used by both more keys keyboard and more suggestions view) 167d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka // TODO: Consider extending to support multiple more keys panels 168d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka private MoreKeysPanel mMoreKeysPanel; 1695f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka 170375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka // Gesture floating preview text 171375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka // TODO: Make this parameter customizable by user via settings. 172375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka private int mGestureFloatingPreviewTextLingerTimeout; 173375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka 1742fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa private final KeyDetector mKeyDetector; 175b6cc3a85ab68cff2fae4c3858b48d9c5d7b45690Tadashi G. Takaoka private final NonDistinctMultitouchHelper mNonDistinctMultitouchHelper; 1765f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka 1772fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa private final TimerHandler mKeyTimerHandler; 178741831d32295acfb7675d7e0781a634d78868c63Satoshi Kataoka private final int mLanguageOnSpacebarHorizontalMargin; 1795f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka 1802fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa private final DrawingHandler mDrawingHandler = 1812fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa new DrawingHandler(this); 182375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka 183dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka public MainKeyboardView(final Context context, final AttributeSet attrs) { 184c8e45ddb032554f4e9d4411d8ef47d98db62d77bTadashi G. Takaoka this(context, attrs, R.attr.mainKeyboardViewStyle); 1855f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka } 1865f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka 187dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka public MainKeyboardView(final Context context, final AttributeSet attrs, final int defStyle) { 1885f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka super(context, attrs, defStyle); 1895f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka 190cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka mDrawingPreviewPlacerView = new DrawingPreviewPlacerView(context, attrs); 1912fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa 1922fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa final TypedArray mainKeyboardViewAttr = context.obtainStyledAttributes( 1932fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa attrs, R.styleable.MainKeyboardView, defStyle, R.style.MainKeyboardView); 1942fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa final int ignoreAltCodeKeyTimeout = mainKeyboardViewAttr.getInt( 1952fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa R.styleable.MainKeyboardView_ignoreAltCodeKeyTimeout, 0); 1962fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa final int gestureRecognitionUpdateTime = mainKeyboardViewAttr.getInt( 1972fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa R.styleable.MainKeyboardView_gestureRecognitionUpdateTime, 0); 1982fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa mKeyTimerHandler = new TimerHandler( 1992fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa this, ignoreAltCodeKeyTimeout, gestureRecognitionUpdateTime); 2002fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa 2012fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa final float keyHysteresisDistance = mainKeyboardViewAttr.getDimension( 2022fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa R.styleable.MainKeyboardView_keyHysteresisDistance, 0.0f); 2032fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa final float keyHysteresisDistanceForSlidingModifier = mainKeyboardViewAttr.getDimension( 2042fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa R.styleable.MainKeyboardView_keyHysteresisDistanceForSlidingModifier, 0.0f); 2052fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa mKeyDetector = new KeyDetector( 2062fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa keyHysteresisDistance, keyHysteresisDistanceForSlidingModifier); 2072fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa 208921a32f0a923ca00c4818d3869f0abd9a63dcf0eTadashi G. Takaoka PointerTracker.init(mainKeyboardViewAttr, mKeyTimerHandler, this /* DrawingProxy */); 2092fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa 21013ae76d7a342581160c172cd21706b3d57d32dadTadashi G. Takaoka final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); 21113ae76d7a342581160c172cd21706b3d57d32dadTadashi G. Takaoka final boolean forceNonDistinctMultitouch = prefs.getBoolean( 212a5ff9f0c77005769f92ca1131882bb4e3ca18980Tadashi G. Takaoka DebugSettings.PREF_FORCE_NON_DISTINCT_MULTITOUCH, false); 21313ae76d7a342581160c172cd21706b3d57d32dadTadashi G. Takaoka final boolean hasDistinctMultitouch = context.getPackageManager() 214b6cc3a85ab68cff2fae4c3858b48d9c5d7b45690Tadashi G. Takaoka .hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT) 215b6cc3a85ab68cff2fae4c3858b48d9c5d7b45690Tadashi G. Takaoka && !forceNonDistinctMultitouch; 216b6cc3a85ab68cff2fae4c3858b48d9c5d7b45690Tadashi G. Takaoka mNonDistinctMultitouchHelper = hasDistinctMultitouch ? null 217921a32f0a923ca00c4818d3869f0abd9a63dcf0eTadashi G. Takaoka : new NonDistinctMultitouchHelper(); 21822b48de11ce6f31a0edf90e1308073e67a7a2adbTadashi G. Takaoka 219f3c4cd45a5df6f90b922ea44db259e53117bb25aTadashi G. Takaoka final int backgroundDimAlpha = mainKeyboardViewAttr.getInt( 220f3c4cd45a5df6f90b922ea44db259e53117bb25aTadashi G. Takaoka R.styleable.MainKeyboardView_backgroundDimAlpha, 0); 221f3c4cd45a5df6f90b922ea44db259e53117bb25aTadashi G. Takaoka mBackgroundDimAlphaPaint.setColor(Color.BLACK); 222f3c4cd45a5df6f90b922ea44db259e53117bb25aTadashi G. Takaoka mBackgroundDimAlphaPaint.setAlpha(backgroundDimAlpha); 2232fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa mSpacebarBackground = mainKeyboardViewAttr.getDrawable( 2242fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa R.styleable.MainKeyboardView_spacebarBackground); 225d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka mAutoCorrectionSpacebarLedEnabled = mainKeyboardViewAttr.getBoolean( 226c8e45ddb032554f4e9d4411d8ef47d98db62d77bTadashi G. Takaoka R.styleable.MainKeyboardView_autoCorrectionSpacebarLedEnabled, false); 227d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka mAutoCorrectionSpacebarLedIcon = mainKeyboardViewAttr.getDrawable( 228c8e45ddb032554f4e9d4411d8ef47d98db62d77bTadashi G. Takaoka R.styleable.MainKeyboardView_autoCorrectionSpacebarLedIcon); 2292fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa mLanguageOnSpacebarTextRatio = mainKeyboardViewAttr.getFraction( 2302fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa R.styleable.MainKeyboardView_languageOnSpacebarTextRatio, 1, 1, 1.0f); 2312fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa mLanguageOnSpacebarTextColor = mainKeyboardViewAttr.getColor( 2322fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa R.styleable.MainKeyboardView_languageOnSpacebarTextColor, 0); 2332fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa mLanguageOnSpacebarTextShadowColor = mainKeyboardViewAttr.getColor( 2342fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa R.styleable.MainKeyboardView_languageOnSpacebarTextShadowColor, 0); 235d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka mLanguageOnSpacebarFinalAlpha = mainKeyboardViewAttr.getInt( 236c8e45ddb032554f4e9d4411d8ef47d98db62d77bTadashi G. Takaoka R.styleable.MainKeyboardView_languageOnSpacebarFinalAlpha, 2374daf32b6c0358f0273a99b622a259ecdf6b44fa4Tom Ouyang Constants.Color.ALPHA_OPAQUE); 238d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka final int languageOnSpacebarFadeoutAnimatorResId = mainKeyboardViewAttr.getResourceId( 239c8e45ddb032554f4e9d4411d8ef47d98db62d77bTadashi G. Takaoka R.styleable.MainKeyboardView_languageOnSpacebarFadeoutAnimator, 0); 240d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka final int altCodeKeyWhileTypingFadeoutAnimatorResId = mainKeyboardViewAttr.getResourceId( 241c8e45ddb032554f4e9d4411d8ef47d98db62d77bTadashi G. Takaoka R.styleable.MainKeyboardView_altCodeKeyWhileTypingFadeoutAnimator, 0); 242d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka final int altCodeKeyWhileTypingFadeinAnimatorResId = mainKeyboardViewAttr.getResourceId( 243c8e45ddb032554f4e9d4411d8ef47d98db62d77bTadashi G. Takaoka R.styleable.MainKeyboardView_altCodeKeyWhileTypingFadeinAnimator, 0); 244160f01211d169d64102205e80e9ac8d46c7d674bTadashi G. Takaoka 245992c5219092ccafe66363451fbf4ca7c5a43fb20Tadashi G. Takaoka mKeyPreviewDrawParams = new KeyPreviewDrawParams(mainKeyboardViewAttr); 246bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka mKeyPreviewChoreographer = new KeyPreviewChoreographer(mKeyPreviewDrawParams); 247bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka 248a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka final int moreKeysKeyboardLayoutId = mainKeyboardViewAttr.getResourceId( 249d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka R.styleable.MainKeyboardView_moreKeysKeyboardLayout, 0); 250d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka mConfigShowMoreKeysKeyboardAtTouchedPoint = mainKeyboardViewAttr.getBoolean( 251c8e45ddb032554f4e9d4411d8ef47d98db62d77bTadashi G. Takaoka R.styleable.MainKeyboardView_showMoreKeysKeyboardAtTouchedPoint, false); 252375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka 253375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka mGestureFloatingPreviewTextLingerTimeout = mainKeyboardViewAttr.getInt( 254375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka R.styleable.MainKeyboardView_gestureFloatingPreviewTextLingerTimeout, 0); 255fb523d7f5d40123a49a9128c455815db320c90fcTadashi G. Takaoka 256cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka mGestureFloatingTextDrawingPreview = new GestureFloatingTextDrawingPreview( 257cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka mDrawingPreviewPlacerView, mainKeyboardViewAttr); 258cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka mDrawingPreviewPlacerView.addPreview(mGestureFloatingTextDrawingPreview); 259fb523d7f5d40123a49a9128c455815db320c90fcTadashi G. Takaoka 260cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka mGestureTrailsDrawingPreview = new GestureTrailsDrawingPreview( 261cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka mDrawingPreviewPlacerView, mainKeyboardViewAttr); 262cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka mDrawingPreviewPlacerView.addPreview(mGestureTrailsDrawingPreview); 263fb523d7f5d40123a49a9128c455815db320c90fcTadashi G. Takaoka 264cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka mSlidingKeyInputDrawingPreview = new SlidingKeyInputDrawingPreview( 265cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka mDrawingPreviewPlacerView, mainKeyboardViewAttr); 266cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka mDrawingPreviewPlacerView.addPreview(mSlidingKeyInputDrawingPreview); 267d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka mainKeyboardViewAttr.recycle(); 268160f01211d169d64102205e80e9ac8d46c7d674bTadashi G. Takaoka 269a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka mMoreKeysKeyboardContainer = LayoutInflater.from(getContext()) 270a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka .inflate(moreKeysKeyboardLayoutId, null); 27131c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka mLanguageOnSpacebarFadeoutAnimator = loadObjectAnimator( 27231c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka languageOnSpacebarFadeoutAnimatorResId, this); 27331c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka mAltCodeKeyWhileTypingFadeoutAnimator = loadObjectAnimator( 27431c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka altCodeKeyWhileTypingFadeoutAnimatorResId, this); 27531c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka mAltCodeKeyWhileTypingFadeinAnimator = loadObjectAnimator( 27631c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka altCodeKeyWhileTypingFadeinAnimatorResId, this); 277f87e8f7ec1efb93398d909c67468d716b0248fe7Tadashi G. Takaoka 278f87e8f7ec1efb93398d909c67468d716b0248fe7Tadashi G. Takaoka mKeyboardActionListener = KeyboardActionListener.EMPTY_LISTENER; 279741831d32295acfb7675d7e0781a634d78868c63Satoshi Kataoka 2802fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa mLanguageOnSpacebarHorizontalMargin = (int)getResources().getDimension( 2812fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa R.dimen.config_language_on_spacebar_horizontal_margin); 28231c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka } 28331c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka 28452876bbefd774e8647910f73a2e4c17ac4e6bf5cKen Wakasa @Override 28552876bbefd774e8647910f73a2e4c17ac4e6bf5cKen Wakasa public void setHardwareAcceleratedDrawingEnabled(final boolean enabled) { 28652876bbefd774e8647910f73a2e4c17ac4e6bf5cKen Wakasa super.setHardwareAcceleratedDrawingEnabled(enabled); 287cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka mDrawingPreviewPlacerView.setHardwareAcceleratedDrawingEnabled(enabled); 28852876bbefd774e8647910f73a2e4c17ac4e6bf5cKen Wakasa } 28952876bbefd774e8647910f73a2e4c17ac4e6bf5cKen Wakasa 290dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka private ObjectAnimator loadObjectAnimator(final int resId, final Object target) { 29120dd1bc090abdd3e88855fe54b1865949aa1168dTadashi G. Takaoka if (resId == 0) { 29257372fd3da2e879f190e4ccd41a00813774c9019Tadashi G. Takaoka // TODO: Stop returning null. 29320dd1bc090abdd3e88855fe54b1865949aa1168dTadashi G. Takaoka return null; 29420dd1bc090abdd3e88855fe54b1865949aa1168dTadashi G. Takaoka } 29531c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka final ObjectAnimator animator = (ObjectAnimator)AnimatorInflater.loadAnimator( 29631c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka getContext(), resId); 297d7c4ba170982ddce5ac12ea92c3c3d8b53d524baTadashi G. Takaoka if (animator != null) { 29831c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka animator.setTarget(target); 29973a46bfeb7a109b49be196e5d679e44c9e66a2e8Tadashi G. Takaoka } 30031c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka return animator; 30131c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka } 30273a46bfeb7a109b49be196e5d679e44c9e66a2e8Tadashi G. Takaoka 3032fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa private static void cancelAndStartAnimators(final ObjectAnimator animatorToCancel, 3042fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa final ObjectAnimator animatorToStart) { 3052fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa if (animatorToCancel == null || animatorToStart == null) { 3062fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa // TODO: Stop using null as a no-operation animator. 3072fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa return; 3082fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa } 3092fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa float startFraction = 0.0f; 3102fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa if (animatorToCancel.isStarted()) { 3112fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa animatorToCancel.cancel(); 3122fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa startFraction = 1.0f - animatorToCancel.getAnimatedFraction(); 3132fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa } 3142fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa final long startTime = (long)(animatorToStart.getDuration() * startFraction); 3152fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa animatorToStart.start(); 3162fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa animatorToStart.setCurrentPlayTime(startTime); 3172fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa } 3182fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa 3192fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa // Implements {@link TimerHander.Callbacks} method. 3202fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa @Override 3212fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa public void startWhileTypingFadeinAnimation() { 3222fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa cancelAndStartAnimators( 3232fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa mAltCodeKeyWhileTypingFadeoutAnimator, mAltCodeKeyWhileTypingFadeinAnimator); 3242fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa } 3252fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa 3262fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa @Override 3272fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa public void startWhileTypingFadeoutAnimation() { 3282fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa cancelAndStartAnimators( 3292fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa mAltCodeKeyWhileTypingFadeinAnimator, mAltCodeKeyWhileTypingFadeoutAnimator); 3302fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa } 3312fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa 33215f6d4ae34664ea3d92827a2c3003198c0bac70bTadashi G. Takaoka @ExternallyReferenced 33331c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka public int getLanguageOnSpacebarAnimAlpha() { 33431c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka return mLanguageOnSpacebarAnimAlpha; 335d7c4ba170982ddce5ac12ea92c3c3d8b53d524baTadashi G. Takaoka } 336d7c4ba170982ddce5ac12ea92c3c3d8b53d524baTadashi G. Takaoka 33715f6d4ae34664ea3d92827a2c3003198c0bac70bTadashi G. Takaoka @ExternallyReferenced 338dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka public void setLanguageOnSpacebarAnimAlpha(final int alpha) { 33931c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka mLanguageOnSpacebarAnimAlpha = alpha; 34031c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka invalidateKey(mSpaceKey); 34131c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka } 34231c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka 34315f6d4ae34664ea3d92827a2c3003198c0bac70bTadashi G. Takaoka @ExternallyReferenced 34431c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka public int getAltCodeKeyWhileTypingAnimAlpha() { 34531c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka return mAltCodeKeyWhileTypingAnimAlpha; 34631c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka } 34731c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka 34815f6d4ae34664ea3d92827a2c3003198c0bac70bTadashi G. Takaoka @ExternallyReferenced 349dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka public void setAltCodeKeyWhileTypingAnimAlpha(final int alpha) { 3505141f04ef3b213fbe4816168d1c42f30449fc446Tadashi G. Takaoka if (mAltCodeKeyWhileTypingAnimAlpha == alpha) { 3515141f04ef3b213fbe4816168d1c42f30449fc446Tadashi G. Takaoka return; 3525141f04ef3b213fbe4816168d1c42f30449fc446Tadashi G. Takaoka } 3535141f04ef3b213fbe4816168d1c42f30449fc446Tadashi G. Takaoka // Update the visual of alt-code-key-while-typing. 35431c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka mAltCodeKeyWhileTypingAnimAlpha = alpha; 3555141f04ef3b213fbe4816168d1c42f30449fc446Tadashi G. Takaoka final Keyboard keyboard = getKeyboard(); 3565141f04ef3b213fbe4816168d1c42f30449fc446Tadashi G. Takaoka if (keyboard == null) { 3575141f04ef3b213fbe4816168d1c42f30449fc446Tadashi G. Takaoka return; 3585141f04ef3b213fbe4816168d1c42f30449fc446Tadashi G. Takaoka } 3595141f04ef3b213fbe4816168d1c42f30449fc446Tadashi G. Takaoka for (final Key key : keyboard.mAltCodeKeysWhileTyping) { 3605141f04ef3b213fbe4816168d1c42f30449fc446Tadashi G. Takaoka invalidateKey(key); 3615141f04ef3b213fbe4816168d1c42f30449fc446Tadashi G. Takaoka } 3625f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka } 3635f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka 364dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka public void setKeyboardActionListener(final KeyboardActionListener listener) { 3655f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka mKeyboardActionListener = listener; 3665c73ed628b22fdfa59585803ee86e383c579a7d4Tadashi G. Takaoka PointerTracker.setKeyboardActionListener(listener); 3675f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka } 3685f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka 3692fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa // TODO: We should reconsider which coordinate system should be used to represent keyboard 3702fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa // event. 3712fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa public int getKeyX(final int x) { 3722fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa return Constants.isValidCoordinate(x) ? mKeyDetector.getTouchX(x) : x; 3735f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka } 3745f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka 3752fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa // TODO: We should reconsider which coordinate system should be used to represent keyboard 3762fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa // event. 3772fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa public int getKeyY(final int y) { 3782fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa return Constants.isValidCoordinate(y) ? mKeyDetector.getTouchY(y) : y; 3790efe174ea43fe576683102effbaef5be27575706Tadashi G. Takaoka } 3800efe174ea43fe576683102effbaef5be27575706Tadashi G. Takaoka 3815f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka /** 3825f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka * Attaches a keyboard to this view. The keyboard can be switched at any time and the 3835f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka * view will re-layout itself to accommodate the keyboard. 3845f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka * @see Keyboard 3855f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka * @see #getKeyboard() 3865f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka * @param keyboard the keyboard to display in this view 3875f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka */ 3885f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka @Override 389dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka public void setKeyboard(final Keyboard keyboard) { 3905cbda70956af14453fca7395d892c59aabbd8fd3Jean Chalard // Remove any pending messages, except dismissing preview and key repeat. 3915cbda70956af14453fca7395d892c59aabbd8fd3Jean Chalard mKeyTimerHandler.cancelLongPressTimers(); 3925f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka super.setKeyboard(keyboard); 3935a7a696aff6718d4e0250c394a9d01cbf2a16916Tadashi G. Takaoka mKeyDetector.setKeyboard( 39408ae0d5ca03ed455827e82222df249d1cafb5d71Tadashi G. Takaoka keyboard, -getPaddingLeft(), -getPaddingTop() + getVerticalCorrection()); 3958335c59ea7715f3dbc6625f128a7a038f314a89fTadashi G. Takaoka PointerTracker.setKeyDetector(mKeyDetector); 396a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka mMoreKeysKeyboardCache.clear(); 3974112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka 398240871ecafde7834ebb4270cd7758fc904a5f3a7Tadashi G. Takaoka mSpaceKey = keyboard.getKey(Constants.CODE_SPACE); 3992fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa mSpacebarIcon = (mSpaceKey != null) 4004daf32b6c0358f0273a99b622a259ecdf6b44fa4Tom Ouyang ? mSpaceKey.getIcon(keyboard.mIconsSet, Constants.Color.ALPHA_OPAQUE) : null; 4014112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap; 4022fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa mLanguageOnSpacebarTextSize = keyHeight * mLanguageOnSpacebarTextRatio; 4039c3860ce461c3791891bf667edc77fe798c8d332Ken Wakasa if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { 40415c42454c0117d869f31ce278021f53ec74c4aa2Tadashi G. Takaoka final int orientation = getContext().getResources().getConfiguration().orientation; 40515c42454c0117d869f31ce278021f53ec74c4aa2Tadashi G. Takaoka ResearchLogger.mainKeyboardView_setKeyboard(keyboard, orientation); 40648a7681e064ae259b840f0e757da2d716043d893Kurt Partridge } 407f147794fd41491a3383e6aca6d49007f58124068alanv 408f147794fd41491a3383e6aca6d49007f58124068alanv // This always needs to be set since the accessibility state can 409f147794fd41491a3383e6aca6d49007f58124068alanv // potentially change without the keyboard being set again. 410b6ca354431367b625daf9fff5fbe4b1f5ef996abKen Wakasa AccessibleKeyboardViewProxy.getInstance().setKeyboard(); 4115f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka } 4125f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka 4130e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka /** 4140e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka * Enables or disables the key feedback popup. This is a popup that shows a magnified 4150e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka * version of the depressed key. By default the preview is enabled. 4160e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka * @param previewEnabled whether or not to enable the key feedback preview 4170e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka * @param delay the delay after which the preview is dismissed 4180e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka * @see #isKeyPreviewPopupEnabled() 4190e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka */ 4200e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka public void setKeyPreviewPopupEnabled(final boolean previewEnabled, final int delay) { 4217d09b5681202d3df9df1d5634071091f3f45fbe5Tadashi G. Takaoka mKeyPreviewDrawParams.setPopupEnabled(previewEnabled, delay); 4220e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka } 4230e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka 424375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka private void locatePreviewPlacerView() { 425cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka if (mDrawingPreviewPlacerView.getParent() != null) { 426375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka return; 427375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka } 428375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka final int width = getWidth(); 429375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka final int height = getHeight(); 430375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka if (width == 0 || height == 0) { 431375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka // In transient state. 432375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka return; 433375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka } 434375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka getLocationInWindow(mOriginCoords); 435375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka final DisplayMetrics dm = getResources().getDisplayMetrics(); 436375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka if (CoordinateUtils.y(mOriginCoords) < dm.heightPixels / 4) { 437375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka // In transient state. 438375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka return; 439375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka } 440375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka final View rootView = getRootView(); 441375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka if (rootView == null) { 442375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka Log.w(TAG, "Cannot find root view"); 443375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka return; 444375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka } 445375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka final ViewGroup windowContentView = (ViewGroup)rootView.findViewById(android.R.id.content); 446375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka // Note: It'd be very weird if we get null by android.R.id.content. 447375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka if (windowContentView == null) { 448cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka Log.w(TAG, "Cannot find android.R.id.content view to add DrawingPreviewPlacerView"); 449375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka } else { 450cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka windowContentView.addView(mDrawingPreviewPlacerView); 451cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka mDrawingPreviewPlacerView.setKeyboardViewGeometry(mOriginCoords, width, height); 452375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka } 453375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka } 454375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka 4550e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka /** 4560e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka * Returns the enabled state of the key feedback preview 4570e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka * @return whether or not the key feedback preview is enabled 4580e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka * @see #setKeyPreviewPopupEnabled(boolean, int) 4590e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka */ 4600e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka public boolean isKeyPreviewPopupEnabled() { 4617d09b5681202d3df9df1d5634071091f3f45fbe5Tadashi G. Takaoka return mKeyPreviewDrawParams.isPopupEnabled(); 4620e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka } 4630e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka 4642fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa // Implements {@link DrawingHandler.Callbacks} method. 4652fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa @Override 4662fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa public void dismissAllKeyPreviews() { 467bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka mKeyPreviewChoreographer.dismissAllKeyPreviews(); 468375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka PointerTracker.setReleasedKeyGraphicsToAllKeys(); 469375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka } 470375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka 4710e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka @Override 4722fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa public void showKeyPreview(final Key key) { 4730e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka // If key is invalid or IME is already closed, we must not show key preview. 4740e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka // Trying to show key preview while root window is closed causes 4750e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka // WindowManager.BadTokenException. 4760e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka if (key == null) { 4770e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka return; 4780e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka } 4790e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka 4802fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa final KeyPreviewDrawParams previewParams = mKeyPreviewDrawParams; 4812fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa final Keyboard keyboard = getKeyboard(); 4827d09b5681202d3df9df1d5634071091f3f45fbe5Tadashi G. Takaoka if (!previewParams.isPopupEnabled()) { 483992c5219092ccafe66363451fbf4ca7c5a43fb20Tadashi G. Takaoka previewParams.setVisibleOffset(-keyboard.mVerticalGap); 4842fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa return; 4852fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa } 4862fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa 487bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka locatePreviewPlacerView(); 488bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka final TextView previewTextView = mKeyPreviewChoreographer.getKeyPreviewTextView( 489bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka key, mDrawingPreviewPlacerView); 4900e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka getLocationInWindow(mOriginCoords); 491bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka mKeyPreviewChoreographer.placeKeyPreview(key, previewTextView, keyboard.mIconsSet, 492bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka mKeyDrawParams, getWidth(), mOriginCoords); 493bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka mKeyPreviewChoreographer.showKeyPreview(key, previewTextView, isHardwareAccelerated()); 4942fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa } 4952fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa 4962fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa // Implements {@link TimerHandler.Callbacks} method. 4970e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka @Override 4982fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa public void dismissKeyPreviewWithoutDelay(final Key key) { 499bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka mKeyPreviewChoreographer.dismissKeyPreview(key, false /* withAnimation */); 5002fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa // To redraw key top letter. 5012fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa invalidateKey(key); 5022fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa } 5032fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa 5042fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa @Override 5052fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa public void dismissKeyPreview(final Key key) { 5062fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa if (!isHardwareAccelerated()) { 5072fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa // TODO: Implement preference option to control key preview method and duration. 5087d09b5681202d3df9df1d5634071091f3f45fbe5Tadashi G. Takaoka mDrawingHandler.dismissKeyPreview(mKeyPreviewDrawParams.getLingerTimeout(), key); 5092fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa return; 5102fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa } 511bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka mKeyPreviewChoreographer.dismissKeyPreview(key, true /* withAnimation */); 5120e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka } 5130e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka 514ff961ddf8c58df569c97684bfd83a01b2a9470aaTadashi G. Takaoka public void setSlidingKeyInputPreviewEnabled(final boolean enabled) { 515cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka mSlidingKeyInputDrawingPreview.setPreviewEnabled(enabled); 516ff961ddf8c58df569c97684bfd83a01b2a9470aaTadashi G. Takaoka } 517ff961ddf8c58df569c97684bfd83a01b2a9470aaTadashi G. Takaoka 5180e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka @Override 5190e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka public void showSlidingKeyInputPreview(final PointerTracker tracker) { 5200e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka locatePreviewPlacerView(); 521cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka mSlidingKeyInputDrawingPreview.setPreviewPosition(tracker); 5220e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka } 5230e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka 5240e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka @Override 5250e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka public void dismissSlidingKeyInputPreview() { 526cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka mSlidingKeyInputDrawingPreview.dismissSlidingKeyInputPreview(); 5270e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka } 5280e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka 529724db044957eb3544323c9814cbb4f20e81b8594Ken Wakasa private void setGesturePreviewMode(final boolean isGestureTrailEnabled, 530724db044957eb3544323c9814cbb4f20e81b8594Ken Wakasa final boolean isGestureFloatingPreviewTextEnabled) { 531cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka mGestureFloatingTextDrawingPreview.setPreviewEnabled(isGestureFloatingPreviewTextEnabled); 532cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka mGestureTrailsDrawingPreview.setPreviewEnabled(isGestureTrailEnabled); 533375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka } 534375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka 5352fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa // Implements {@link DrawingHandler.Callbacks} method. 5362fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa @Override 537375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka public void showGestureFloatingPreviewText(final SuggestedWords suggestedWords) { 538375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka locatePreviewPlacerView(); 539cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka mGestureFloatingTextDrawingPreview.setSuggetedWords(suggestedWords); 540375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka } 541375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka 542375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka public void dismissGestureFloatingPreviewText() { 543375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka locatePreviewPlacerView(); 544375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka mDrawingHandler.dismissGestureFloatingPreviewText(mGestureFloatingPreviewTextLingerTimeout); 545375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka } 546375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka 547fb523d7f5d40123a49a9128c455815db320c90fcTadashi G. Takaoka @Override 548212165b0b8308802a461a6a526d367ba67b5567aTadashi G. Takaoka public void showGestureTrail(final PointerTracker tracker, 549212165b0b8308802a461a6a526d367ba67b5567aTadashi G. Takaoka final boolean showsFloatingPreviewText) { 550375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka locatePreviewPlacerView(); 551212165b0b8308802a461a6a526d367ba67b5567aTadashi G. Takaoka if (showsFloatingPreviewText) { 552cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka mGestureFloatingTextDrawingPreview.setPreviewPosition(tracker); 553212165b0b8308802a461a6a526d367ba67b5567aTadashi G. Takaoka } 554cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka mGestureTrailsDrawingPreview.setPreviewPosition(tracker); 555375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka } 556375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka 5578335c59ea7715f3dbc6625f128a7a038f314a89fTadashi G. Takaoka // Note that this method is called from a non-UI thread. 558dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka public void setMainDictionaryAvailability(final boolean mainDictionaryAvailable) { 5598335c59ea7715f3dbc6625f128a7a038f314a89fTadashi G. Takaoka PointerTracker.setMainDictionaryAvailability(mainDictionaryAvailable); 5608335c59ea7715f3dbc6625f128a7a038f314a89fTadashi G. Takaoka } 5618335c59ea7715f3dbc6625f128a7a038f314a89fTadashi G. Takaoka 562724db044957eb3544323c9814cbb4f20e81b8594Ken Wakasa public void setGestureHandlingEnabledByUser(final boolean isGestureHandlingEnabledByUser, 563724db044957eb3544323c9814cbb4f20e81b8594Ken Wakasa final boolean isGestureTrailEnabled, 564724db044957eb3544323c9814cbb4f20e81b8594Ken Wakasa final boolean isGestureFloatingPreviewTextEnabled) { 565724db044957eb3544323c9814cbb4f20e81b8594Ken Wakasa PointerTracker.setGestureHandlingEnabledByUser(isGestureHandlingEnabledByUser); 566724db044957eb3544323c9814cbb4f20e81b8594Ken Wakasa setGesturePreviewMode(isGestureHandlingEnabledByUser && isGestureTrailEnabled, 567724db044957eb3544323c9814cbb4f20e81b8594Ken Wakasa isGestureHandlingEnabledByUser && isGestureFloatingPreviewTextEnabled); 5680657b9698a110f8e895448d829478982ce37b6d1Tadashi G. Takaoka } 5690657b9698a110f8e895448d829478982ce37b6d1Tadashi G. Takaoka 5705f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka @Override 5714331012a9e7779ff7c8359a443dc5815ee6ea8d9Kurt Partridge protected void onAttachedToWindow() { 5724331012a9e7779ff7c8359a443dc5815ee6ea8d9Kurt Partridge super.onAttachedToWindow(); 5739c3860ce461c3791891bf667edc77fe798c8d332Ken Wakasa // Notify the ResearchLogger (development only diagnostics) that the keyboard view has 5749c3860ce461c3791891bf667edc77fe798c8d332Ken Wakasa // been attached. This is needed to properly show the splash screen, which requires that 5759c3860ce461c3791891bf667edc77fe798c8d332Ken Wakasa // the window token of the KeyboardView be non-null. 5769c3860ce461c3791891bf667edc77fe798c8d332Ken Wakasa if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { 577c3f78c9057a5710898feaf8027659484477e5821Tadashi G. Takaoka ResearchLogger.getInstance().mainKeyboardView_onAttachedToWindow(this); 578c3f78c9057a5710898feaf8027659484477e5821Tadashi G. Takaoka } 579c3f78c9057a5710898feaf8027659484477e5821Tadashi G. Takaoka } 580c3f78c9057a5710898feaf8027659484477e5821Tadashi G. Takaoka 581c3f78c9057a5710898feaf8027659484477e5821Tadashi G. Takaoka @Override 582c3f78c9057a5710898feaf8027659484477e5821Tadashi G. Takaoka protected void onDetachedFromWindow() { 583c3f78c9057a5710898feaf8027659484477e5821Tadashi G. Takaoka super.onDetachedFromWindow(); 584cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka mDrawingPreviewPlacerView.removeAllViews(); 5859c3860ce461c3791891bf667edc77fe798c8d332Ken Wakasa // Notify the ResearchLogger (development only diagnostics) that the keyboard view has 5869c3860ce461c3791891bf667edc77fe798c8d332Ken Wakasa // been detached. This is needed to invalidate the reference of {@link MainKeyboardView} 5879c3860ce461c3791891bf667edc77fe798c8d332Ken Wakasa // to null. 5889c3860ce461c3791891bf667edc77fe798c8d332Ken Wakasa if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { 589c3f78c9057a5710898feaf8027659484477e5821Tadashi G. Takaoka ResearchLogger.getInstance().mainKeyboardView_onDetachedFromWindow(); 5904331012a9e7779ff7c8359a443dc5815ee6ea8d9Kurt Partridge } 5914331012a9e7779ff7c8359a443dc5815ee6ea8d9Kurt Partridge } 5924331012a9e7779ff7c8359a443dc5815ee6ea8d9Kurt Partridge 593a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka private MoreKeysPanel onCreateMoreKeysPanel(final Key key, final Context context) { 5947dc60f9db729e93cb591492574a436418c553ebfTadashi G. Takaoka if (key.getMoreKeys() == null) { 5955f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka return null; 59620dd1bc090abdd3e88855fe54b1865949aa1168dTadashi G. Takaoka } 597a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka Keyboard moreKeysKeyboard = mMoreKeysKeyboardCache.get(key); 598a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka if (moreKeysKeyboard == null) { 599a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka moreKeysKeyboard = new MoreKeysKeyboard.Builder( 600a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka context, key, this, mKeyPreviewDrawParams).build(); 601a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka mMoreKeysKeyboardCache.put(key, moreKeysKeyboard); 60220dd1bc090abdd3e88855fe54b1865949aa1168dTadashi G. Takaoka } 6035f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka 604a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka final View container = mMoreKeysKeyboardContainer; 6052affaf91a04d63e0994102299816014a8bbe11e1Tadashi G. Takaoka final MoreKeysKeyboardView moreKeysKeyboardView = 6062affaf91a04d63e0994102299816014a8bbe11e1Tadashi G. Takaoka (MoreKeysKeyboardView)container.findViewById(R.id.more_keys_keyboard_view); 6072affaf91a04d63e0994102299816014a8bbe11e1Tadashi G. Takaoka moreKeysKeyboardView.setKeyboard(moreKeysKeyboard); 608b8dc67466339dc14653ad634c86851025373326bTadashi G. Takaoka container.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); 6092affaf91a04d63e0994102299816014a8bbe11e1Tadashi G. Takaoka return moreKeysKeyboardView; 6105f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka } 6115f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka 6122fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa // Implements {@link TimerHandler.Callbacks} method. 6135f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka /** 614d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka * Called when a key is long pressed. 6155f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka * @param tracker the pointer tracker which pressed the parent key 6165f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka */ 6172fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa @Override 6182fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa public void onLongPress(final PointerTracker tracker) { 619a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka if (isShowingMoreKeysPanel()) { 62096efb1252a0bf84ac72ef3d438ea3b3d5ac8ddd7Tadashi G. Takaoka return; 621a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka } 622a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka final Key key = tracker.getKey(); 623a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka if (key == null) { 62496efb1252a0bf84ac72ef3d438ea3b3d5ac8ddd7Tadashi G. Takaoka return; 625a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka } 6269c3860ce461c3791891bf667edc77fe798c8d332Ken Wakasa if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { 627c8e45ddb032554f4e9d4411d8ef47d98db62d77bTadashi G. Takaoka ResearchLogger.mainKeyboardView_onLongPress(); 6289bc29d78a6ce83f77869aa63748176241e29d43cKurt Partridge } 629f87e8f7ec1efb93398d909c67468d716b0248fe7Tadashi G. Takaoka final KeyboardActionListener listener = mKeyboardActionListener; 6309552badf3c24d2098d227b0ddca0721b928a10b1Tadashi G. Takaoka if (key.hasNoPanelAutoMoreKey()) { 6317dc60f9db729e93cb591492574a436418c553ebfTadashi G. Takaoka final int moreKeyCode = key.getMoreKeys()[0].mCode; 6323708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka tracker.onLongPressed(); 633ab16237e69061bb0aa7f882e48e5d93459c22ef3Tadashi G. Takaoka listener.onPressKey(moreKeyCode, 0 /* repeatCount */, true /* isSinglePointer */); 634f87e8f7ec1efb93398d909c67468d716b0248fe7Tadashi G. Takaoka listener.onCodeInput(moreKeyCode, 635f87e8f7ec1efb93398d909c67468d716b0248fe7Tadashi G. Takaoka Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE); 636f87e8f7ec1efb93398d909c67468d716b0248fe7Tadashi G. Takaoka listener.onReleaseKey(moreKeyCode, false /* withSliding */); 63796efb1252a0bf84ac72ef3d438ea3b3d5ac8ddd7Tadashi G. Takaoka return; 6383708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka } 6397dc60f9db729e93cb591492574a436418c553ebfTadashi G. Takaoka final int code = key.getCode(); 640a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka if (code == Constants.CODE_SPACE || code == Constants.CODE_LANGUAGE_SWITCH) { 6413708787fe91227083d2a1874fa41493d3bc9fe10Tadashi G. Takaoka // Long pressing the space key invokes IME switcher dialog. 642f87e8f7ec1efb93398d909c67468d716b0248fe7Tadashi G. Takaoka if (listener.onCustomRequest(Constants.CUSTOM_CODE_SHOW_INPUT_METHOD_PICKER)) { 6436dde878d515f7bf5268d16a8fe4921d8821c5ae7Tadashi G. Takaoka tracker.onLongPressed(); 644f87e8f7ec1efb93398d909c67468d716b0248fe7Tadashi G. Takaoka listener.onReleaseKey(code, false /* withSliding */); 64596efb1252a0bf84ac72ef3d438ea3b3d5ac8ddd7Tadashi G. Takaoka return; 6466dde878d515f7bf5268d16a8fe4921d8821c5ae7Tadashi G. Takaoka } 6476dde878d515f7bf5268d16a8fe4921d8821c5ae7Tadashi G. Takaoka } 64896efb1252a0bf84ac72ef3d438ea3b3d5ac8ddd7Tadashi G. Takaoka openMoreKeysPanel(key, tracker); 6496dde878d515f7bf5268d16a8fe4921d8821c5ae7Tadashi G. Takaoka } 6506dde878d515f7bf5268d16a8fe4921d8821c5ae7Tadashi G. Takaoka 65196efb1252a0bf84ac72ef3d438ea3b3d5ac8ddd7Tadashi G. Takaoka private void openMoreKeysPanel(final Key key, final PointerTracker tracker) { 652a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka final MoreKeysPanel moreKeysPanel = onCreateMoreKeysPanel(key, getContext()); 6539d5601e9013c5ec9a7ac75db16f4a0a8218b02bfTadashi G. Takaoka if (moreKeysPanel == null) { 65496efb1252a0bf84ac72ef3d438ea3b3d5ac8ddd7Tadashi G. Takaoka return; 6555f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka } 65663c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka 657547b638194c05f971003edb06c3c6c489a76da5fTadashi G. Takaoka final int[] lastCoords = CoordinateUtils.newInstance(); 658547b638194c05f971003edb06c3c6c489a76da5fTadashi G. Takaoka tracker.getLastCoordinates(lastCoords); 659a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka final boolean keyPreviewEnabled = isKeyPreviewPopupEnabled() && !key.noKeyPreview(); 6607ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka // The more keys keyboard is usually horizontally aligned with the center of the parent key. 6617ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka // If showMoreKeysKeyboardAtTouchedPoint is true and the key preview is disabled, the more 6627ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka // keys keyboard is placed at the touch point of the parent key. 6637ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka final int pointX = (mConfigShowMoreKeysKeyboardAtTouchedPoint && !keyPreviewEnabled) 664547b638194c05f971003edb06c3c6c489a76da5fTadashi G. Takaoka ? CoordinateUtils.x(lastCoords) 6657dc60f9db729e93cb591492574a436418c553ebfTadashi G. Takaoka : key.getX() + key.getWidth() / 2; 6667ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka // The more keys keyboard is usually vertically aligned with the top edge of the parent key 6677ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka // (plus vertical gap). If the key preview is enabled, the more keys keyboard is vertically 6687ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka // aligned with the bottom edge of the visible part of the key preview. 66929d5973fd35438a83acf7f44b5d55d5620278ee3Tadashi G. Takaoka // {@code mPreviewVisibleOffset} has been set appropriately in 67029d5973fd35438a83acf7f44b5d55d5620278ee3Tadashi G. Takaoka // {@link KeyboardView#showKeyPreview(PointerTracker)}. 671992c5219092ccafe66363451fbf4ca7c5a43fb20Tadashi G. Takaoka final int pointY = key.getY() + mKeyPreviewDrawParams.getVisibleOffset(); 672fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang moreKeysPanel.showMoreKeysPanel(this, this, pointX, pointY, mKeyboardActionListener); 67333482a9b9ccf605c63fab7c9b8273a240bbc2035Tadashi G. Takaoka tracker.onShowMoreKeysPanel(moreKeysPanel); 6742fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa // TODO: Implement zoom in animation of more keys panel. 6752fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa dismissKeyPreviewWithoutDelay(key); 6765f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka } 6775f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka 6782fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa public boolean isInDraggingFinger() { 679a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka if (isShowingMoreKeysPanel()) { 68063c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka return true; 6815f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka } 6822fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa return PointerTracker.isAnyInDraggingFinger(); 6835f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka } 6845f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka 685d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka @Override 686d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka public void onShowMoreKeysPanel(final MoreKeysPanel panel) { 6871b6eea89037158a1e271730eacdacb8b6e550d3aTadashi G. Takaoka locatePreviewPlacerView(); 688cf915ddc878699909365dd599a0e154552e244e2Tadashi G. Takaoka panel.showInParent(mDrawingPreviewPlacerView); 689d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka mMoreKeysPanel = panel; 690a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka dimEntireKeyboard(true /* dimmed */); 691d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka } 692d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka 693d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka public boolean isShowingMoreKeysPanel() { 694a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka return mMoreKeysPanel != null && mMoreKeysPanel.isShowingInParent(); 695d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka } 696d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka 697d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka @Override 6980e08d70fe52737582b6c83dbf48aaf4d83063566Tadashi G. Takaoka public void onCancelMoreKeysPanel(final MoreKeysPanel panel) { 699d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka PointerTracker.dismissAllMoreKeysPanels(); 700d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka } 701d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka 702d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka @Override 7030e08d70fe52737582b6c83dbf48aaf4d83063566Tadashi G. Takaoka public void onDismissMoreKeysPanel(final MoreKeysPanel panel) { 704d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka dimEntireKeyboard(false /* dimmed */); 705d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka if (isShowingMoreKeysPanel()) { 7067f8345d59a82a9b1d458b8e55ffd12c2a0d466a7Tadashi G. Takaoka mMoreKeysPanel.removeFromParent(); 707d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka mMoreKeysPanel = null; 708d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka } 709d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka } 710d9449ccf3ce9e5eabb022aed6a45bba680bce115Tadashi G. Takaoka 7115433ce64c0f141bc4ee82912844f47f575654af5Tadashi G. Takaoka public void startDoubleTapShiftKeyTimer() { 7125433ce64c0f141bc4ee82912844f47f575654af5Tadashi G. Takaoka mKeyTimerHandler.startDoubleTapShiftKeyTimer(); 7135433ce64c0f141bc4ee82912844f47f575654af5Tadashi G. Takaoka } 7145433ce64c0f141bc4ee82912844f47f575654af5Tadashi G. Takaoka 7155433ce64c0f141bc4ee82912844f47f575654af5Tadashi G. Takaoka public void cancelDoubleTapShiftKeyTimer() { 7165433ce64c0f141bc4ee82912844f47f575654af5Tadashi G. Takaoka mKeyTimerHandler.cancelDoubleTapShiftKeyTimer(); 7175433ce64c0f141bc4ee82912844f47f575654af5Tadashi G. Takaoka } 7185433ce64c0f141bc4ee82912844f47f575654af5Tadashi G. Takaoka 7195433ce64c0f141bc4ee82912844f47f575654af5Tadashi G. Takaoka public boolean isInDoubleTapShiftKeyTimeout() { 7205433ce64c0f141bc4ee82912844f47f575654af5Tadashi G. Takaoka return mKeyTimerHandler.isInDoubleTapShiftKeyTimeout(); 7215433ce64c0f141bc4ee82912844f47f575654af5Tadashi G. Takaoka } 7225433ce64c0f141bc4ee82912844f47f575654af5Tadashi G. Takaoka 7235f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka @Override 724dc2ee7772402633817702e95c2a5b17f6dec03ebalanv public boolean dispatchTouchEvent(MotionEvent event) { 725dc2ee7772402633817702e95c2a5b17f6dec03ebalanv if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()) { 726dc2ee7772402633817702e95c2a5b17f6dec03ebalanv return AccessibleKeyboardViewProxy.getInstance().dispatchTouchEvent(event); 727dc2ee7772402633817702e95c2a5b17f6dec03ebalanv } 728dc2ee7772402633817702e95c2a5b17f6dec03ebalanv return super.dispatchTouchEvent(event); 729dc2ee7772402633817702e95c2a5b17f6dec03ebalanv } 730dc2ee7772402633817702e95c2a5b17f6dec03ebalanv 731dc2ee7772402633817702e95c2a5b17f6dec03ebalanv @Override 732dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka public boolean onTouchEvent(final MotionEvent me) { 73346286874f30c4a6ef44646c4e4adf36fe55c74b9Tadashi G. Takaoka if (getKeyboard() == null) { 73446286874f30c4a6ef44646c4e4adf36fe55c74b9Tadashi G. Takaoka return false; 73546286874f30c4a6ef44646c4e4adf36fe55c74b9Tadashi G. Takaoka } 736b6cc3a85ab68cff2fae4c3858b48d9c5d7b45690Tadashi G. Takaoka if (mNonDistinctMultitouchHelper != null) { 737b6cc3a85ab68cff2fae4c3858b48d9c5d7b45690Tadashi G. Takaoka if (me.getPointerCount() > 1 && mKeyTimerHandler.isInKeyRepeat()) { 738b6cc3a85ab68cff2fae4c3858b48d9c5d7b45690Tadashi G. Takaoka // Key repeating timer will be canceled if 2 or more keys are in action. 7392fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa mKeyTimerHandler.cancelKeyRepeatTimers(); 740b6cc3a85ab68cff2fae4c3858b48d9c5d7b45690Tadashi G. Takaoka } 741b6cc3a85ab68cff2fae4c3858b48d9c5d7b45690Tadashi G. Takaoka // Non distinct multitouch screen support 7422fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa mNonDistinctMultitouchHelper.processMotionEvent(me, mKeyDetector); 743b6cc3a85ab68cff2fae4c3858b48d9c5d7b45690Tadashi G. Takaoka return true; 744b6cc3a85ab68cff2fae4c3858b48d9c5d7b45690Tadashi G. Takaoka } 745310ea9ab9058e922a562309cb0dc5d5e092000f1Tadashi G. Takaoka return processMotionEvent(me); 746c403a46f6d787b79768895272d53d296100677ddTadashi G. Takaoka } 747c403a46f6d787b79768895272d53d296100677ddTadashi G. Takaoka 748dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka public boolean processMotionEvent(final MotionEvent me) { 74930977a151e15e30f5385a349e92fb770b987435fTadashi G. Takaoka if (LatinImeLogger.sUsabilityStudy) { 75030977a151e15e30f5385a349e92fb770b987435fTadashi G. Takaoka UsabilityStudyLogUtils.writeMotionEvent(me); 751d05afa3f4c59641c8fabed034e457cb25f0c57f0Kurt Partridge } 752fca71cfddb7a5062e7a4fb512e1faab401c65cd3Tadashi G. Takaoka // Currently the same "move" event is being logged twice. 7539c3860ce461c3791891bf667edc77fe798c8d332Ken Wakasa if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { 75454dd1bed528331208f15df2693bcd01004dd471aTadashi G. Takaoka ResearchLogger.mainKeyboardView_processMotionEvent(me); 75515d4793911fa305e0a58aced925961e948582979satok } 7565f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka 757e08c418ff8b374244677960903cee8dd52a4d831Tadashi G. Takaoka final int index = me.getActionIndex(); 758e08c418ff8b374244677960903cee8dd52a4d831Tadashi G. Takaoka final int id = me.getPointerId(index); 7592fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa final PointerTracker tracker = PointerTracker.getPointerTracker(id); 7602fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa // When a more keys panel is showing, we should ignore other fingers' single touch events 7612fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa // other than the finger that is showing the more keys panel. 7622fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa if (isShowingMoreKeysPanel() && !tracker.isShowingMoreKeysPanel() 7632fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa && PointerTracker.getActivePointerTrackerCount() == 1) { 7642fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa return true; 7652fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa } 7662fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa tracker.processMotionEvent(me, mKeyDetector); 7675f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka return true; 7685f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka } 7695f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka 7705c095e59f679f726df1b6655fbbd73e310ac0decTadashi G. Takaoka public void cancelAllOngoingEvents() { 771375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka mKeyTimerHandler.cancelAllMessages(); 772375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka mDrawingHandler.cancelAllMessages(); 7735c095e59f679f726df1b6655fbbd73e310ac0decTadashi G. Takaoka dismissAllKeyPreviews(); 7745c095e59f679f726df1b6655fbbd73e310ac0decTadashi G. Takaoka dismissGestureFloatingPreviewText(); 7755c095e59f679f726df1b6655fbbd73e310ac0decTadashi G. Takaoka dismissSlidingKeyInputPreview(); 7765c095e59f679f726df1b6655fbbd73e310ac0decTadashi G. Takaoka PointerTracker.dismissAllMoreKeysPanels(); 7775c095e59f679f726df1b6655fbbd73e310ac0decTadashi G. Takaoka PointerTracker.cancelAllPointerTrackers(); 778375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka } 779375982106bf073971fccd14b2c65ec8e089bb2aeTadashi G. Takaoka 7805f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka public void closing() { 7815c095e59f679f726df1b6655fbbd73e310ac0decTadashi G. Takaoka cancelAllOngoingEvents(); 782a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka mMoreKeysKeyboardCache.clear(); 7835f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka } 7845f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka 785586a15c3f0d44590a5162e0ab4c3c52511f13f26Alan Viverette /** 786c6435f92a80c6664870f9d1a4bb2a1c5153ef2c3Tadashi G. Takaoka * Receives hover events from the input framework. 787586a15c3f0d44590a5162e0ab4c3c52511f13f26Alan Viverette * 788586a15c3f0d44590a5162e0ab4c3c52511f13f26Alan Viverette * @param event The motion event to be dispatched. 789586a15c3f0d44590a5162e0ab4c3c52511f13f26Alan Viverette * @return {@code true} if the event was handled by the view, {@code false} 790586a15c3f0d44590a5162e0ab4c3c52511f13f26Alan Viverette * otherwise 791586a15c3f0d44590a5162e0ab4c3c52511f13f26Alan Viverette */ 792c6435f92a80c6664870f9d1a4bb2a1c5153ef2c3Tadashi G. Takaoka @Override 793dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka public boolean dispatchHoverEvent(final MotionEvent event) { 7945f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()) { 7956a23b9e3d54031524445b1190cc1eba77916c5b3Tadashi G. Takaoka return AccessibleKeyboardViewProxy.getInstance().dispatchHoverEvent( 7966a23b9e3d54031524445b1190cc1eba77916c5b3Tadashi G. Takaoka event, mKeyDetector); 7975f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka } 7985f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka 799586a15c3f0d44590a5162e0ab4c3c52511f13f26Alan Viverette // Reflection doesn't support calling superclass methods. 8005f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka return false; 8015f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka } 80222b48de11ce6f31a0edf90e1308073e67a7a2adbTadashi G. Takaoka 803dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka public void updateShortcutKey(final boolean available) { 8047bd714c086a78e2058543b0971ac92f5a30b2362Tadashi G. Takaoka final Keyboard keyboard = getKeyboard(); 80520dd1bc090abdd3e88855fe54b1865949aa1168dTadashi G. Takaoka if (keyboard == null) { 80620dd1bc090abdd3e88855fe54b1865949aa1168dTadashi G. Takaoka return; 80720dd1bc090abdd3e88855fe54b1865949aa1168dTadashi G. Takaoka } 808240871ecafde7834ebb4270cd7758fc904a5f3a7Tadashi G. Takaoka final Key shortcutKey = keyboard.getKey(Constants.CODE_SHORTCUT); 80920dd1bc090abdd3e88855fe54b1865949aa1168dTadashi G. Takaoka if (shortcutKey == null) { 81020dd1bc090abdd3e88855fe54b1865949aa1168dTadashi G. Takaoka return; 81120dd1bc090abdd3e88855fe54b1865949aa1168dTadashi G. Takaoka } 8127bd714c086a78e2058543b0971ac92f5a30b2362Tadashi G. Takaoka shortcutKey.setEnabled(available); 8137bd714c086a78e2058543b0971ac92f5a30b2362Tadashi G. Takaoka invalidateKey(shortcutKey); 8145afc3ae2d9df0c2c93f2c66af13b128889ac3b5dTadashi G. Takaoka } 8155afc3ae2d9df0c2c93f2c66af13b128889ac3b5dTadashi G. Takaoka 816dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka public void startDisplayLanguageOnSpacebar(final boolean subtypeChanged, 817dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka final boolean needsToDisplayLanguage, final boolean hasMultipleEnabledIMEsOrSubtypes) { 8184112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka mNeedsToDisplayLanguage = needsToDisplayLanguage; 819fd60b2f97035382b14dce207b3613711982a613eTadashi G. Takaoka mHasMultipleEnabledIMEsOrSubtypes = hasMultipleEnabledIMEsOrSubtypes; 820fd60b2f97035382b14dce207b3613711982a613eTadashi G. Takaoka final ObjectAnimator animator = mLanguageOnSpacebarFadeoutAnimator; 821d7c4ba170982ddce5ac12ea92c3c3d8b53d524baTadashi G. Takaoka if (animator == null) { 822aee5f03d6ebf9cb03b52cbea003556f38745b4feTadashi G. Takaoka mNeedsToDisplayLanguage = false; 8234c0c638a189c1073b1fb6e43fe5fddb6f9932038Tadashi G. Takaoka } else { 824dabf96896ef4c304c6dad36b307a2a458a58209dTadashi G. Takaoka if (subtypeChanged && needsToDisplayLanguage) { 8254daf32b6c0358f0273a99b622a259ecdf6b44fa4Tom Ouyang setLanguageOnSpacebarAnimAlpha(Constants.Color.ALPHA_OPAQUE); 82631c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka if (animator.isStarted()) { 82731c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka animator.cancel(); 82831c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka } 829d7c4ba170982ddce5ac12ea92c3c3d8b53d524baTadashi G. Takaoka animator.start(); 830dabf96896ef4c304c6dad36b307a2a458a58209dTadashi G. Takaoka } else { 83131c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka if (!animator.isStarted()) { 83231c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka mLanguageOnSpacebarAnimAlpha = mLanguageOnSpacebarFinalAlpha; 83331c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka } 834dabf96896ef4c304c6dad36b307a2a458a58209dTadashi G. Takaoka } 8354c0c638a189c1073b1fb6e43fe5fddb6f9932038Tadashi G. Takaoka } 8364112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka invalidateKey(mSpaceKey); 8374112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka } 8384112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka 839dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka public void updateAutoCorrectionState(final boolean isAutoCorrection) { 84020dd1bc090abdd3e88855fe54b1865949aa1168dTadashi G. Takaoka if (!mAutoCorrectionSpacebarLedEnabled) { 84120dd1bc090abdd3e88855fe54b1865949aa1168dTadashi G. Takaoka return; 84220dd1bc090abdd3e88855fe54b1865949aa1168dTadashi G. Takaoka } 8434112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka mAutoCorrectionSpacebarLedOn = isAutoCorrection; 8444112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka invalidateKey(mSpaceKey); 84522b48de11ce6f31a0edf90e1308073e67a7a2adbTadashi G. Takaoka } 84622b48de11ce6f31a0edf90e1308073e67a7a2adbTadashi G. Takaoka 847a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka private void dimEntireKeyboard(final boolean dimmed) { 848f3c4cd45a5df6f90b922ea44db259e53117bb25aTadashi G. Takaoka final boolean needsRedrawing = mNeedsToDimEntireKeyboard != dimmed; 849f3c4cd45a5df6f90b922ea44db259e53117bb25aTadashi G. Takaoka mNeedsToDimEntireKeyboard = dimmed; 850f3c4cd45a5df6f90b922ea44db259e53117bb25aTadashi G. Takaoka if (needsRedrawing) { 851f3c4cd45a5df6f90b922ea44db259e53117bb25aTadashi G. Takaoka invalidateAllKeys(); 852f3c4cd45a5df6f90b922ea44db259e53117bb25aTadashi G. Takaoka } 853f3c4cd45a5df6f90b922ea44db259e53117bb25aTadashi G. Takaoka } 854f3c4cd45a5df6f90b922ea44db259e53117bb25aTadashi G. Takaoka 855f3c4cd45a5df6f90b922ea44db259e53117bb25aTadashi G. Takaoka @Override 856f3c4cd45a5df6f90b922ea44db259e53117bb25aTadashi G. Takaoka protected void onDraw(final Canvas canvas) { 857f3c4cd45a5df6f90b922ea44db259e53117bb25aTadashi G. Takaoka super.onDraw(canvas); 858f3c4cd45a5df6f90b922ea44db259e53117bb25aTadashi G. Takaoka 859f3c4cd45a5df6f90b922ea44db259e53117bb25aTadashi G. Takaoka // Overlay a dark rectangle to dim. 860f3c4cd45a5df6f90b922ea44db259e53117bb25aTadashi G. Takaoka if (mNeedsToDimEntireKeyboard) { 86108ae0d5ca03ed455827e82222df249d1cafb5d71Tadashi G. Takaoka canvas.drawRect(0.0f, 0.0f, getWidth(), getHeight(), mBackgroundDimAlphaPaint); 862f3c4cd45a5df6f90b922ea44db259e53117bb25aTadashi G. Takaoka } 863f3c4cd45a5df6f90b922ea44db259e53117bb25aTadashi G. Takaoka } 864f3c4cd45a5df6f90b922ea44db259e53117bb25aTadashi G. Takaoka 8652fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa // Draw key background. 8662fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa @Override 8672fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa protected void onDrawKeyBackground(final Key key, final Canvas canvas, 8682fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa final Drawable background) { 8692fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa if (key.getCode() == Constants.CODE_SPACE) { 8702fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa super.onDrawKeyBackground(key, canvas, mSpacebarBackground); 8712fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa return; 8722fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa } 8732fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa super.onDrawKeyBackground(key, canvas, background); 8742fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa } 8752fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa 87622b48de11ce6f31a0edf90e1308073e67a7a2adbTadashi G. Takaoka @Override 877dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka protected void onDrawKeyTopVisuals(final Key key, final Canvas canvas, final Paint paint, 878dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka final KeyDrawParams params) { 8796bc9186457219daeb3734531a01271b0e4fa37fbTadashi G. Takaoka if (key.altCodeWhileTyping() && key.isEnabled()) { 88073a46bfeb7a109b49be196e5d679e44c9e66a2e8Tadashi G. Takaoka params.mAnimAlpha = mAltCodeKeyWhileTypingAnimAlpha; 88173a46bfeb7a109b49be196e5d679e44c9e66a2e8Tadashi G. Takaoka } 8822fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa // Don't draw key top letter when key preview is showing. 8832fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa if (FADE_OUT_KEY_TOP_LETTER_WHEN_KEY_IS_PRESSED 884bb476be4e62b3bed7848d37df42f8fa7363b58d1Tadashi G. Takaoka && mKeyPreviewChoreographer.isShowingKeyPreview(key)) { 8852fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa // TODO: Fade out animation for the key top letter, and fade in animation for the key 8862fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa // background color when the user presses the key. 8872fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa return; 8882fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa } 8897dc60f9db729e93cb591492574a436418c553ebfTadashi G. Takaoka final int code = key.getCode(); 8907dc60f9db729e93cb591492574a436418c553ebfTadashi G. Takaoka if (code == Constants.CODE_SPACE) { 891bd93eddb52816acedd5242864e467781d4adfd71Tadashi G. Takaoka drawSpacebar(key, canvas, paint); 8924112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka // Whether space key needs to show the "..." popup hint for special purposes 893fd60b2f97035382b14dce207b3613711982a613eTadashi G. Takaoka if (key.isLongPressEnabled() && mHasMultipleEnabledIMEsOrSubtypes) { 894bd93eddb52816acedd5242864e467781d4adfd71Tadashi G. Takaoka drawKeyPopupHint(key, canvas, paint, params); 8954112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka } 8967dc60f9db729e93cb591492574a436418c553ebfTadashi G. Takaoka } else if (code == Constants.CODE_LANGUAGE_SWITCH) { 89781d4e3cd66a9388c47c7dba55240ddf849b31934Tadashi G. Takaoka super.onDrawKeyTopVisuals(key, canvas, paint, params); 898fd60b2f97035382b14dce207b3613711982a613eTadashi G. Takaoka drawKeyPopupHint(key, canvas, paint, params); 899b19a6b9fc55910bd241bee3b312169a818cb721dTadashi G. Takaoka } else { 900b19a6b9fc55910bd241bee3b312169a818cb721dTadashi G. Takaoka super.onDrawKeyTopVisuals(key, canvas, paint, params); 90122b48de11ce6f31a0edf90e1308073e67a7a2adbTadashi G. Takaoka } 90222b48de11ce6f31a0edf90e1308073e67a7a2adbTadashi G. Takaoka } 9034112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka 904741831d32295acfb7675d7e0781a634d78868c63Satoshi Kataoka private boolean fitsTextIntoWidth(final int width, final String text, final Paint paint) { 905741831d32295acfb7675d7e0781a634d78868c63Satoshi Kataoka final int maxTextWidth = width - mLanguageOnSpacebarHorizontalMargin * 2; 906bd2ca9c0214ea80fa860f4a9d118f866e16b03caTadashi G. Takaoka paint.setTextScaleX(1.0f); 9072fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa final float textWidth = TypefaceUtils.getStringWidth(text, paint); 90820dd1bc090abdd3e88855fe54b1865949aa1168dTadashi G. Takaoka if (textWidth < width) { 90920dd1bc090abdd3e88855fe54b1865949aa1168dTadashi G. Takaoka return true; 91020dd1bc090abdd3e88855fe54b1865949aa1168dTadashi G. Takaoka } 911bd2ca9c0214ea80fa860f4a9d118f866e16b03caTadashi G. Takaoka 912741831d32295acfb7675d7e0781a634d78868c63Satoshi Kataoka final float scaleX = maxTextWidth / textWidth; 91320dd1bc090abdd3e88855fe54b1865949aa1168dTadashi G. Takaoka if (scaleX < MINIMUM_XSCALE_OF_LANGUAGE_NAME) { 91420dd1bc090abdd3e88855fe54b1865949aa1168dTadashi G. Takaoka return false; 91520dd1bc090abdd3e88855fe54b1865949aa1168dTadashi G. Takaoka } 916bd2ca9c0214ea80fa860f4a9d118f866e16b03caTadashi G. Takaoka 917bd2ca9c0214ea80fa860f4a9d118f866e16b03caTadashi G. Takaoka paint.setTextScaleX(scaleX); 9182fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa return TypefaceUtils.getStringWidth(text, paint) < maxTextWidth; 919bd2ca9c0214ea80fa860f4a9d118f866e16b03caTadashi G. Takaoka } 920bd2ca9c0214ea80fa860f4a9d118f866e16b03caTadashi G. Takaoka 921bd2ca9c0214ea80fa860f4a9d118f866e16b03caTadashi G. Takaoka // Layout language name on spacebar. 922741831d32295acfb7675d7e0781a634d78868c63Satoshi Kataoka private String layoutLanguageOnSpacebar(final Paint paint, 92308ae0d5ca03ed455827e82222df249d1cafb5d71Tadashi G. Takaoka final InputMethodSubtype subtype, final int width) { 924741831d32295acfb7675d7e0781a634d78868c63Satoshi Kataoka 925bd2ca9c0214ea80fa860f4a9d118f866e16b03caTadashi G. Takaoka // Choose appropriate language name to fit into the width. 926a410cb48eab0cd75aa27e20f60e47a29a59fb9ffTadashi G. Takaoka final String fullText = SubtypeLocaleUtils.getFullDisplayName(subtype); 92720dd1bc090abdd3e88855fe54b1865949aa1168dTadashi G. Takaoka if (fitsTextIntoWidth(width, fullText, paint)) { 92820dd1bc090abdd3e88855fe54b1865949aa1168dTadashi G. Takaoka return fullText; 929bd2ca9c0214ea80fa860f4a9d118f866e16b03caTadashi G. Takaoka } 930bd2ca9c0214ea80fa860f4a9d118f866e16b03caTadashi G. Takaoka 931a410cb48eab0cd75aa27e20f60e47a29a59fb9ffTadashi G. Takaoka final String middleText = SubtypeLocaleUtils.getMiddleDisplayName(subtype); 93220dd1bc090abdd3e88855fe54b1865949aa1168dTadashi G. Takaoka if (fitsTextIntoWidth(width, middleText, paint)) { 93320dd1bc090abdd3e88855fe54b1865949aa1168dTadashi G. Takaoka return middleText; 9344112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka } 9354112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka 936a410cb48eab0cd75aa27e20f60e47a29a59fb9ffTadashi G. Takaoka final String shortText = SubtypeLocaleUtils.getShortDisplayName(subtype); 93720dd1bc090abdd3e88855fe54b1865949aa1168dTadashi G. Takaoka if (fitsTextIntoWidth(width, shortText, paint)) { 93820dd1bc090abdd3e88855fe54b1865949aa1168dTadashi G. Takaoka return shortText; 9394112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka } 9404112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka 941bd2ca9c0214ea80fa860f4a9d118f866e16b03caTadashi G. Takaoka return ""; 9424112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka } 9434112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka 944dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka private void drawSpacebar(final Key key, final Canvas canvas, final Paint paint) { 9457dc60f9db729e93cb591492574a436418c553ebfTadashi G. Takaoka final int width = key.getWidth(); 9467dc60f9db729e93cb591492574a436418c553ebfTadashi G. Takaoka final int height = key.getHeight(); 9474112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka 948f6972561fcb45310f18230ce217f0c6bb57e7eeeTadashi G. Takaoka // If input language are explicitly selected. 949bd93eddb52816acedd5242864e467781d4adfd71Tadashi G. Takaoka if (mNeedsToDisplayLanguage) { 950bd2ca9c0214ea80fa860f4a9d118f866e16b03caTadashi G. Takaoka paint.setTextAlign(Align.CENTER); 951bd2ca9c0214ea80fa860f4a9d118f866e16b03caTadashi G. Takaoka paint.setTypeface(Typeface.DEFAULT); 9522fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa paint.setTextSize(mLanguageOnSpacebarTextSize); 953bd2ca9c0214ea80fa860f4a9d118f866e16b03caTadashi G. Takaoka final InputMethodSubtype subtype = getKeyboard().mId.mSubtype; 954bd2ca9c0214ea80fa860f4a9d118f866e16b03caTadashi G. Takaoka final String language = layoutLanguageOnSpacebar(paint, subtype, width); 9554112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka // Draw language text with shadow 9564112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka final float descent = paint.descent(); 9574112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka final float textHeight = -paint.ascent() + descent; 958b19a6b9fc55910bd241bee3b312169a818cb721dTadashi G. Takaoka final float baseline = height / 2 + textHeight / 2; 9592fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa paint.setColor(mLanguageOnSpacebarTextShadowColor); 96031c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka paint.setAlpha(mLanguageOnSpacebarAnimAlpha); 9614112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka canvas.drawText(language, width / 2, baseline - descent - 1, paint); 9622fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa paint.setColor(mLanguageOnSpacebarTextColor); 96331c94cea82f1788e3a04f2a1e012945f35497f0aTadashi G. Takaoka paint.setAlpha(mLanguageOnSpacebarAnimAlpha); 9644112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka canvas.drawText(language, width / 2, baseline - descent, paint); 9654112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka } 9664112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka 9674112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka // Draw the spacebar icon at the bottom 968bd93eddb52816acedd5242864e467781d4adfd71Tadashi G. Takaoka if (mAutoCorrectionSpacebarLedOn) { 9694112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka final int iconWidth = width * SPACE_LED_LENGTH_PERCENT / 100; 9704112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka final int iconHeight = mAutoCorrectionSpacebarLedIcon.getIntrinsicHeight(); 9714112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka int x = (width - iconWidth) / 2; 9724112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka int y = height - iconHeight; 973bd93eddb52816acedd5242864e467781d4adfd71Tadashi G. Takaoka drawIcon(canvas, mAutoCorrectionSpacebarLedIcon, x, y, iconWidth, iconHeight); 9742fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa } else if (mSpacebarIcon != null) { 9752fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa final int iconWidth = mSpacebarIcon.getIntrinsicWidth(); 9762fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa final int iconHeight = mSpacebarIcon.getIntrinsicHeight(); 9774112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka int x = (width - iconWidth) / 2; 9784112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka int y = height - iconHeight; 9792fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa drawIcon(canvas, mSpacebarIcon, x, y, iconWidth, iconHeight); 9804112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka } 9814112dc05002d7a880e558418639cf25c4bd02a5aTadashi G. Takaoka } 982c8814e20b7b0ed5f7e11292480e89152618dd862Ken Wakasa 983e68d565d0f9704145adbf781105f1ac9a90f0a98Ken Wakasa @Override 984c8814e20b7b0ed5f7e11292480e89152618dd862Ken Wakasa public void deallocateMemory() { 985e68d565d0f9704145adbf781105f1ac9a90f0a98Ken Wakasa super.deallocateMemory(); 986afca1ddd233c03d79433931a0b6ba97ed22663edTadashi G. Takaoka mDrawingPreviewPlacerView.deallocateMemory(); 987c8814e20b7b0ed5f7e11292480e89152618dd862Ken Wakasa } 9885f6816fa8bf259f0340a3d12c551d1532f647d66Tadashi G. Takaoka} 989