Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 53b6d627 authored by Tadashi G. Takaoka's avatar Tadashi G. Takaoka
Browse files

Refactor PointerTracker and MainKeyboardView

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

Change-Id: I4aa10f57309ae2f81333a1e2bd863c23a7a41d82
parent 4195567d
Loading
Loading
Loading
Loading
+2 −6
Original line number Diff line number Diff line
@@ -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
+32 −58
Original line number Diff line number Diff line
@@ -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() {
+56 −42
Original line number Diff line number Diff line
@@ -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,24 +444,14 @@ 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() {
@@ -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();
    }
+20 −13
Original line number Diff line number Diff line
@@ -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.
+2 −3
Original line number Diff line number Diff line
@@ -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();