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

Commit 3491c877 authored by Tadashi G. Takaoka's avatar Tadashi G. Takaoka Committed by Android (Google) Code Review
Browse files

Merge "Queuing PointerTracker to support n-key roll-over and shift modifier." into gingerbread

parents 8f5b0ccc 40a05f62
Loading
Loading
Loading
Loading
+26 −3
Original line number Diff line number Diff line
@@ -227,6 +227,9 @@ public class LatinIME extends InputMethodService
    private int mDeleteCount;
    private long mLastKeyTime;

    // Shift modifier key state
    private ModifierKeyState mShiftKeyState = new ModifierKeyState();

    private Tutorial mTutorial;

    private AudioManager mAudioManager;
@@ -976,7 +979,8 @@ public class LatinIME extends InputMethodService
    public void updateShiftKeyState(EditorInfo attr) {
        InputConnection ic = getCurrentInputConnection();
        if (ic != null && attr != null && mKeyboardSwitcher.isAlphabetMode()) {
            mKeyboardSwitcher.setShifted(mCapsLock || getCursorCapsMode(ic, attr) != 0);
            mKeyboardSwitcher.setShifted(mShiftKeyState.isMomentary() || mCapsLock
                    || getCursorCapsMode(ic, attr) != 0);
        }
    }

@@ -1233,12 +1237,20 @@ public class LatinIME extends InputMethodService
        ic.endBatchEdit();
    }

    private void resetShift() {
        handleShiftInternal(true);
    }

    private void handleShift() {
        handleShiftInternal(false);
    }

    private void handleShiftInternal(boolean forceNormal) {
        mHandler.removeMessages(MSG_UPDATE_SHIFT_STATE);
        KeyboardSwitcher switcher = mKeyboardSwitcher;
        LatinKeyboardView inputView = switcher.getInputView();
        if (switcher.isAlphabetMode()) {
            if (mCapsLock) {
            if (mCapsLock || forceNormal) {
                mCapsLock = false;
                switcher.setShifted(false);
            } else if (inputView != null) {
@@ -2146,15 +2158,26 @@ public class LatinIME extends InputMethodService
        vibrate();
        playKeyClick(primaryCode);
        if (primaryCode == Keyboard.KEYCODE_SHIFT) {
            mShiftKeyState.onPress();
            handleShift();
        }
        } else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE) {
            // TODO: We should handle KEYCODE_MODE_CHANGE (symbol) here as well.
        } else {
            mShiftKeyState.onOtherKeyPressed();
        }
    }

    public void onRelease(int primaryCode) {
        // Reset any drag flags in the keyboard
        ((LatinKeyboard) mKeyboardSwitcher.getInputView().getKeyboard()).keyReleased();
        //vibrate();
        if (primaryCode == Keyboard.KEYCODE_SHIFT) {
            if (mShiftKeyState.isMomentary())
                resetShift();
            mShiftKeyState.onRelease();
        } else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE) {
            // TODO: We should handle KEYCODE_MODE_CHANGE (symbol) here as well.
        }
    }

    private FieldContext makeFieldContext() {
+64 −3
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.inputmethodservice.Keyboard.Key;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.GestureDetector;
import android.view.Gravity;
@@ -45,6 +46,7 @@ import android.widget.TextView;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

/**
@@ -62,6 +64,7 @@ import java.util.Map;
 */
public class LatinKeyboardBaseView extends View implements View.OnClickListener,
        PointerTracker.UIProxy {
    private static final String TAG = "LatinKeyboardBaseView";
    private static final boolean DEBUG = false;

    public static final int NOT_A_TOUCH_COORDINATE = -1;
@@ -199,6 +202,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener,
    private OnKeyboardActionListener mKeyboardActionListener;

    private final ArrayList<PointerTracker> mPointerTrackers = new ArrayList<PointerTracker>();
    private final PointerQueue mPointerQueue = new PointerQueue();
    private final float mDebounceHysteresis;

    protected KeyDetector mKeyDetector = new ProximityKeyDetector();
@@ -316,6 +320,41 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener,
        }
    };

    static class PointerQueue {
        private LinkedList<PointerTracker> mQueue = new LinkedList<PointerTracker>();

        public void add(PointerTracker tracker) {
            mQueue.add(tracker);
        }

        public int lastIndexOf(PointerTracker tracker) {
            LinkedList<PointerTracker> queue = mQueue;
            for (int index = queue.size() - 1; index >= 0; index--) {
                PointerTracker t = queue.get(index);
                if (t == tracker)
                    return index;
            }
            return -1;
        }

        public void releasePointersOlderThan(PointerTracker tracker, long eventTime) {
            LinkedList<PointerTracker> queue = mQueue;
            int oldestPos = 0;
            for (PointerTracker t = queue.get(oldestPos); t != tracker; t = queue.get(oldestPos)) {
                if (t.isModifier()) {
                    oldestPos++;
                } else {
                    t.onUpEvent(t.getLastX(), t.getLastY(), eventTime);
                    queue.remove(oldestPos);
                }
            }
        }

        public void remove(PointerTracker tracker) {
            mQueue.remove(tracker);
        }
    }

    public LatinKeyboardBaseView(Context context, AttributeSet attrs) {
        this(context, attrs, R.attr.keyboardViewStyle);
    }
