diff options
Diffstat (limited to 'java/src/com/android/inputmethod/keyboard/MainKeyboardView.java')
-rw-r--r-- | java/src/com/android/inputmethod/keyboard/MainKeyboardView.java | 944 |
1 files changed, 281 insertions, 663 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java index 13db47004..702efb3d7 100644 --- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java @@ -27,60 +27,47 @@ import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Typeface; -import android.graphics.drawable.Drawable; -import android.os.Message; -import android.os.SystemClock; import android.preference.PreferenceManager; import android.util.AttributeSet; -import android.util.DisplayMetrics; import android.util.Log; -import android.util.SparseArray; -import android.util.TypedValue; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; -import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.inputmethod.InputMethodSubtype; -import android.widget.TextView; import com.android.inputmethod.accessibility.AccessibilityUtils; -import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy; +import com.android.inputmethod.accessibility.MainKeyboardAccessibilityDelegate; import com.android.inputmethod.annotations.ExternallyReferenced; -import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy; -import com.android.inputmethod.keyboard.PointerTracker.TimerProxy; -import com.android.inputmethod.keyboard.internal.GestureFloatingPreviewText; -import com.android.inputmethod.keyboard.internal.GestureTrailsPreview; +import com.android.inputmethod.keyboard.internal.DrawingHandler; +import com.android.inputmethod.keyboard.internal.DrawingPreviewPlacerView; +import com.android.inputmethod.keyboard.internal.GestureFloatingTextDrawingPreview; +import com.android.inputmethod.keyboard.internal.GestureTrailsDrawingPreview; import com.android.inputmethod.keyboard.internal.KeyDrawParams; +import com.android.inputmethod.keyboard.internal.KeyPreviewChoreographer; import com.android.inputmethod.keyboard.internal.KeyPreviewDrawParams; +import com.android.inputmethod.keyboard.internal.LanguageOnSpacebarHelper; +import com.android.inputmethod.keyboard.internal.MoreKeySpec; import com.android.inputmethod.keyboard.internal.NonDistinctMultitouchHelper; -import com.android.inputmethod.keyboard.internal.PreviewPlacerView; -import com.android.inputmethod.keyboard.internal.SlidingKeyInputPreview; +import com.android.inputmethod.keyboard.internal.SlidingKeyInputDrawingPreview; +import com.android.inputmethod.keyboard.internal.TimerHandler; import com.android.inputmethod.latin.Constants; -import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.SuggestedWords; -import com.android.inputmethod.latin.define.ProductionFlag; import com.android.inputmethod.latin.settings.DebugSettings; -import com.android.inputmethod.latin.utils.CollectionUtils; import com.android.inputmethod.latin.utils.CoordinateUtils; -import com.android.inputmethod.latin.utils.StaticInnerHandlerWrapper; -import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; +import com.android.inputmethod.latin.utils.SpacebarLanguageUtils; import com.android.inputmethod.latin.utils.TypefaceUtils; -import com.android.inputmethod.latin.utils.UsabilityStudyLogUtils; -import com.android.inputmethod.latin.utils.ViewLayoutUtils; -import com.android.inputmethod.research.ResearchLogger; import java.util.WeakHashMap; /** * A view that is responsible for detecting key presses and touch movements. * - * @attr ref R.styleable#MainKeyboardView_autoCorrectionSpacebarLedEnabled - * @attr ref R.styleable#MainKeyboardView_autoCorrectionSpacebarLedIcon - * @attr ref R.styleable#MainKeyboardView_spacebarTextRatio - * @attr ref R.styleable#MainKeyboardView_spacebarTextColor - * @attr ref R.styleable#MainKeyboardView_spacebarTextShadowColor + * @attr ref R.styleable#MainKeyboardView_languageOnSpacebarTextRatio + * @attr ref R.styleable#MainKeyboardView_languageOnSpacebarTextColor + * @attr ref R.styleable#MainKeyboardView_languageOnSpacebarTextShadowRadius + * @attr ref R.styleable#MainKeyboardView_languageOnSpacebarTextShadowColor * @attr ref R.styleable#MainKeyboardView_languageOnSpacebarFinalAlpha * @attr ref R.styleable#MainKeyboardView_languageOnSpacebarFadeoutAnimator * @attr ref R.styleable#MainKeyboardView_altCodeKeyWhileTypingFadeoutAnimator @@ -88,7 +75,7 @@ import java.util.WeakHashMap; * @attr ref R.styleable#MainKeyboardView_keyHysteresisDistance * @attr ref R.styleable#MainKeyboardView_touchNoiseThresholdTime * @attr ref R.styleable#MainKeyboardView_touchNoiseThresholdDistance - * @attr ref R.styleable#MainKeyboardView_slidingKeyInputEnable + * @attr ref R.styleable#MainKeyboardView_keySelectionByDraggingFinger * @attr ref R.styleable#MainKeyboardView_keyRepeatStartTimeout * @attr ref R.styleable#MainKeyboardView_keyRepeatInterval * @attr ref R.styleable#MainKeyboardView_longPressKeyTimeout @@ -114,61 +101,51 @@ import java.util.WeakHashMap; * @attr ref R.styleable#MainKeyboardView_gestureRecognitionSpeedThreshold * @attr ref R.styleable#MainKeyboardView_suppressKeyPreviewAfterBatchInputDuration */ -public final class MainKeyboardView extends KeyboardView implements PointerTracker.KeyEventHandler, - PointerTracker.DrawingProxy, MoreKeysPanel.Controller { +public final class MainKeyboardView extends KeyboardView implements PointerTracker.DrawingProxy, + MoreKeysPanel.Controller, DrawingHandler.Callbacks, TimerHandler.Callbacks { private static final String TAG = MainKeyboardView.class.getSimpleName(); /** Listener for {@link KeyboardActionListener}. */ private KeyboardActionListener mKeyboardActionListener; - /* Space key and its icons */ + /* Space key and its icon and background. */ private Key mSpaceKey; - private Drawable mSpaceIcon; // Stuff to draw language name on spacebar. private final int mLanguageOnSpacebarFinalAlpha; private ObjectAnimator mLanguageOnSpacebarFadeoutAnimator; - private boolean mNeedsToDisplayLanguage; + private int mLanguageOnSpacebarFormatType; private boolean mHasMultipleEnabledIMEsOrSubtypes; private int mLanguageOnSpacebarAnimAlpha = Constants.Color.ALPHA_OPAQUE; - private final float mSpacebarTextRatio; - private float mSpacebarTextSize; - private final int mSpacebarTextColor; - private final int mSpacebarTextShadowColor; + private final float mLanguageOnSpacebarTextRatio; + private float mLanguageOnSpacebarTextSize; + private final int mLanguageOnSpacebarTextColor; + private final float mLanguageOnSpacebarTextShadowRadius; + private final int mLanguageOnSpacebarTextShadowColor; + private static final float LANGUAGE_ON_SPACEBAR_TEXT_SHADOW_RADIUS_DISABLED = -1.0f; // The minimum x-scale to fit the language name on spacebar. private static final float MINIMUM_XSCALE_OF_LANGUAGE_NAME = 0.8f; - // Stuff to draw auto correction LED on spacebar. - private boolean mAutoCorrectionSpacebarLedOn; - private final boolean mAutoCorrectionSpacebarLedEnabled; - private final Drawable mAutoCorrectionSpacebarLedIcon; - private static final int SPACE_LED_LENGTH_PERCENT = 80; // Stuff to draw altCodeWhileTyping keys. - private ObjectAnimator mAltCodeKeyWhileTypingFadeoutAnimator; - private ObjectAnimator mAltCodeKeyWhileTypingFadeinAnimator; + private final ObjectAnimator mAltCodeKeyWhileTypingFadeoutAnimator; + private final ObjectAnimator mAltCodeKeyWhileTypingFadeinAnimator; private int mAltCodeKeyWhileTypingAnimAlpha = Constants.Color.ALPHA_OPAQUE; - // Preview placer view - private final PreviewPlacerView mPreviewPlacerView; + // Drawing preview placer view + private final DrawingPreviewPlacerView mDrawingPreviewPlacerView; private final int[] mOriginCoords = CoordinateUtils.newInstance(); - private final GestureFloatingPreviewText mGestureFloatingPreviewText; - private final GestureTrailsPreview mGestureTrailsPreview; - private final SlidingKeyInputPreview mSlidingKeyInputPreview; + private final GestureFloatingTextDrawingPreview mGestureFloatingTextDrawingPreview; + private final GestureTrailsDrawingPreview mGestureTrailsDrawingPreview; + private final SlidingKeyInputDrawingPreview mSlidingKeyInputDrawingPreview; // Key preview - private final int mKeyPreviewLayoutId; - private final int mKeyPreviewOffset; - private final int mKeyPreviewHeight; - private final SparseArray<TextView> mKeyPreviewTexts = CollectionUtils.newSparseArray(); - private final KeyPreviewDrawParams mKeyPreviewDrawParams = new KeyPreviewDrawParams(); - private boolean mShowKeyPreviewPopup = true; - private int mKeyPreviewLingerTimeout; + private final KeyPreviewDrawParams mKeyPreviewDrawParams; + private final KeyPreviewChoreographer mKeyPreviewChoreographer; // More keys keyboard private final Paint mBackgroundDimAlphaPaint = new Paint(); private boolean mNeedsToDimEntireKeyboard; private final View mMoreKeysKeyboardContainer; - private final WeakHashMap<Key, Keyboard> mMoreKeysKeyboardCache = - CollectionUtils.newWeakHashMap(); + private final WeakHashMap<Key, Keyboard> mMoreKeysKeyboardCache = new WeakHashMap<>(); private final boolean mConfigShowMoreKeysKeyboardAtTouchedPoint; // More keys panel (used by both more keys keyboard and more suggestions view) // TODO: Consider extending to support multiple more keys panels @@ -178,244 +155,15 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack // TODO: Make this parameter customizable by user via settings. private int mGestureFloatingPreviewTextLingerTimeout; - private KeyDetector mKeyDetector; + private final KeyDetector mKeyDetector; private final NonDistinctMultitouchHelper mNonDistinctMultitouchHelper; - private final KeyTimerHandler mKeyTimerHandler; + private final TimerHandler mKeyTimerHandler; private final int mLanguageOnSpacebarHorizontalMargin; - private static final class KeyTimerHandler extends StaticInnerHandlerWrapper<MainKeyboardView> - implements TimerProxy { - private static final int MSG_TYPING_STATE_EXPIRED = 0; - private static final int MSG_REPEAT_KEY = 1; - private static final int MSG_LONGPRESS_KEY = 2; - private static final int MSG_DOUBLE_TAP_SHIFT_KEY = 3; - private static final int MSG_UPDATE_BATCH_INPUT = 4; - - private final int mIgnoreAltCodeKeyTimeout; - private final int mGestureRecognitionUpdateTime; - - public KeyTimerHandler(final MainKeyboardView outerInstance, - final TypedArray mainKeyboardViewAttr) { - super(outerInstance); - - mIgnoreAltCodeKeyTimeout = mainKeyboardViewAttr.getInt( - R.styleable.MainKeyboardView_ignoreAltCodeKeyTimeout, 0); - mGestureRecognitionUpdateTime = mainKeyboardViewAttr.getInt( - R.styleable.MainKeyboardView_gestureRecognitionUpdateTime, 0); - } - - @Override - public void handleMessage(final Message msg) { - final MainKeyboardView keyboardView = getOuterInstance(); - if (keyboardView == null) { - return; - } - final PointerTracker tracker = (PointerTracker) msg.obj; - switch (msg.what) { - case MSG_TYPING_STATE_EXPIRED: - startWhileTypingFadeinAnimation(keyboardView); - break; - case MSG_REPEAT_KEY: - tracker.onKeyRepeat(msg.arg1 /* code */, msg.arg2 /* repeatCount */); - break; - case MSG_LONGPRESS_KEY: - keyboardView.onLongPress(tracker); - break; - case MSG_UPDATE_BATCH_INPUT: - tracker.updateBatchInputByTimer(SystemClock.uptimeMillis()); - startUpdateBatchInputTimer(tracker); - break; - } - } - - @Override - public void startKeyRepeatTimer(final PointerTracker tracker, final int repeatCount, - final int delay) { - final Key key = tracker.getKey(); - if (key == null || delay == 0) { - return; - } - sendMessageDelayed( - obtainMessage(MSG_REPEAT_KEY, key.getCode(), repeatCount, tracker), delay); - } - - public void cancelKeyRepeatTimer() { - removeMessages(MSG_REPEAT_KEY); - } - - // TODO: Suppress layout changes in key repeat mode - public boolean isInKeyRepeat() { - return hasMessages(MSG_REPEAT_KEY); - } - - @Override - public void startLongPressTimer(final PointerTracker tracker, final int delay) { - cancelLongPressTimer(); - if (delay <= 0) return; - sendMessageDelayed(obtainMessage(MSG_LONGPRESS_KEY, tracker), delay); - } - - @Override - public void cancelLongPressTimer() { - removeMessages(MSG_LONGPRESS_KEY); - } - - private static void cancelAndStartAnimators(final ObjectAnimator animatorToCancel, - final ObjectAnimator animatorToStart) { - if (animatorToCancel == null || animatorToStart == null) { - // TODO: Stop using null as a no-operation animator. - return; - } - float startFraction = 0.0f; - if (animatorToCancel.isStarted()) { - animatorToCancel.cancel(); - startFraction = 1.0f - animatorToCancel.getAnimatedFraction(); - } - final long startTime = (long)(animatorToStart.getDuration() * startFraction); - animatorToStart.start(); - animatorToStart.setCurrentPlayTime(startTime); - } - - private static void startWhileTypingFadeinAnimation(final MainKeyboardView keyboardView) { - cancelAndStartAnimators(keyboardView.mAltCodeKeyWhileTypingFadeoutAnimator, - keyboardView.mAltCodeKeyWhileTypingFadeinAnimator); - } - - private static void startWhileTypingFadeoutAnimation(final MainKeyboardView keyboardView) { - cancelAndStartAnimators(keyboardView.mAltCodeKeyWhileTypingFadeinAnimator, - keyboardView.mAltCodeKeyWhileTypingFadeoutAnimator); - } - - @Override - public void startTypingStateTimer(final Key typedKey) { - if (typedKey.isModifier() || typedKey.altCodeWhileTyping()) { - return; - } - - final boolean isTyping = isTypingState(); - removeMessages(MSG_TYPING_STATE_EXPIRED); - final MainKeyboardView keyboardView = getOuterInstance(); - - // When user hits the space or the enter key, just cancel the while-typing timer. - final int typedCode = typedKey.getCode(); - if (typedCode == Constants.CODE_SPACE || typedCode == Constants.CODE_ENTER) { - if (isTyping) { - startWhileTypingFadeinAnimation(keyboardView); - } - return; - } - - sendMessageDelayed( - obtainMessage(MSG_TYPING_STATE_EXPIRED), mIgnoreAltCodeKeyTimeout); - if (isTyping) { - return; - } - startWhileTypingFadeoutAnimation(keyboardView); - } - - @Override - public boolean isTypingState() { - return hasMessages(MSG_TYPING_STATE_EXPIRED); - } - - @Override - public void startDoubleTapShiftKeyTimer() { - sendMessageDelayed(obtainMessage(MSG_DOUBLE_TAP_SHIFT_KEY), - ViewConfiguration.getDoubleTapTimeout()); - } - - @Override - public void cancelDoubleTapShiftKeyTimer() { - removeMessages(MSG_DOUBLE_TAP_SHIFT_KEY); - } - - @Override - public boolean isInDoubleTapShiftKeyTimeout() { - return hasMessages(MSG_DOUBLE_TAP_SHIFT_KEY); - } - - @Override - public void cancelKeyTimers() { - cancelKeyRepeatTimer(); - cancelLongPressTimer(); - } - - @Override - public void startUpdateBatchInputTimer(final PointerTracker tracker) { - if (mGestureRecognitionUpdateTime <= 0) { - return; - } - removeMessages(MSG_UPDATE_BATCH_INPUT, tracker); - sendMessageDelayed(obtainMessage(MSG_UPDATE_BATCH_INPUT, tracker), - mGestureRecognitionUpdateTime); - } - - @Override - public void cancelUpdateBatchInputTimer(final PointerTracker tracker) { - removeMessages(MSG_UPDATE_BATCH_INPUT, tracker); - } - - @Override - public void cancelAllUpdateBatchInputTimers() { - removeMessages(MSG_UPDATE_BATCH_INPUT); - } - - public void cancelAllMessages() { - cancelKeyTimers(); - cancelAllUpdateBatchInputTimers(); - } - } - private final DrawingHandler mDrawingHandler = new DrawingHandler(this); - public static class DrawingHandler extends StaticInnerHandlerWrapper<MainKeyboardView> { - private static final int MSG_DISMISS_KEY_PREVIEW = 0; - private static final int MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 1; - - public DrawingHandler(final MainKeyboardView outerInstance) { - super(outerInstance); - } - - @Override - public void handleMessage(final Message msg) { - final MainKeyboardView mainKeyboardView = getOuterInstance(); - if (mainKeyboardView == null) return; - final PointerTracker tracker = (PointerTracker) msg.obj; - switch (msg.what) { - case MSG_DISMISS_KEY_PREVIEW: - final TextView previewText = mainKeyboardView.mKeyPreviewTexts.get( - tracker.mPointerId); - if (previewText != null) { - previewText.setVisibility(INVISIBLE); - } - break; - case MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT: - mainKeyboardView.showGestureFloatingPreviewText(SuggestedWords.EMPTY); - break; - } - } - - public void dismissKeyPreview(final long delay, final PointerTracker tracker) { - sendMessageDelayed(obtainMessage(MSG_DISMISS_KEY_PREVIEW, tracker), delay); - } - - public void cancelDismissKeyPreview(final PointerTracker tracker) { - removeMessages(MSG_DISMISS_KEY_PREVIEW, tracker); - } - - private void cancelAllDismissKeyPreviews() { - removeMessages(MSG_DISMISS_KEY_PREVIEW); - } - - public void dismissGestureFloatingPreviewText(final long delay) { - sendMessageDelayed(obtainMessage(MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT), delay); - } - - public void cancelAllMessages() { - cancelAllDismissKeyPreviews(); - } - } + private MainKeyboardAccessibilityDelegate mAccessibilityDelegate; public MainKeyboardView(final Context context, final AttributeSet attrs) { this(context, attrs, R.attr.mainKeyboardViewStyle); @@ -424,7 +172,26 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack public MainKeyboardView(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); - PointerTracker.init(getResources()); + mDrawingPreviewPlacerView = new DrawingPreviewPlacerView(context, attrs); + + final TypedArray mainKeyboardViewAttr = context.obtainStyledAttributes( + attrs, R.styleable.MainKeyboardView, defStyle, R.style.MainKeyboardView); + final int ignoreAltCodeKeyTimeout = mainKeyboardViewAttr.getInt( + R.styleable.MainKeyboardView_ignoreAltCodeKeyTimeout, 0); + final int gestureRecognitionUpdateTime = mainKeyboardViewAttr.getInt( + R.styleable.MainKeyboardView_gestureRecognitionUpdateTime, 0); + mKeyTimerHandler = new TimerHandler( + this, ignoreAltCodeKeyTimeout, gestureRecognitionUpdateTime); + + final float keyHysteresisDistance = mainKeyboardViewAttr.getDimension( + R.styleable.MainKeyboardView_keyHysteresisDistance, 0.0f); + final float keyHysteresisDistanceForSlidingModifier = mainKeyboardViewAttr.getDimension( + R.styleable.MainKeyboardView_keyHysteresisDistanceForSlidingModifier, 0.0f); + mKeyDetector = new KeyDetector( + keyHysteresisDistance, keyHysteresisDistanceForSlidingModifier); + + PointerTracker.init(mainKeyboardViewAttr, mKeyTimerHandler, this /* DrawingProxy */); + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); final boolean forceNonDistinctMultitouch = prefs.getBoolean( DebugSettings.PREF_FORCE_NON_DISTINCT_MULTITOUCH, false); @@ -434,24 +201,19 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack mNonDistinctMultitouchHelper = hasDistinctMultitouch ? null : new NonDistinctMultitouchHelper(); - mPreviewPlacerView = new PreviewPlacerView(context, attrs); - - final TypedArray mainKeyboardViewAttr = context.obtainStyledAttributes( - attrs, R.styleable.MainKeyboardView, defStyle, R.style.MainKeyboardView); final int backgroundDimAlpha = mainKeyboardViewAttr.getInt( R.styleable.MainKeyboardView_backgroundDimAlpha, 0); mBackgroundDimAlphaPaint.setColor(Color.BLACK); mBackgroundDimAlphaPaint.setAlpha(backgroundDimAlpha); - mAutoCorrectionSpacebarLedEnabled = mainKeyboardViewAttr.getBoolean( - R.styleable.MainKeyboardView_autoCorrectionSpacebarLedEnabled, false); - mAutoCorrectionSpacebarLedIcon = mainKeyboardViewAttr.getDrawable( - R.styleable.MainKeyboardView_autoCorrectionSpacebarLedIcon); - mSpacebarTextRatio = mainKeyboardViewAttr.getFraction( - R.styleable.MainKeyboardView_spacebarTextRatio, 1, 1, 1.0f); - mSpacebarTextColor = mainKeyboardViewAttr.getColor( - R.styleable.MainKeyboardView_spacebarTextColor, 0); - mSpacebarTextShadowColor = mainKeyboardViewAttr.getColor( - R.styleable.MainKeyboardView_spacebarTextShadowColor, 0); + mLanguageOnSpacebarTextRatio = mainKeyboardViewAttr.getFraction( + R.styleable.MainKeyboardView_languageOnSpacebarTextRatio, 1, 1, 1.0f); + mLanguageOnSpacebarTextColor = mainKeyboardViewAttr.getColor( + R.styleable.MainKeyboardView_languageOnSpacebarTextColor, 0); + mLanguageOnSpacebarTextShadowRadius = mainKeyboardViewAttr.getFloat( + R.styleable.MainKeyboardView_languageOnSpacebarTextShadowRadius, + LANGUAGE_ON_SPACEBAR_TEXT_SHADOW_RADIUS_DISABLED); + mLanguageOnSpacebarTextShadowColor = mainKeyboardViewAttr.getColor( + R.styleable.MainKeyboardView_languageOnSpacebarTextShadowColor, 0); mLanguageOnSpacebarFinalAlpha = mainKeyboardViewAttr.getInt( R.styleable.MainKeyboardView_languageOnSpacebarFinalAlpha, Constants.Color.ALPHA_OPAQUE); @@ -462,24 +224,9 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack final int altCodeKeyWhileTypingFadeinAnimatorResId = mainKeyboardViewAttr.getResourceId( R.styleable.MainKeyboardView_altCodeKeyWhileTypingFadeinAnimator, 0); - final float keyHysteresisDistance = mainKeyboardViewAttr.getDimension( - R.styleable.MainKeyboardView_keyHysteresisDistance, 0.0f); - final float keyHysteresisDistanceForSlidingModifier = mainKeyboardViewAttr.getDimension( - R.styleable.MainKeyboardView_keyHysteresisDistanceForSlidingModifier, 0.0f); - mKeyDetector = new KeyDetector( - keyHysteresisDistance, keyHysteresisDistanceForSlidingModifier); - mKeyTimerHandler = new KeyTimerHandler(this, mainKeyboardViewAttr); - mKeyPreviewOffset = mainKeyboardViewAttr.getDimensionPixelOffset( - R.styleable.MainKeyboardView_keyPreviewOffset, 0); - mKeyPreviewHeight = mainKeyboardViewAttr.getDimensionPixelSize( - R.styleable.MainKeyboardView_keyPreviewHeight, 0); - mKeyPreviewLingerTimeout = mainKeyboardViewAttr.getInt( - R.styleable.MainKeyboardView_keyPreviewLingerTimeout, 0); - mKeyPreviewLayoutId = mainKeyboardViewAttr.getResourceId( - R.styleable.MainKeyboardView_keyPreviewLayout, 0); - if (mKeyPreviewLayoutId == 0) { - mShowKeyPreviewPopup = false; - } + mKeyPreviewDrawParams = new KeyPreviewDrawParams(mainKeyboardViewAttr); + mKeyPreviewChoreographer = new KeyPreviewChoreographer(mKeyPreviewDrawParams); + final int moreKeysKeyboardLayoutId = mainKeyboardViewAttr.getResourceId( R.styleable.MainKeyboardView_moreKeysKeyboardLayout, 0); mConfigShowMoreKeysKeyboardAtTouchedPoint = mainKeyboardViewAttr.getBoolean( @@ -487,19 +234,16 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack mGestureFloatingPreviewTextLingerTimeout = mainKeyboardViewAttr.getInt( R.styleable.MainKeyboardView_gestureFloatingPreviewTextLingerTimeout, 0); - PointerTracker.setParameters(mainKeyboardViewAttr); - mGestureFloatingPreviewText = new GestureFloatingPreviewText( - mPreviewPlacerView, mainKeyboardViewAttr); - mPreviewPlacerView.addPreview(mGestureFloatingPreviewText); + mGestureFloatingTextDrawingPreview = new GestureFloatingTextDrawingPreview( + mainKeyboardViewAttr); + mGestureFloatingTextDrawingPreview.setDrawingView(mDrawingPreviewPlacerView); - mGestureTrailsPreview = new GestureTrailsPreview( - mPreviewPlacerView, mainKeyboardViewAttr); - mPreviewPlacerView.addPreview(mGestureTrailsPreview); + mGestureTrailsDrawingPreview = new GestureTrailsDrawingPreview(mainKeyboardViewAttr); + mGestureTrailsDrawingPreview.setDrawingView(mDrawingPreviewPlacerView); - mSlidingKeyInputPreview = new SlidingKeyInputPreview( - mPreviewPlacerView, mainKeyboardViewAttr); - mPreviewPlacerView.addPreview(mSlidingKeyInputPreview); + mSlidingKeyInputDrawingPreview = new SlidingKeyInputDrawingPreview(mainKeyboardViewAttr); + mSlidingKeyInputDrawingPreview.setDrawingView(mDrawingPreviewPlacerView); mainKeyboardViewAttr.recycle(); mMoreKeysKeyboardContainer = LayoutInflater.from(getContext()) @@ -513,14 +257,14 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack mKeyboardActionListener = KeyboardActionListener.EMPTY_LISTENER; - mLanguageOnSpacebarHorizontalMargin = - (int) getResources().getDimension(R.dimen.language_on_spacebar_horizontal_margin); + mLanguageOnSpacebarHorizontalMargin = (int)getResources().getDimension( + R.dimen.config_language_on_spacebar_horizontal_margin); } @Override public void setHardwareAcceleratedDrawingEnabled(final boolean enabled) { super.setHardwareAcceleratedDrawingEnabled(enabled); - mPreviewPlacerView.setHardwareAcceleratedDrawingEnabled(enabled); + mDrawingPreviewPlacerView.setHardwareAcceleratedDrawingEnabled(enabled); } private ObjectAnimator loadObjectAnimator(final int resId, final Object target) { @@ -536,6 +280,35 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack return animator; } + private static void cancelAndStartAnimators(final ObjectAnimator animatorToCancel, + final ObjectAnimator animatorToStart) { + if (animatorToCancel == null || animatorToStart == null) { + // TODO: Stop using null as a no-operation animator. + return; + } + float startFraction = 0.0f; + if (animatorToCancel.isStarted()) { + animatorToCancel.cancel(); + startFraction = 1.0f - animatorToCancel.getAnimatedFraction(); + } + final long startTime = (long)(animatorToStart.getDuration() * startFraction); + animatorToStart.start(); + animatorToStart.setCurrentPlayTime(startTime); + } + + // Implements {@link TimerHander.Callbacks} method. + @Override + public void startWhileTypingFadeinAnimation() { + cancelAndStartAnimators( + mAltCodeKeyWhileTypingFadeoutAnimator, mAltCodeKeyWhileTypingFadeinAnimator); + } + + @Override + public void startWhileTypingFadeoutAnimation() { + cancelAndStartAnimators( + mAltCodeKeyWhileTypingFadeinAnimator, mAltCodeKeyWhileTypingFadeoutAnimator); + } + @ExternallyReferenced public int getLanguageOnSpacebarAnimAlpha() { return mLanguageOnSpacebarAnimAlpha; @@ -573,28 +346,16 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack PointerTracker.setKeyboardActionListener(listener); } - /** - * Returns the {@link KeyboardActionListener} object. - * @return the listener attached to this keyboard - */ - @Override - public KeyboardActionListener getKeyboardActionListener() { - return mKeyboardActionListener; - } - - @Override - public KeyDetector getKeyDetector() { - return mKeyDetector; + // TODO: We should reconsider which coordinate system should be used to represent keyboard + // event. + public int getKeyX(final int x) { + return Constants.isValidCoordinate(x) ? mKeyDetector.getTouchX(x) : x; } - @Override - public DrawingProxy getDrawingProxy() { - return this; - } - - @Override - public TimerProxy getTimerProxy() { - return mKeyTimerHandler; + // TODO: We should reconsider which coordinate system should be used to represent keyboard + // event. + public int getKeyY(final int y) { + return Constants.isValidCoordinate(y) ? mKeyDetector.getTouchY(y) : y; } /** @@ -607,7 +368,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack @Override public void setKeyboard(final Keyboard keyboard) { // Remove any pending messages, except dismissing preview and key repeat. - mKeyTimerHandler.cancelLongPressTimer(); + mKeyTimerHandler.cancelLongPressTimers(); super.setKeyboard(keyboard); mKeyDetector.setKeyboard( keyboard, -getPaddingLeft(), -getPaddingTop() + getVerticalCorrection()); @@ -615,18 +376,17 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack mMoreKeysKeyboardCache.clear(); mSpaceKey = keyboard.getKey(Constants.CODE_SPACE); - mSpaceIcon = (mSpaceKey != null) - ? mSpaceKey.getIcon(keyboard.mIconsSet, Constants.Color.ALPHA_OPAQUE) : null; final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap; - mSpacebarTextSize = keyHeight * mSpacebarTextRatio; - if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { - final int orientation = getContext().getResources().getConfiguration().orientation; - ResearchLogger.mainKeyboardView_setKeyboard(keyboard, orientation); - } + mLanguageOnSpacebarTextSize = keyHeight * mLanguageOnSpacebarTextRatio; - // This always needs to be set since the accessibility state can - // potentially change without the keyboard being set again. - AccessibleKeyboardViewProxy.getInstance().setKeyboard(); + if (AccessibilityUtils.getInstance().isAccessibilityEnabled()) { + if (mAccessibilityDelegate == null) { + mAccessibilityDelegate = new MainKeyboardAccessibilityDelegate(this, mKeyDetector); + } + mAccessibilityDelegate.setKeyboard(keyboard); + } else { + mAccessibilityDelegate = null; + } } /** @@ -637,26 +397,21 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack * @see #isKeyPreviewPopupEnabled() */ public void setKeyPreviewPopupEnabled(final boolean previewEnabled, final int delay) { - mShowKeyPreviewPopup = previewEnabled; - mKeyPreviewLingerTimeout = delay; + mKeyPreviewDrawParams.setPopupEnabled(previewEnabled, delay); + } + + public void setKeyPreviewAnimationParams(final float showUpStartScale, final int showUpDuration, + final float dismissEndScale, final int dismissDuration) { + mKeyPreviewDrawParams.setAnimationParams( + showUpStartScale, showUpDuration, dismissEndScale, dismissDuration); } private void locatePreviewPlacerView() { - if (mPreviewPlacerView.getParent() != null) { - return; - } - final int width = getWidth(); - final int height = getHeight(); - if (width == 0 || height == 0) { - // In transient state. - return; - } getLocationInWindow(mOriginCoords); - final DisplayMetrics dm = getResources().getDisplayMetrics(); - if (CoordinateUtils.y(mOriginCoords) < dm.heightPixels / 4) { - // In transient state. - return; - } + mDrawingPreviewPlacerView.setKeyboardViewGeometry(mOriginCoords, getWidth(), getHeight()); + } + + private void installPreviewPlacerView() { final View rootView = getRootView(); if (rootView == null) { Log.w(TAG, "Cannot find root view"); @@ -665,191 +420,85 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack final ViewGroup windowContentView = (ViewGroup)rootView.findViewById(android.R.id.content); // Note: It'd be very weird if we get null by android.R.id.content. if (windowContentView == null) { - Log.w(TAG, "Cannot find android.R.id.content view to add PreviewPlacerView"); - } else { - windowContentView.addView(mPreviewPlacerView); - mPreviewPlacerView.setKeyboardViewGeometry(mOriginCoords, width, height); - } - } - - /** - * Returns the enabled state of the key feedback preview - * @return whether or not the key feedback preview is enabled - * @see #setKeyPreviewPopupEnabled(boolean, int) - */ - public boolean isKeyPreviewPopupEnabled() { - return mShowKeyPreviewPopup; - } - - private void addKeyPreview(final TextView keyPreview) { - locatePreviewPlacerView(); - mPreviewPlacerView.addView( - keyPreview, ViewLayoutUtils.newLayoutParam(mPreviewPlacerView, 0, 0)); - } - - private TextView getKeyPreviewText(final int pointerId) { - TextView previewText = mKeyPreviewTexts.get(pointerId); - if (previewText != null) { - return previewText; - } - final Context context = getContext(); - if (mKeyPreviewLayoutId != 0) { - previewText = (TextView)LayoutInflater.from(context).inflate(mKeyPreviewLayoutId, null); - } else { - previewText = new TextView(context); + Log.w(TAG, "Cannot find android.R.id.content view to add DrawingPreviewPlacerView"); + return; } - mKeyPreviewTexts.put(pointerId, previewText); - return previewText; + windowContentView.addView(mDrawingPreviewPlacerView); } - private void dismissAllKeyPreviews() { - final int pointerCount = mKeyPreviewTexts.size(); - for (int id = 0; id < pointerCount; id++) { - final TextView previewText = mKeyPreviewTexts.get(id); - if (previewText != null) { - previewText.setVisibility(INVISIBLE); - } - } + // Implements {@link DrawingHandler.Callbacks} method. + @Override + public void dismissAllKeyPreviews() { + mKeyPreviewChoreographer.dismissAllKeyPreviews(); PointerTracker.setReleasedKeyGraphicsToAllKeys(); } - // Background state set - private static final int[][][] KEY_PREVIEW_BACKGROUND_STATE_TABLE = { - { // STATE_MIDDLE - EMPTY_STATE_SET, - { R.attr.state_has_morekeys } - }, - { // STATE_LEFT - { R.attr.state_left_edge }, - { R.attr.state_left_edge, R.attr.state_has_morekeys } - }, - { // STATE_RIGHT - { R.attr.state_right_edge }, - { R.attr.state_right_edge, R.attr.state_has_morekeys } - } - }; - private static final int STATE_MIDDLE = 0; - private static final int STATE_LEFT = 1; - private static final int STATE_RIGHT = 2; - private static final int STATE_NORMAL = 0; - private static final int STATE_HAS_MOREKEYS = 1; - @Override - public void showKeyPreview(final PointerTracker tracker) { - final KeyPreviewDrawParams previewParams = mKeyPreviewDrawParams; - final Keyboard keyboard = getKeyboard(); - if (!mShowKeyPreviewPopup) { - previewParams.mPreviewVisibleOffset = -keyboard.mVerticalGap; + public void showKeyPreview(final Key key) { + // If the key is invalid or has no key preview, we must not show key preview. + if (key == null || key.noKeyPreview()) { return; } - - final TextView previewText = getKeyPreviewText(tracker.mPointerId); - // If the key preview has no parent view yet, add it to the ViewGroup which can place - // key preview absolutely in SoftInputWindow. - if (previewText.getParent() == null) { - addKeyPreview(previewText); - } - - mDrawingHandler.cancelDismissKeyPreview(tracker); - final Key key = tracker.getKey(); - // If key is invalid or IME is already closed, we must not show key preview. - // Trying to show key preview while root window is closed causes - // WindowManager.BadTokenException. - if (key == null) { + final Keyboard keyboard = getKeyboard(); + if (keyboard == null) { return; } - - final KeyDrawParams drawParams = mKeyDrawParams; - previewText.setTextColor(drawParams.mPreviewTextColor); - final Drawable background = previewText.getBackground(); - final String label = key.getPreviewLabel(); - // What we show as preview should match what we show on a key top in onDraw(). - if (label != null) { - // TODO Should take care of temporaryShiftLabel here. - previewText.setCompoundDrawables(null, null, null, null); - previewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, - key.selectPreviewTextSize(drawParams)); - previewText.setTypeface(key.selectPreviewTypeface(drawParams)); - previewText.setText(label); - } else { - previewText.setCompoundDrawables(null, null, null, - key.getPreviewIcon(keyboard.mIconsSet)); - previewText.setText(null); + final KeyPreviewDrawParams previewParams = mKeyPreviewDrawParams; + if (!previewParams.isPopupEnabled()) { + previewParams.setVisibleOffset(-keyboard.mVerticalGap); + return; } - previewText.measure( - ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); - final int keyDrawWidth = key.getDrawWidth(); - final int previewWidth = previewText.getMeasuredWidth(); - final int previewHeight = mKeyPreviewHeight; - // The width and height of visible part of the key preview background. The content marker - // of the background 9-patch have to cover the visible part of the background. - previewParams.mPreviewVisibleWidth = previewWidth - previewText.getPaddingLeft() - - previewText.getPaddingRight(); - previewParams.mPreviewVisibleHeight = previewHeight - previewText.getPaddingTop() - - previewText.getPaddingBottom(); - // The distance between the top edge of the parent key and the bottom of the visible part - // of the key preview background. - previewParams.mPreviewVisibleOffset = mKeyPreviewOffset - previewText.getPaddingBottom(); + locatePreviewPlacerView(); getLocationInWindow(mOriginCoords); - // The key preview is horizontally aligned with the center of the visible part of the - // parent key. If it doesn't fit in this {@link KeyboardView}, it is moved inward to fit and - // the left/right background is used if such background is specified. - final int statePosition; - int previewX = key.getDrawX() - (previewWidth - keyDrawWidth) / 2 - + CoordinateUtils.x(mOriginCoords); - if (previewX < 0) { - previewX = 0; - statePosition = STATE_LEFT; - } else if (previewX > getWidth() - previewWidth) { - previewX = getWidth() - previewWidth; - statePosition = STATE_RIGHT; - } else { - statePosition = STATE_MIDDLE; - } - // The key preview is placed vertically above the top edge of the parent key with an - // arbitrary offset. - final int previewY = key.getY() - previewHeight + mKeyPreviewOffset - + CoordinateUtils.y(mOriginCoords); - - if (background != null) { - final int hasMoreKeys = (key.getMoreKeys() != null) ? STATE_HAS_MOREKEYS : STATE_NORMAL; - background.setState(KEY_PREVIEW_BACKGROUND_STATE_TABLE[statePosition][hasMoreKeys]); - } - ViewLayoutUtils.placeViewAt( - previewText, previewX, previewY, previewWidth, previewHeight); - previewText.setVisibility(VISIBLE); + mKeyPreviewChoreographer.placeAndShowKeyPreview(key, keyboard.mIconsSet, mKeyDrawParams, + getWidth(), mOriginCoords, mDrawingPreviewPlacerView, isHardwareAccelerated()); } + // Implements {@link TimerHandler.Callbacks} method. @Override - public void dismissKeyPreview(final PointerTracker tracker) { - mDrawingHandler.dismissKeyPreview(mKeyPreviewLingerTimeout, tracker); + public void dismissKeyPreviewWithoutDelay(final Key key) { + mKeyPreviewChoreographer.dismissKeyPreview(key, false /* withAnimation */); + // To redraw key top letter. + invalidateKey(key); + } + + @Override + public void dismissKeyPreview(final Key key) { + if (!isHardwareAccelerated()) { + // TODO: Implement preference option to control key preview method and duration. + mDrawingHandler.dismissKeyPreview(mKeyPreviewDrawParams.getLingerTimeout(), key); + return; + } + mKeyPreviewChoreographer.dismissKeyPreview(key, true /* withAnimation */); } public void setSlidingKeyInputPreviewEnabled(final boolean enabled) { - mSlidingKeyInputPreview.setPreviewEnabled(enabled); + mSlidingKeyInputDrawingPreview.setPreviewEnabled(enabled); } @Override public void showSlidingKeyInputPreview(final PointerTracker tracker) { locatePreviewPlacerView(); - mSlidingKeyInputPreview.setPreviewPosition(tracker); + mSlidingKeyInputDrawingPreview.setPreviewPosition(tracker); } @Override public void dismissSlidingKeyInputPreview() { - mSlidingKeyInputPreview.dismissSlidingKeyInputPreview(); + mSlidingKeyInputDrawingPreview.dismissSlidingKeyInputPreview(); } private void setGesturePreviewMode(final boolean isGestureTrailEnabled, final boolean isGestureFloatingPreviewTextEnabled) { - mGestureFloatingPreviewText.setPreviewEnabled(isGestureFloatingPreviewTextEnabled); - mGestureTrailsPreview.setPreviewEnabled(isGestureTrailEnabled); + mGestureFloatingTextDrawingPreview.setPreviewEnabled(isGestureFloatingPreviewTextEnabled); + mGestureTrailsDrawingPreview.setPreviewEnabled(isGestureTrailEnabled); } + // Implements {@link DrawingHandler.Callbacks} method. + @Override public void showGestureFloatingPreviewText(final SuggestedWords suggestedWords) { locatePreviewPlacerView(); - mGestureFloatingPreviewText.setSuggetedWords(suggestedWords); + mGestureFloatingTextDrawingPreview.setSuggetedWords(suggestedWords); } public void dismissGestureFloatingPreviewText() { @@ -862,12 +511,13 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack final boolean showsFloatingPreviewText) { locatePreviewPlacerView(); if (showsFloatingPreviewText) { - mGestureFloatingPreviewText.setPreviewPosition(tracker); + mGestureFloatingTextDrawingPreview.setPreviewPosition(tracker); } - mGestureTrailsPreview.setPreviewPosition(tracker); + mGestureTrailsDrawingPreview.setPreviewPosition(tracker); } // Note that this method is called from a non-UI thread. + @SuppressWarnings("static-method") public void setMainDictionaryAvailability(final boolean mainDictionaryAvailable) { PointerTracker.setMainDictionaryAvailability(mainDictionaryAvailable); } @@ -883,34 +533,35 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - // Notify the ResearchLogger (development only diagnostics) that the keyboard view has - // been attached. This is needed to properly show the splash screen, which requires that - // the window token of the KeyboardView be non-null. - if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { - ResearchLogger.getInstance().mainKeyboardView_onAttachedToWindow(this); - } + installPreviewPlacerView(); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); - mPreviewPlacerView.removeAllViews(); - // Notify the ResearchLogger (development only diagnostics) that the keyboard view has - // been detached. This is needed to invalidate the reference of {@link MainKeyboardView} - // to null. - if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { - ResearchLogger.getInstance().mainKeyboardView_onDetachedFromWindow(); - } + mDrawingPreviewPlacerView.removeAllViews(); } private MoreKeysPanel onCreateMoreKeysPanel(final Key key, final Context context) { - if (key.getMoreKeys() == null) { + final MoreKeySpec[] moreKeys = key.getMoreKeys(); + if (moreKeys == null) { return null; } Keyboard moreKeysKeyboard = mMoreKeysKeyboardCache.get(key); if (moreKeysKeyboard == null) { - moreKeysKeyboard = new MoreKeysKeyboard.Builder( - context, key, this, mKeyPreviewDrawParams).build(); + // {@link KeyPreviewDrawParams#mPreviewVisibleWidth} should have been set at + // {@link KeyPreviewChoreographer#placeKeyPreview(Key,TextView,KeyboardIconsSet,KeyDrawParams,int,int[]}, + // though there may be some chances that the value is zero. <code>width == 0</code> + // will cause zero-division error at + // {@link MoreKeysKeyboardParams#setParameters(int,int,int,int,int,int,boolean,int)}. + final boolean isSingleMoreKeyWithPreview = mKeyPreviewDrawParams.isPopupEnabled() + && !key.noKeyPreview() && moreKeys.length == 1 + && mKeyPreviewDrawParams.getVisibleWidth() > 0; + final MoreKeysKeyboard.Builder builder = new MoreKeysKeyboard.Builder( + context, key, getKeyboard(), isSingleMoreKeyWithPreview, + mKeyPreviewDrawParams.getVisibleWidth(), + mKeyPreviewDrawParams.getVisibleHeight(), newLabelPaint(key)); + moreKeysKeyboard = builder.build(); mMoreKeysKeyboardCache.put(key, moreKeysKeyboard); } @@ -922,11 +573,13 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack return moreKeysKeyboardView; } + // Implements {@link TimerHandler.Callbacks} method. /** * Called when a key is long pressed. * @param tracker the pointer tracker which pressed the parent key */ - private void onLongPress(final PointerTracker tracker) { + @Override + public void onLongPress(final PointerTracker tracker) { if (isShowingMoreKeysPanel()) { return; } @@ -934,16 +587,13 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack if (key == null) { return; } - if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { - ResearchLogger.mainKeyboardView_onLongPress(); - } final KeyboardActionListener listener = mKeyboardActionListener; if (key.hasNoPanelAutoMoreKey()) { final int moreKeyCode = key.getMoreKeys()[0].mCode; tracker.onLongPressed(); listener.onPressKey(moreKeyCode, 0 /* repeatCount */, true /* isSinglePointer */); - listener.onCodeInput(moreKeyCode, - Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE); + listener.onCodeInput(moreKeyCode, Constants.NOT_A_COORDINATE, + Constants.NOT_A_COORDINATE, false /* isKeyRepeat */); listener.onReleaseKey(moreKeyCode, false /* withSliding */); return; } @@ -967,7 +617,8 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack final int[] lastCoords = CoordinateUtils.newInstance(); tracker.getLastCoordinates(lastCoords); - final boolean keyPreviewEnabled = isKeyPreviewPopupEnabled() && !key.noKeyPreview(); + final boolean keyPreviewEnabled = mKeyPreviewDrawParams.isPopupEnabled() + && !key.noKeyPreview(); // The more keys keyboard is usually horizontally aligned with the center of the parent key. // If showMoreKeysKeyboardAtTouchedPoint is true and the key preview is disabled, the more // keys keyboard is placed at the touch point of the parent key. @@ -979,26 +630,24 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack // aligned with the bottom edge of the visible part of the key preview. // {@code mPreviewVisibleOffset} has been set appropriately in // {@link KeyboardView#showKeyPreview(PointerTracker)}. - final int pointY = key.getY() + mKeyPreviewDrawParams.mPreviewVisibleOffset; + final int pointY = key.getY() + mKeyPreviewDrawParams.getVisibleOffset(); moreKeysPanel.showMoreKeysPanel(this, this, pointX, pointY, mKeyboardActionListener); tracker.onShowMoreKeysPanel(moreKeysPanel); + // TODO: Implement zoom in animation of more keys panel. + dismissKeyPreviewWithoutDelay(key); } - public boolean isInSlidingKeyInput() { + public boolean isInDraggingFinger() { if (isShowingMoreKeysPanel()) { return true; } - return PointerTracker.isAnyInSlidingKeyInput(); + return PointerTracker.isAnyInDraggingFinger(); } @Override public void onShowMoreKeysPanel(final MoreKeysPanel panel) { locatePreviewPlacerView(); - // TODO: Remove this check - if (panel.isShowingInParent()) { - panel.dismissMoreKeysPanel(); - } - mPreviewPlacerView.addView(panel.getContainerView()); + panel.showInParent(mDrawingPreviewPlacerView); mMoreKeysPanel = panel; dimEntireKeyboard(true /* dimmed */); } @@ -1008,15 +657,15 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack } @Override - public void onCancelMoreKeysPanel(final MoreKeysPanel panel) { + public void onCancelMoreKeysPanel() { PointerTracker.dismissAllMoreKeysPanels(); } @Override - public void onDismissMoreKeysPanel(final MoreKeysPanel panel) { + public void onDismissMoreKeysPanel() { dimEntireKeyboard(false /* dimmed */); if (isShowingMoreKeysPanel()) { - mPreviewPlacerView.removeView(mMoreKeysPanel.getContainerView()); + mMoreKeysPanel.removeFromParent(); mMoreKeysPanel = null; } } @@ -1034,14 +683,6 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack } @Override - public boolean dispatchTouchEvent(MotionEvent event) { - if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()) { - return AccessibleKeyboardViewProxy.getInstance().dispatchTouchEvent(event); - } - return super.dispatchTouchEvent(event); - } - - @Override public boolean onTouchEvent(final MotionEvent me) { if (getKeyboard() == null) { return false; @@ -1049,28 +690,26 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack if (mNonDistinctMultitouchHelper != null) { if (me.getPointerCount() > 1 && mKeyTimerHandler.isInKeyRepeat()) { // Key repeating timer will be canceled if 2 or more keys are in action. - mKeyTimerHandler.cancelKeyRepeatTimer(); + mKeyTimerHandler.cancelKeyRepeatTimers(); } // Non distinct multitouch screen support - mNonDistinctMultitouchHelper.processMotionEvent(me, this); + mNonDistinctMultitouchHelper.processMotionEvent(me, mKeyDetector); return true; } return processMotionEvent(me); } public boolean processMotionEvent(final MotionEvent me) { - if (LatinImeLogger.sUsabilityStudy) { - UsabilityStudyLogUtils.writeMotionEvent(me); - } - // Currently the same "move" event is being logged twice. - if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { - ResearchLogger.mainKeyboardView_processMotionEvent(me); - } - final int index = me.getActionIndex(); final int id = me.getPointerId(index); - final PointerTracker tracker = PointerTracker.getPointerTracker(id, this); - tracker.processMotionEvent(me, this); + final PointerTracker tracker = PointerTracker.getPointerTracker(id); + // When a more keys panel is showing, we should ignore other fingers' single touch events + // other than the finger that is showing the more keys panel. + if (isShowingMoreKeysPanel() && !tracker.isShowingMoreKeysPanel() + && PointerTracker.getActivePointerTrackerCount() == 1) { + return true; + } + tracker.processMotionEvent(me, mKeyDetector); return true; } @@ -1089,22 +728,24 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack mMoreKeysKeyboardCache.clear(); } + public void onHideWindow() { + onDismissMoreKeysPanel(); + final MainKeyboardAccessibilityDelegate accessibilityDelegate = mAccessibilityDelegate; + if (accessibilityDelegate != null) { + accessibilityDelegate.onHideWindow(); + } + } + /** - * Receives hover events from the input framework. - * - * @param event The motion event to be dispatched. - * @return {@code true} if the event was handled by the view, {@code false} - * otherwise + * {@inheritDoc} */ @Override - public boolean dispatchHoverEvent(final MotionEvent event) { - if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()) { - final PointerTracker tracker = PointerTracker.getPointerTracker(0, this); - return AccessibleKeyboardViewProxy.getInstance().dispatchHoverEvent(event, tracker); + public boolean onHoverEvent(final MotionEvent event) { + final MainKeyboardAccessibilityDelegate accessibilityDelegate = mAccessibilityDelegate; + if (accessibilityDelegate != null) { + return accessibilityDelegate.onHoverEvent(event); } - - // Reflection doesn't support calling superclass methods. - return false; + return super.onHoverEvent(event); } public void updateShortcutKey(final boolean available) { @@ -1121,14 +762,16 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack } public void startDisplayLanguageOnSpacebar(final boolean subtypeChanged, - final boolean needsToDisplayLanguage, final boolean hasMultipleEnabledIMEsOrSubtypes) { - mNeedsToDisplayLanguage = needsToDisplayLanguage; + final int languageOnSpacebarFormatType, + final boolean hasMultipleEnabledIMEsOrSubtypes) { + mLanguageOnSpacebarFormatType = languageOnSpacebarFormatType; mHasMultipleEnabledIMEsOrSubtypes = hasMultipleEnabledIMEsOrSubtypes; final ObjectAnimator animator = mLanguageOnSpacebarFadeoutAnimator; if (animator == null) { - mNeedsToDisplayLanguage = false; + mLanguageOnSpacebarFormatType = LanguageOnSpacebarHelper.FORMAT_TYPE_NONE; } else { - if (subtypeChanged && needsToDisplayLanguage) { + if (subtypeChanged + && languageOnSpacebarFormatType != LanguageOnSpacebarHelper.FORMAT_TYPE_NONE) { setLanguageOnSpacebarAnimAlpha(Constants.Color.ALPHA_OPAQUE); if (animator.isStarted()) { animator.cancel(); @@ -1143,14 +786,6 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack invalidateKey(mSpaceKey); } - public void updateAutoCorrectionState(final boolean isAutoCorrection) { - if (!mAutoCorrectionSpacebarLedEnabled) { - return; - } - mAutoCorrectionSpacebarLedOn = isAutoCorrection; - invalidateKey(mSpaceKey); - } - private void dimEntireKeyboard(final boolean dimmed) { final boolean needsRedrawing = mNeedsToDimEntireKeyboard != dimmed; mNeedsToDimEntireKeyboard = dimmed; @@ -1175,25 +810,26 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack if (key.altCodeWhileTyping() && key.isEnabled()) { params.mAnimAlpha = mAltCodeKeyWhileTypingAnimAlpha; } + super.onDrawKeyTopVisuals(key, canvas, paint, params); final int code = key.getCode(); if (code == Constants.CODE_SPACE) { - drawSpacebar(key, canvas, paint); + // If input language are explicitly selected. + if (mLanguageOnSpacebarFormatType != LanguageOnSpacebarHelper.FORMAT_TYPE_NONE) { + drawLanguageOnSpacebar(key, canvas, paint); + } // Whether space key needs to show the "..." popup hint for special purposes if (key.isLongPressEnabled() && mHasMultipleEnabledIMEsOrSubtypes) { drawKeyPopupHint(key, canvas, paint, params); } } else if (code == Constants.CODE_LANGUAGE_SWITCH) { - super.onDrawKeyTopVisuals(key, canvas, paint, params); drawKeyPopupHint(key, canvas, paint, params); - } else { - super.onDrawKeyTopVisuals(key, canvas, paint, params); } } private boolean fitsTextIntoWidth(final int width, final String text, final Paint paint) { final int maxTextWidth = width - mLanguageOnSpacebarHorizontalMargin * 2; paint.setTextScaleX(1.0f); - final float textWidth = TypefaceUtils.getLabelWidth(text, paint); + final float textWidth = TypefaceUtils.getStringWidth(text, paint); if (textWidth < width) { return true; } @@ -1204,74 +840,56 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack } paint.setTextScaleX(scaleX); - return TypefaceUtils.getLabelWidth(text, paint) < maxTextWidth; + return TypefaceUtils.getStringWidth(text, paint) < maxTextWidth; } // Layout language name on spacebar. private String layoutLanguageOnSpacebar(final Paint paint, final InputMethodSubtype subtype, final int width) { - // Choose appropriate language name to fit into the width. - final String fullText = SubtypeLocaleUtils.getFullDisplayName(subtype); - if (fitsTextIntoWidth(width, fullText, paint)) { - return fullText; + if (mLanguageOnSpacebarFormatType == LanguageOnSpacebarHelper.FORMAT_TYPE_FULL_LOCALE) { + final String fullText = SpacebarLanguageUtils.getFullDisplayName(subtype); + if (fitsTextIntoWidth(width, fullText, paint)) { + return fullText; + } } - final String middleText = SubtypeLocaleUtils.getMiddleDisplayName(subtype); + final String middleText = SpacebarLanguageUtils.getMiddleDisplayName(subtype); if (fitsTextIntoWidth(width, middleText, paint)) { return middleText; } - final String shortText = SubtypeLocaleUtils.getShortDisplayName(subtype); - if (fitsTextIntoWidth(width, shortText, paint)) { - return shortText; - } - return ""; } - private void drawSpacebar(final Key key, final Canvas canvas, final Paint paint) { + private void drawLanguageOnSpacebar(final Key key, final Canvas canvas, final Paint paint) { final int width = key.getWidth(); final int height = key.getHeight(); - - // If input language are explicitly selected. - if (mNeedsToDisplayLanguage) { - paint.setTextAlign(Align.CENTER); - paint.setTypeface(Typeface.DEFAULT); - paint.setTextSize(mSpacebarTextSize); - final InputMethodSubtype subtype = getKeyboard().mId.mSubtype; - final String language = layoutLanguageOnSpacebar(paint, subtype, width); - // Draw language text with shadow - final float descent = paint.descent(); - final float textHeight = -paint.ascent() + descent; - final float baseline = height / 2 + textHeight / 2; - paint.setColor(mSpacebarTextShadowColor); - paint.setAlpha(mLanguageOnSpacebarAnimAlpha); - canvas.drawText(language, width / 2, baseline - descent - 1, paint); - paint.setColor(mSpacebarTextColor); - paint.setAlpha(mLanguageOnSpacebarAnimAlpha); - canvas.drawText(language, width / 2, baseline - descent, paint); - } - - // Draw the spacebar icon at the bottom - if (mAutoCorrectionSpacebarLedOn) { - final int iconWidth = width * SPACE_LED_LENGTH_PERCENT / 100; - final int iconHeight = mAutoCorrectionSpacebarLedIcon.getIntrinsicHeight(); - int x = (width - iconWidth) / 2; - int y = height - iconHeight; - drawIcon(canvas, mAutoCorrectionSpacebarLedIcon, x, y, iconWidth, iconHeight); - } else if (mSpaceIcon != null) { - final int iconWidth = mSpaceIcon.getIntrinsicWidth(); - final int iconHeight = mSpaceIcon.getIntrinsicHeight(); - int x = (width - iconWidth) / 2; - int y = height - iconHeight; - drawIcon(canvas, mSpaceIcon, x, y, iconWidth, iconHeight); + paint.setTextAlign(Align.CENTER); + paint.setTypeface(Typeface.DEFAULT); + paint.setTextSize(mLanguageOnSpacebarTextSize); + final InputMethodSubtype subtype = getKeyboard().mId.mSubtype; + final String language = layoutLanguageOnSpacebar(paint, subtype, width); + // Draw language text with shadow + final float descent = paint.descent(); + final float textHeight = -paint.ascent() + descent; + final float baseline = height / 2 + textHeight / 2; + if (mLanguageOnSpacebarTextShadowRadius > 0.0f) { + paint.setShadowLayer(mLanguageOnSpacebarTextShadowRadius, 0, 0, + mLanguageOnSpacebarTextShadowColor); + } else { + paint.clearShadowLayer(); } + paint.setColor(mLanguageOnSpacebarTextColor); + paint.setAlpha(mLanguageOnSpacebarAnimAlpha); + canvas.drawText(language, width / 2, baseline - descent, paint); + paint.clearShadowLayer(); + paint.setTextScaleX(1.0f); } @Override public void deallocateMemory() { super.deallocateMemory(); - mGestureTrailsPreview.deallocateMemory(); + mDrawingPreviewPlacerView.deallocateMemory(); } } |