Loading java/src/com/android/inputmethod/latin/LatinIME.java +26 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } } Loading Loading @@ -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) { Loading Loading @@ -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() { Loading java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +64 −3 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -45,6 +46,7 @@ import android.widget.TextView; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; /** Loading @@ -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; Loading Loading @@ -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(); Loading Loading @@ -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); } Loading Loading @@ -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; } } Loading @@ -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(); } Loading java/src/com/android/inputmethod/latin/ModifierKeyState.java 0 → 100644 +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; } } java/src/com/android/inputmethod/latin/PointerTracker.java +21 −1 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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(); Loading @@ -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(); Loading Loading @@ -305,6 +324,7 @@ public class PointerTracker { private void showKeyPreviewAndUpdateKey(int keyIndex) { updateKey(keyIndex); if (!isModifier()) mProxy.showPreview(keyIndex, this); } Loading Loading
java/src/com/android/inputmethod/latin/LatinIME.java +26 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } } Loading Loading @@ -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) { Loading Loading @@ -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() { Loading
java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +64 −3 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -45,6 +46,7 @@ import android.widget.TextView; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; /** Loading @@ -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; Loading Loading @@ -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(); Loading Loading @@ -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); } Loading Loading @@ -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; } } Loading @@ -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(); } Loading
java/src/com/android/inputmethod/latin/ModifierKeyState.java 0 → 100644 +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; } }
java/src/com/android/inputmethod/latin/PointerTracker.java +21 −1 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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(); Loading @@ -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(); Loading Loading @@ -305,6 +324,7 @@ public class PointerTracker { private void showKeyPreviewAndUpdateKey(int keyIndex) { updateKey(keyIndex); if (!isModifier()) mProxy.showPreview(keyIndex, this); } Loading