@@ -1107,14 +1146,14 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener,
            switch (action) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_POINTER_DOWN:
                tracker.onDownEvent(touchX, touchY, eventTime);
                onDownEvent(tracker, touchX, touchY, eventTime);
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_POINTER_UP:
                tracker.onUpEvent(touchX, touchY, eventTime);
                onUpEvent(tracker, touchX, touchY, eventTime);
                break;
            case MotionEvent.ACTION_CANCEL:
                tracker.onCancelEvent(touchX, touchY, eventTime);
                onCancelEvent(tracker, touchX, touchY, eventTime);
                break;
            }
        }
@@ -1122,6 +1161,28 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener,
        return true;
    }

    private void onDownEvent(PointerTracker tracker, int touchX, int touchY, long eventTime) {
        tracker.onDownEvent(touchX, touchY, eventTime);
        mPointerQueue.add(tracker);
    }

    private void onUpEvent(PointerTracker tracker, int touchX, int touchY, long eventTime) {
        int index = mPointerQueue.lastIndexOf(tracker);
        if (index >= 0) {
            mPointerQueue.releasePointersOlderThan(tracker, eventTime);
        } else {
            Log.w(TAG, "onUpEvent: corresponding down event not found for pointer "
                    + tracker.mPointerId);
        }
        tracker.onUpEvent(touchX, touchY, eventTime);
        mPointerQueue.remove(tracker);
    }

    private void onCancelEvent(PointerTracker tracker, int touchX, int touchY, long eventTime) {
        tracker.onCancelEvent(touchX, touchY, eventTime);
        mPointerQueue.remove(tracker);
    }

    protected void swipeRight() {
        mKeyboardActionListener.swipeRight();
    }
+42 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.android.inputmethod.latin;

class ModifierKeyState {
    private static final int RELEASING = 0;
    private static final int PRESSING = 1;
    private static final int MOMENTARY = 2;

    private int mState = RELEASING;

    public void onPress() {
        mState = PRESSING;
    }

    public void onRelease() {
        mState = RELEASING;
    }

    public void onOtherKeyPressed() {
        if (mState == PRESSING)
            mState = MOMENTARY;
    }

    public boolean isMomentary() {
        return mState == MOMENTARY;
    }
}
+21 −1
Original line number Diff line number Diff line
@@ -21,9 +21,13 @@ import com.android.inputmethod.latin.LatinKeyboardBaseView.UIHandler;

import android.inputmethodservice.Keyboard;
import android.inputmethodservice.Keyboard.Key;
import android.util.Log;
import android.view.ViewConfiguration;

public class PointerTracker {
    private static final String TAG = "PointerTracker";
    private static final boolean DEBUG = false;

    public interface UIProxy {
        public void invalidateKey(Key key);
        public void showPreview(int keyIndex, PointerTracker tracker);
@@ -108,6 +112,15 @@ public class PointerTracker {
        return isValidKeyIndex(keyIndex) ? mKeys[keyIndex] : null;
    }

    public boolean isModifier() {
        Key key = getKey(mCurrentKey);
        if (key == null)
            return false;
        int primaryCode = key.codes[0];
        // TODO: KEYCODE_MODE_CHANGE (symbol) will be also a modifier key
        return primaryCode == Keyboard.KEYCODE_SHIFT;
    }

    public void updateKey(int keyIndex) {
        int oldKeyIndex = mPreviousKey;
        mPreviousKey = keyIndex;
@@ -146,6 +159,8 @@ public class PointerTracker {
        }
        showKeyPreviewAndUpdateKey(keyIndex);
        updateMoveDebouncing(touchX, touchY);
        if (DEBUG)
            Log.d(TAG, "onDownEvent: [" + mPointerId + "] modifier=" + isModifier());
    }

    public void onMoveEvent(int touchX, int touchY, long eventTime) {
@@ -178,6 +193,8 @@ public class PointerTracker {
    }

    public void onUpEvent(int touchX, int touchY, long eventTime) {
        if (DEBUG)
            Log.d(TAG, "onUpEvent: [" + mPointerId + "] modifier=" + isModifier());
        int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null);
        boolean wasInKeyRepeat = mHandler.isInKeyRepeat();
        mHandler.cancelKeyTimers();
@@ -204,6 +221,8 @@ public class PointerTracker {
    }

    public void onCancelEvent(int touchX, int touchY, long eventTime) {
        if (DEBUG)
            Log.d(TAG, "onCancelEvent: [" + mPointerId + "]");
        mHandler.cancelKeyTimers();
        mHandler.cancelPopupPreview();
        mProxy.dismissPopupKeyboard();
@@ -305,6 +324,7 @@ public class PointerTracker {

    private void showKeyPreviewAndUpdateKey(int keyIndex) {
        updateKey(keyIndex);
        if (!isModifier())
            mProxy.showPreview(keyIndex, this);
    }