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

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

Support multi-touch only when device has distinct multi-touch panel

Bug: 2973373
Change-Id: I9871c09ec8c1c2aa945d97392e61ee1ec585baef
parent a8d9702f
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -365,6 +365,10 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
        }
    }

    public boolean hasDistinctMultitouch() {
        return mInputView != null && mInputView.hasDistinctMultitouch();
    }

    /**
     * Updates state machine to figure out when to automatically switch back to alpha mode.
     * Returns true if the keyboard needs to switch back 
+6 −4
Original line number Diff line number Diff line
@@ -1135,7 +1135,9 @@ public class LatinIME extends InputMethodService
                LatinImeLogger.logOnDelete();
                break;
            case Keyboard.KEYCODE_SHIFT:
                // Shift key is handled in onPress().
                // Shift key is handled in onPress() when device has distinct multi-touch panel.
                if (!mKeyboardSwitcher.hasDistinctMultitouch())
                    handleShift();
                break;
            case Keyboard.KEYCODE_CANCEL:
                if (!isShowingOptionDialog()) {
@@ -1935,7 +1937,7 @@ public class LatinIME extends InputMethodService
            List<CharSequence> suggestions = mWordToSuggestions.get(selectedWord);
            // If the first letter of touching is capitalized, make all the suggestions
            // start with a capital letter.
            if (Character.isUpperCase((char) touching.word.charAt(0))) {
            if (Character.isUpperCase(touching.word.charAt(0))) {
                for (int i = 0; i < suggestions.size(); i++) {
                    String origSugg = (String) suggestions.get(i);
                    String capsSugg = origSugg.toUpperCase().charAt(0)
@@ -2196,7 +2198,7 @@ public class LatinIME extends InputMethodService
    public void onPress(int primaryCode) {
        vibrate();
        playKeyClick(primaryCode);
        if (primaryCode == Keyboard.KEYCODE_SHIFT) {
        if (mKeyboardSwitcher.hasDistinctMultitouch() && primaryCode == Keyboard.KEYCODE_SHIFT) {
            mShiftKeyState.onPress();
            handleShift();
        } else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE) {
@@ -2210,7 +2212,7 @@ public class LatinIME extends InputMethodService
        // Reset any drag flags in the keyboard
        ((LatinKeyboard) mKeyboardSwitcher.getInputView().getKeyboard()).keyReleased();
        //vibrate();
        if (primaryCode == Keyboard.KEYCODE_SHIFT) {
        if (mKeyboardSwitcher.hasDistinctMultitouch() && primaryCode == Keyboard.KEYCODE_SHIFT) {
            if (mShiftKeyState.isMomentary())
                resetShift();
            mShiftKeyState.onRelease();
+50 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.inputmethod.latin;

import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
@@ -204,6 +205,8 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
    private final ArrayList<PointerTracker> mPointerTrackers = new ArrayList<PointerTracker>();
    private final PointerQueue mPointerQueue = new PointerQueue();
    private final float mDebounceHysteresis;
    private final boolean mHasDistinctMultitouch;
    private int mOldPointerCount = 1;

    protected KeyDetector mKeyDetector = new ProximityKeyDetector();

@@ -508,6 +511,9 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
        final boolean ignoreMultitouch = true;
        mGestureDetector = new GestureDetector(getContext(), listener, null, ignoreMultitouch);
        mGestureDetector.setIsLongpressEnabled(false);

        mHasDistinctMultitouch = context.getPackageManager()
                .hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT);
    }

    public void setOnKeyboardActionListener(OnKeyboardActionListener listener) {
@@ -563,6 +569,14 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
        return mKeyboard;
    }

    /**
     * Return whether the device has distinct multi-touch panel.
     * @return true if the device has distinct multi-touch panel.
     */
    public boolean hasDistinctMultitouch() {
        return mHasDistinctMultitouch;
    }

    /**
     * Sets the state of the shift key of the keyboard, if any.
     * @param shifted whether or not to enable the state of the shift key
@@ -1090,7 +1104,7 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
        // Create pointer trackers until we can get 'id+1'-th tracker, if needed.
        for (int i = pointers.size(); i <= id; i++) {
            final PointerTracker tracker =
                new PointerTracker(i, mHandler, mKeyDetector, this);
                new PointerTracker(i, mHandler, mKeyDetector, this, mHasDistinctMultitouch);
            if (keys != null)
                tracker.setKeyboard(keys, mDebounceHysteresis);
            if (listener != null)
@@ -1107,6 +1121,13 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
        final int action = me.getActionMasked();
        final long eventTime = me.getEventTime();

        // TODO: cleanup this code into a multi-touch to single-touch event converter class?
        // If the device does not have distinct multi-touch support panel, ignore all multi-touch
        // events except a transition from/to single-touch.
        if (!mHasDistinctMultitouch && pointerCount > 1 && mOldPointerCount > 1) {
            return true;
        }

        // Track the last few movements to look for spurious swipes.
        mSwipeTracker.addMovement(me);

@@ -1138,6 +1159,34 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
            // Up event will pass through.
        }

        // TODO: cleanup this code into a multi-touch to single-touch event converter class?
        // Translate mutli-touch event to single-touch events on the device that has no distinct
        // multi-touch panel.
        if (!mHasDistinctMultitouch) {
            // Use only main (id=0) pointer tracker.
            PointerTracker tracker = getPointerTracker(0);
            int index = me.getActionIndex();
            int x = (int)me.getX(index);
            int y = (int)me.getY(index);
            int oldPointerCount = mOldPointerCount;
            if (pointerCount == 1 && oldPointerCount == 2) {
                // Multi-touch to single touch transition.
                // Send a down event for the latest pointer.
                tracker.onDownEvent(x, y, eventTime);
            } else if (pointerCount == 2 && oldPointerCount == 1) {
                // Single-touch to multi-touch transition.
                // Send an up event for the last pointer.
                tracker.onUpEvent(tracker.getLastX(), tracker.getLastY(), eventTime);
            } else if (pointerCount == 1 && oldPointerCount == 1) {
                tracker.onTouchEvent(action, x, y, eventTime);
            } else {
                Log.w(TAG, "Unknown touch panel behavior: pointer count is " + pointerCount
                        + " (old " + oldPointerCount + ")");
            }
            mOldPointerCount = pointerCount;
            return true;
        }

        if (action == MotionEvent.ACTION_MOVE) {
            for (int index = 0; index < pointerCount; index++) {
                int x = (int)me.getX(index);
+30 −4
Original line number Diff line number Diff line
@@ -22,12 +22,13 @@ import com.android.inputmethod.latin.LatinKeyboardBaseView.UIHandler;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.Keyboard.Key;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ViewConfiguration;

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

    public interface UIProxy {
        public void invalidateKey(Key key);
@@ -51,6 +52,7 @@ public class PointerTracker {
    private final UIHandler mHandler;
    private final KeyDetector mKeyDetector;
    private OnKeyboardActionListener mListener;
    private final boolean mHasDistinctMultitouch;

    private Key[] mKeys;
    private int mKeyDebounceThresholdSquared = -1;
@@ -85,13 +87,15 @@ public class PointerTracker {
    // pressed key
    private int mPreviousKey = NOT_A_KEY;

    public PointerTracker(int id, UIHandler handler, KeyDetector keyDetector, UIProxy proxy) {
    public PointerTracker(int id, UIHandler handler, KeyDetector keyDetector, UIProxy proxy,
            boolean hasDistinctMultitouch) {
        if (proxy == null || handler == null || keyDetector == null)
            throw new NullPointerException();
        mPointerId = id;
        mProxy = proxy;
        mHandler = handler;
        mKeyDetector = keyDetector;
        mHasDistinctMultitouch = hasDistinctMultitouch;
        resetMultiTap();
    }

@@ -146,6 +150,25 @@ public class PointerTracker {
        mKeyAlreadyProcessed = true;
    }

    public void onTouchEvent(int action, int x, int y, long eventTime) {
        switch (action) {
        case MotionEvent.ACTION_MOVE:
            onMoveEvent(x, y, eventTime);
            break;
        case MotionEvent.ACTION_DOWN:
        case MotionEvent.ACTION_POINTER_DOWN:
            onDownEvent(x, y, eventTime);
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_POINTER_UP:
            onUpEvent(x, y, eventTime);
            break;
        case MotionEvent.ACTION_CANCEL:
            onCancelEvent(x, y, eventTime);
            break;
        }
    }

    public void onDownEvent(int x, int y, long eventTime) {
        int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null);
        mCurrentKey = keyIndex;
@@ -242,7 +265,7 @@ public class PointerTracker {
        showKeyPreviewAndUpdateKey(NOT_A_KEY);
        // If we're not on a repeating key (which sends on a DOWN event)
        if (!wasInKeyRepeat) {
            detectAndSendKey(mCurrentKey, (int)x, (int)y, eventTime);
            detectAndSendKey(mCurrentKey, x, y, eventTime);
        }
        if (isValidKeyIndex(keyIndex))
            mProxy.invalidateKey(mKeys[keyIndex]);
@@ -355,7 +378,10 @@ public class PointerTracker {

    private void showKeyPreviewAndUpdateKey(int keyIndex) {
        updateKey(keyIndex);
        if (!isModifier())
        // The modifier key, such as shift key, should not be shown as preview when multi-touch is
        // supported. On thge other hand, if multi-touch is not supported, the modifier key should
        // be shown as preview.
        if (!isModifier() || !mHasDistinctMultitouch)
            mProxy.showPreview(keyIndex, this);
    }