Refactor PointerTracker and MainKeyboardView

This CL reorganize the key press/release state visual drawing code.

Change-Id: I4aa10f57309ae2f81333a1e2bd863c23a7a41d82
main
Tadashi G. Takaoka 2014-10-30 13:10:59 +09:00
parent 4195567d24
commit 53b6d627e7
5 changed files with 112 additions and 122 deletions

View File

@ -269,13 +269,9 @@ public final class MainKeyboardAccessibilityDelegate
eventTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0 /* metaState */);
// Inject a fake down event to {@link PointerTracker} to handle a long press correctly.
tracker.processMotionEvent(downEvent, mKeyDetector);
// The above fake down event triggers an unnecessary long press timer that should be
// canceled.
tracker.cancelLongPressTimer();
downEvent.recycle();
// Invoke {@link MainKeyboardView#onLongPress(PointerTracker)} as if a long press timeout
// has passed.
mKeyboardView.onLongPress(tracker);
// Invoke {@link PointerTracker#onLongPressed()} as if a long press timeout has passed.
tracker.onLongPressed();
// If {@link Key#hasNoPanelAutoMoreKeys()} is true (such as "0 +" key on the phone layout)
// or a key invokes IME switcher dialog, we should just ignore the next
// {@link #onRegisterHoverKey(Key,MotionEvent)}. It can be determined by whether

View File

@ -461,12 +461,17 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy
windowContentView.addView(mDrawingPreviewPlacerView);
}
// Implements {@link DrawingProxy#onKeyPressed(Key,boolean)}.
@Override
public void showKeyPreview(@Nonnull final Key key) {
// If the key is invalid or has no key preview, we must not show key preview.
if (key.noKeyPreview()) {
return;
public void onKeyPressed(@Nonnull final Key key, final boolean withPreview) {
key.onPressed();
invalidateKey(key);
if (withPreview && !key.noKeyPreview()) {
showKeyPreview(key);
}
}
private void showKeyPreview(@Nonnull final Key key) {
final Keyboard keyboard = getKeyboard();
if (keyboard == null) {
return;
@ -483,15 +488,26 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy
getWidth(), mOriginCoords, mDrawingPreviewPlacerView, isHardwareAccelerated());
}
// Implements {@link DrawingProxy#dismissKeyPreviewWithoutDelay(Key)}.
@Override
public void dismissKeyPreviewWithoutDelay(@Nonnull final Key key) {
private void dismissKeyPreviewWithoutDelay(@Nonnull final Key key) {
mKeyPreviewChoreographer.dismissKeyPreview(key, false /* withAnimation */);
invalidateKey(key);
}
// Implements {@link DrawingProxy#onKeyReleased(Key,boolean)}.
@Override
public void dismissKeyPreview(@Nonnull final Key key) {
public void onKeyReleased(@Nonnull final Key key, final boolean withAnimation) {
key.onReleased();
invalidateKey(key);
if (!key.noKeyPreview()) {
if (withAnimation) {
dismissKeyPreview(key);
} else {
dismissKeyPreviewWithoutDelay(key);
}
}
}
private void dismissKeyPreview(@Nonnull final Key key) {
if (isHardwareAccelerated()) {
mKeyPreviewChoreographer.dismissKeyPreview(key, true /* withAnimation */);
return;
@ -574,7 +590,11 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy
mDrawingPreviewPlacerView.removeAllViews();
}
private MoreKeysPanel onCreateMoreKeysPanel(final Key key, final Context context) {
// Implements {@link DrawingProxy@showMoreKeysKeyboard(Key,PointerTracker)}.
@Override
@Nullable
public MoreKeysPanel showMoreKeysKeyboard(@Nonnull final Key key,
@Nonnull final PointerTracker tracker) {
final MoreKeySpec[] moreKeys = key.getMoreKeys();
if (moreKeys == null) {
return null;
@ -590,7 +610,7 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy
&& !key.noKeyPreview() && moreKeys.length == 1
&& mKeyPreviewDrawParams.getVisibleWidth() > 0;
final MoreKeysKeyboard.Builder builder = new MoreKeysKeyboard.Builder(
context, key, getKeyboard(), isSingleMoreKeyWithPreview,
getContext(), key, getKeyboard(), isSingleMoreKeyWithPreview,
mKeyPreviewDrawParams.getVisibleWidth(),
mKeyPreviewDrawParams.getVisibleHeight(), newLabelPaint(key));
moreKeysKeyboard = builder.build();
@ -603,50 +623,6 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy
(MoreKeysKeyboardView)container.findViewById(R.id.more_keys_keyboard_view);
moreKeysKeyboardView.setKeyboard(moreKeysKeyboard);
container.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
return moreKeysKeyboardView;
}
// Implements {@link DrawingProxy@onLongPress(PointerTracker)}.
/**
* Called when a key is long pressed.
* @param tracker the pointer tracker which pressed the parent key
*/
@Override
public void onLongPress(@Nonnull final PointerTracker tracker) {
if (isShowingMoreKeysPanel()) {
return;
}
final Key key = tracker.getKey();
if (key == null) {
return;
}
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, false /* isKeyRepeat */);
listener.onReleaseKey(moreKeyCode, false /* withSliding */);
return;
}
final int code = key.getCode();
if (code == Constants.CODE_SPACE || code == Constants.CODE_LANGUAGE_SWITCH) {
// Long pressing the space key invokes IME switcher dialog.
if (listener.onCustomRequest(Constants.CUSTOM_CODE_SHOW_INPUT_METHOD_PICKER)) {
tracker.onLongPressed();
listener.onReleaseKey(code, false /* withSliding */);
return;
}
}
openMoreKeysPanel(key, tracker);
}
private void openMoreKeysPanel(final Key key, final PointerTracker tracker) {
final MoreKeysPanel moreKeysPanel = onCreateMoreKeysPanel(key, getContext());
if (moreKeysPanel == null) {
return;
}
final int[] lastCoords = CoordinateUtils.newInstance();
tracker.getLastCoordinates(lastCoords);
@ -664,10 +640,8 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy
// {@code mPreviewVisibleOffset} has been set appropriately in
// {@link KeyboardView#showKeyPreview(PointerTracker)}.
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.
mKeyPreviewChoreographer.dismissKeyPreview(key, false /* withAnimation */);
moreKeysKeyboardView.showMoreKeysPanel(this, this, pointX, pointY, mKeyboardActionListener);
return moreKeysKeyboardView;
}
public boolean isInDraggingFinger() {

View File

@ -222,7 +222,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
final int trackersSize = sTrackers.size();
for (int i = 0; i < trackersSize; ++i) {
final PointerTracker tracker = sTrackers.get(i);
tracker.setReleasedKeyGraphics(tracker.getKey());
tracker.setReleasedKeyGraphics(tracker.getKey(), true /* withAnimation */);
}
}
@ -382,19 +382,18 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
return mKeyDetector.detectHitKey(x, y);
}
private void setReleasedKeyGraphics(@Nullable final Key key) {
private void setReleasedKeyGraphics(@Nullable final Key key, final boolean withAnimation) {
if (key == null) {
return;
}
sDrawingProxy.dismissKeyPreview(key);
// Even if the key is disabled, update the key release graphics just in case.
updateReleaseKeyGraphics(key);
sDrawingProxy.onKeyReleased(key, withAnimation);
if (key.isShift()) {
for (final Key shiftKey : mKeyboard.mShiftKeys) {
if (shiftKey != key) {
updateReleaseKeyGraphics(shiftKey);
sDrawingProxy.onKeyReleased(shiftKey, false /* withAnimation */);
}
}
}
@ -403,11 +402,11 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
final int altCode = key.getAltCode();
final Key altKey = mKeyboard.getKey(altCode);
if (altKey != null) {
updateReleaseKeyGraphics(altKey);
sDrawingProxy.onKeyReleased(altKey, false /* withAnimation */);
}
for (final Key k : mKeyboard.mAltCodeKeysWhileTyping) {
if (k != key && k.getAltCode() == altCode) {
updateReleaseKeyGraphics(k);
sDrawingProxy.onKeyReleased(k, false /* withAnimation */);
}
}
}
@ -418,7 +417,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
return sTypingTimeRecorder.needsToSuppressKeyPreviewPopup(eventTime);
}
private void setPressedKeyGraphics(final Key key, final long eventTime) {
private void setPressedKeyGraphics(@Nullable final Key key, final long eventTime) {
if (key == null) {
return;
}
@ -430,15 +429,13 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
return;
}
if (!key.noKeyPreview() && !sInGesture && !needsToSuppressKeyPreviewPopup(eventTime)) {
sDrawingProxy.showKeyPreview(key);
}
updatePressKeyGraphics(key);
final boolean noKeyPreview = sInGesture || needsToSuppressKeyPreviewPopup(eventTime);
sDrawingProxy.onKeyPressed(key, !noKeyPreview);
if (key.isShift()) {
for (final Key shiftKey : mKeyboard.mShiftKeys) {
if (shiftKey != key) {
updatePressKeyGraphics(shiftKey);
sDrawingProxy.onKeyPressed(shiftKey, false /* withPreview */);
}
}
}
@ -447,26 +444,16 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
final int altCode = key.getAltCode();
final Key altKey = mKeyboard.getKey(altCode);
if (altKey != null) {
updatePressKeyGraphics(altKey);
sDrawingProxy.onKeyPressed(altKey, false /* withPreview */);
}
for (final Key k : mKeyboard.mAltCodeKeysWhileTyping) {
if (k != key && k.getAltCode() == altCode) {
updatePressKeyGraphics(k);
sDrawingProxy.onKeyPressed(k, false /* withPreview */);
}
}
}
}
private static void updateReleaseKeyGraphics(final Key key) {
key.onReleased();
sDrawingProxy.invalidateKey(key);
}
private static void updatePressKeyGraphics(final Key key) {
key.onPressed();
sDrawingProxy.invalidateKey(key);
}
public GestureStrokeDrawingPoints getGestureStrokeDrawingPoints() {
return mGestureStrokeDrawingPoints;
}
@ -837,7 +824,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
}
private void processDraggingFingerOutFromOldKey(final Key oldKey) {
setReleasedKeyGraphics(oldKey);
setReleasedKeyGraphics(oldKey, true /* withAnimation */);
callListenerOnRelease(oldKey, oldKey.getCode(), true /* withSliding */);
startKeySelectionByDraggingFinger(oldKey);
sTimerProxy.cancelKeyTimersOf(this);
@ -880,12 +867,12 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
}
onUpEvent(x, y, eventTime);
cancelTrackingForAction();
setReleasedKeyGraphics(oldKey);
setReleasedKeyGraphics(oldKey, true /* withAnimation */);
} else {
if (!mIsDetectingGesture) {
cancelTrackingForAction();
}
setReleasedKeyGraphics(oldKey);
setReleasedKeyGraphics(oldKey, true /* withAnimation */);
}
}
@ -913,7 +900,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
onGestureMoveEvent(x, y, eventTime, true /* isMajorEvent */, newKey);
if (sInGesture) {
mCurrentKey = null;
setReleasedKeyGraphics(oldKey);
setReleasedKeyGraphics(oldKey, true /* withAnimation */);
return;
}
}
@ -978,7 +965,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
final int currentRepeatingKeyCode = mCurrentRepeatingKeyCode;
mCurrentRepeatingKeyCode = Constants.NOT_A_CODE;
// Release the last pressed key.
setReleasedKeyGraphics(currentKey);
setReleasedKeyGraphics(currentKey, true /* withAnimation */);
if (isShowingMoreKeysPanel()) {
if (!mIsTrackingForActionDisabled) {
@ -1015,14 +1002,6 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
}
}
public void onShowMoreKeysPanel(final MoreKeysPanel panel) {
setReleasedKeyGraphics(mCurrentKey);
final int translatedX = panel.translateX(mLastX);
final int translatedY = panel.translateY(mLastY);
panel.onDownEvent(translatedX, translatedY, mPointerId, SystemClock.uptimeMillis());
mMoreKeysPanel = panel;
}
@Override
public void cancelTrackingForAction() {
if (isShowingMoreKeysPanel()) {
@ -1035,14 +1014,49 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
return !mIsTrackingForActionDisabled;
}
public void cancelLongPressTimer() {
public void onLongPressed() {
sTimerProxy.cancelLongPressTimersOf(this);
if (isShowingMoreKeysPanel()) {
return;
}
final Key key = getKey();
if (key == null) {
return;
}
if (key.hasNoPanelAutoMoreKey()) {
cancelKeyTracking();
final int moreKeyCode = key.getMoreKeys()[0].mCode;
sListener.onPressKey(moreKeyCode, 0 /* repeatCont */, true /* isSinglePointer */);
sListener.onCodeInput(moreKeyCode, Constants.NOT_A_COORDINATE,
Constants.NOT_A_COORDINATE, false /* isKeyRepeat */);
sListener.onReleaseKey(moreKeyCode, false /* withSliding */);
return;
}
final int code = key.getCode();
if (code == Constants.CODE_SPACE || code == Constants.CODE_LANGUAGE_SWITCH) {
// Long pressing the space key invokes IME switcher dialog.
if (sListener.onCustomRequest(Constants.CUSTOM_CODE_SHOW_INPUT_METHOD_PICKER)) {
cancelKeyTracking();
sListener.onReleaseKey(code, false /* withSliding */);
return;
}
}
public void onLongPressed() {
setReleasedKeyGraphics(key, false /* withAnimation */);
final MoreKeysPanel moreKeysPanel = sDrawingProxy.showMoreKeysKeyboard(key, this);
if (moreKeysPanel == null) {
return;
}
final int translatedX = moreKeysPanel.translateX(mLastX);
final int translatedY = moreKeysPanel.translateY(mLastY);
moreKeysPanel.onDownEvent(translatedX, translatedY, mPointerId, SystemClock.uptimeMillis());
mMoreKeysPanel = moreKeysPanel;
}
private void cancelKeyTracking() {
resetKeySelectionByDraggingFinger();
cancelTrackingForAction();
setReleasedKeyGraphics(mCurrentKey);
setReleasedKeyGraphics(mCurrentKey, true /* withAnimation */);
sPointerTrackerQueue.remove(this);
}
@ -1059,7 +1073,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element,
private void onCancelEventInternal() {
sTimerProxy.cancelKeyTimersOf(this);
setReleasedKeyGraphics(mCurrentKey);
setReleasedKeyGraphics(mCurrentKey, true /* withAnimation */);
resetKeySelectionByDraggingFinger();
dismissMoreKeysPanel();
}

View File

@ -17,29 +17,36 @@
package com.android.inputmethod.keyboard.internal;
import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.MoreKeysPanel;
import com.android.inputmethod.keyboard.PointerTracker;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public interface DrawingProxy {
// TODO: Remove this method.
public void invalidateKey(@Nullable Key key);
// TODO: Rename this method to onKeyPressed.
public void showKeyPreview(@Nonnull Key key);
// TODO: Rename this method to onKeyReleased.
public void dismissKeyPreview(@Nonnull Key key);
/**
* Called when a key is being pressed.
* @param key the {@link Key} that is being pressed.
* @param withPreview true if key popup preview should be displayed.
*/
public void onKeyPressed(@Nonnull Key key, boolean withPreview);
/**
* Dismiss a key preview visual without delay.
* @param key the key whose preview visual should be dismissed.
* Called when a key is being released.
* @param key the {@link Key} that is being released.
* @param withAnimation when true, key popup preview should be dismissed with animation.
*/
public void dismissKeyPreviewWithoutDelay(@Nonnull Key key);
public void onKeyReleased(@Nonnull Key key, boolean withAnimation);
// TODO: Rename this method to onKeyLongPressed.
public void onLongPress(@Nonnull PointerTracker tracker);
/**
* Start showing more keys keyboard of a key that is being long pressed.
* @param key the {@link Key} that is being long pressed and showing more keys keyboard.
* @param tracker the {@link PointerTracker} that detects this long pressing.
* @return {@link MoreKeysPanel} that is being shown. null if there is no need to show more keys
* keyboard.
*/
@Nullable
public MoreKeysPanel showMoreKeysKeyboard(@Nonnull Key key, @Nonnull PointerTracker tracker);
/**
* Start a while-typing-animation.

View File

@ -66,7 +66,7 @@ public final class TimerHandler extends LeakGuardHandlerWrapper<DrawingProxy>
case MSG_LONGPRESS_SHIFT_KEY:
cancelLongPressTimers();
final PointerTracker tracker2 = (PointerTracker) msg.obj;
drawingProxy.onLongPress(tracker2);
tracker2.onLongPressed();
break;
case MSG_UPDATE_BATCH_INPUT:
final PointerTracker tracker3 = (PointerTracker) msg.obj;
@ -74,8 +74,7 @@ public final class TimerHandler extends LeakGuardHandlerWrapper<DrawingProxy>
startUpdateBatchInputTimer(tracker3);
break;
case MSG_DISMISS_KEY_PREVIEW:
final Key key = (Key) msg.obj;
drawingProxy.dismissKeyPreviewWithoutDelay(key);
drawingProxy.onKeyReleased((Key) msg.obj, false /* withAnimation */);
break;
case MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT:
drawingProxy.dismissGestureFloatingPreviewTextWithoutDelay();