am d0457eae: am 3491c877: Merge "Queuing PointerTracker to support n-key roll-over and shift modifier." into gingerbread
Merge commit 'd0457eae17d10535023a02579d16ede7bfcc6bec' * commit 'd0457eae17d10535023a02579d16ede7bfcc6bec': Queuing PointerTracker to support n-key roll-over and shift modifier.main
commit
373656f09b
|
@ -226,6 +226,9 @@ public class LatinIME extends InputMethodService
|
||||||
private int mDeleteCount;
|
private int mDeleteCount;
|
||||||
private long mLastKeyTime;
|
private long mLastKeyTime;
|
||||||
|
|
||||||
|
// Shift modifier key state
|
||||||
|
private ModifierKeyState mShiftKeyState = new ModifierKeyState();
|
||||||
|
|
||||||
private Tutorial mTutorial;
|
private Tutorial mTutorial;
|
||||||
|
|
||||||
private AudioManager mAudioManager;
|
private AudioManager mAudioManager;
|
||||||
|
@ -975,7 +978,8 @@ public class LatinIME extends InputMethodService
|
||||||
public void updateShiftKeyState(EditorInfo attr) {
|
public void updateShiftKeyState(EditorInfo attr) {
|
||||||
InputConnection ic = getCurrentInputConnection();
|
InputConnection ic = getCurrentInputConnection();
|
||||||
if (ic != null && attr != null && mKeyboardSwitcher.isAlphabetMode()) {
|
if (ic != null && attr != null && mKeyboardSwitcher.isAlphabetMode()) {
|
||||||
mKeyboardSwitcher.setShifted(mCapsLock || getCursorCapsMode(ic, attr) != 0);
|
mKeyboardSwitcher.setShifted(mShiftKeyState.isMomentary() || mCapsLock
|
||||||
|
|| getCursorCapsMode(ic, attr) != 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1232,12 +1236,20 @@ public class LatinIME extends InputMethodService
|
||||||
ic.endBatchEdit();
|
ic.endBatchEdit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void resetShift() {
|
||||||
|
handleShiftInternal(true);
|
||||||
|
}
|
||||||
|
|
||||||
private void handleShift() {
|
private void handleShift() {
|
||||||
|
handleShiftInternal(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleShiftInternal(boolean forceNormal) {
|
||||||
mHandler.removeMessages(MSG_UPDATE_SHIFT_STATE);
|
mHandler.removeMessages(MSG_UPDATE_SHIFT_STATE);
|
||||||
KeyboardSwitcher switcher = mKeyboardSwitcher;
|
KeyboardSwitcher switcher = mKeyboardSwitcher;
|
||||||
LatinKeyboardView inputView = switcher.getInputView();
|
LatinKeyboardView inputView = switcher.getInputView();
|
||||||
if (switcher.isAlphabetMode()) {
|
if (switcher.isAlphabetMode()) {
|
||||||
if (mCapsLock) {
|
if (mCapsLock || forceNormal) {
|
||||||
mCapsLock = false;
|
mCapsLock = false;
|
||||||
switcher.setShifted(false);
|
switcher.setShifted(false);
|
||||||
} else if (inputView != null) {
|
} else if (inputView != null) {
|
||||||
|
@ -2145,15 +2157,26 @@ public class LatinIME extends InputMethodService
|
||||||
vibrate();
|
vibrate();
|
||||||
playKeyClick(primaryCode);
|
playKeyClick(primaryCode);
|
||||||
if (primaryCode == Keyboard.KEYCODE_SHIFT) {
|
if (primaryCode == Keyboard.KEYCODE_SHIFT) {
|
||||||
|
mShiftKeyState.onPress();
|
||||||
handleShift();
|
handleShift();
|
||||||
}
|
} else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE) {
|
||||||
// TODO: We should handle KEYCODE_MODE_CHANGE (symbol) here as well.
|
// TODO: We should handle KEYCODE_MODE_CHANGE (symbol) here as well.
|
||||||
|
} else {
|
||||||
|
mShiftKeyState.onOtherKeyPressed();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onRelease(int primaryCode) {
|
public void onRelease(int primaryCode) {
|
||||||
// Reset any drag flags in the keyboard
|
// Reset any drag flags in the keyboard
|
||||||
((LatinKeyboard) mKeyboardSwitcher.getInputView().getKeyboard()).keyReleased();
|
((LatinKeyboard) mKeyboardSwitcher.getInputView().getKeyboard()).keyReleased();
|
||||||
//vibrate();
|
//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() {
|
private FieldContext makeFieldContext() {
|
||||||
|
|
|
@ -33,6 +33,7 @@ import android.inputmethodservice.Keyboard.Key;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.util.Log;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.GestureDetector;
|
import android.view.GestureDetector;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
|
@ -45,6 +46,7 @@ import android.widget.TextView;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,6 +64,7 @@ import java.util.Map;
|
||||||
*/
|
*/
|
||||||
public class LatinKeyboardBaseView extends View implements View.OnClickListener,
|
public class LatinKeyboardBaseView extends View implements View.OnClickListener,
|
||||||
PointerTracker.UIProxy {
|
PointerTracker.UIProxy {
|
||||||
|
private static final String TAG = "LatinKeyboardBaseView";
|
||||||
private static final boolean DEBUG = false;
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
public static final int NOT_A_TOUCH_COORDINATE = -1;
|
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 OnKeyboardActionListener mKeyboardActionListener;
|
||||||
|
|
||||||
private final ArrayList<PointerTracker> mPointerTrackers = new ArrayList<PointerTracker>();
|
private final ArrayList<PointerTracker> mPointerTrackers = new ArrayList<PointerTracker>();
|
||||||
|
private final PointerQueue mPointerQueue = new PointerQueue();
|
||||||
private final float mDebounceHysteresis;
|
private final float mDebounceHysteresis;
|
||||||
|
|
||||||
protected KeyDetector mKeyDetector = new ProximityKeyDetector();
|
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) {
|
public LatinKeyboardBaseView(Context context, AttributeSet attrs) {
|
||||||
this(context, attrs, R.attr.keyboardViewStyle);
|
this(context, attrs, R.attr.keyboardViewStyle);
|
||||||
}
|
}
|
||||||
|
@ -1107,14 +1146,14 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener,
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case MotionEvent.ACTION_DOWN:
|
case MotionEvent.ACTION_DOWN:
|
||||||
case MotionEvent.ACTION_POINTER_DOWN:
|
case MotionEvent.ACTION_POINTER_DOWN:
|
||||||
tracker.onDownEvent(touchX, touchY, eventTime);
|
onDownEvent(tracker, touchX, touchY, eventTime);
|
||||||
break;
|
break;
|
||||||
case MotionEvent.ACTION_UP:
|
case MotionEvent.ACTION_UP:
|
||||||
case MotionEvent.ACTION_POINTER_UP:
|
case MotionEvent.ACTION_POINTER_UP:
|
||||||
tracker.onUpEvent(touchX, touchY, eventTime);
|
onUpEvent(tracker, touchX, touchY, eventTime);
|
||||||
break;
|
break;
|
||||||
case MotionEvent.ACTION_CANCEL:
|
case MotionEvent.ACTION_CANCEL:
|
||||||
tracker.onCancelEvent(touchX, touchY, eventTime);
|
onCancelEvent(tracker, touchX, touchY, eventTime);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1122,6 +1161,28 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener,
|
||||||
return true;
|
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() {
|
protected void swipeRight() {
|
||||||
mKeyboardActionListener.swipeRight();
|
mKeyboardActionListener.swipeRight();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* 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,9 +21,13 @@ import com.android.inputmethod.latin.LatinKeyboardBaseView.UIHandler;
|
||||||
|
|
||||||
import android.inputmethodservice.Keyboard;
|
import android.inputmethodservice.Keyboard;
|
||||||
import android.inputmethodservice.Keyboard.Key;
|
import android.inputmethodservice.Keyboard.Key;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.ViewConfiguration;
|
import android.view.ViewConfiguration;
|
||||||
|
|
||||||
public class PointerTracker {
|
public class PointerTracker {
|
||||||
|
private static final String TAG = "PointerTracker";
|
||||||
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
public interface UIProxy {
|
public interface UIProxy {
|
||||||
public void invalidateKey(Key key);
|
public void invalidateKey(Key key);
|
||||||
public void showPreview(int keyIndex, PointerTracker tracker);
|
public void showPreview(int keyIndex, PointerTracker tracker);
|
||||||
|
@ -108,6 +112,15 @@ public class PointerTracker {
|
||||||
return isValidKeyIndex(keyIndex) ? mKeys[keyIndex] : null;
|
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) {
|
public void updateKey(int keyIndex) {
|
||||||
int oldKeyIndex = mPreviousKey;
|
int oldKeyIndex = mPreviousKey;
|
||||||
mPreviousKey = keyIndex;
|
mPreviousKey = keyIndex;
|
||||||
|
@ -146,6 +159,8 @@ public class PointerTracker {
|
||||||
}
|
}
|
||||||
showKeyPreviewAndUpdateKey(keyIndex);
|
showKeyPreviewAndUpdateKey(keyIndex);
|
||||||
updateMoveDebouncing(touchX, touchY);
|
updateMoveDebouncing(touchX, touchY);
|
||||||
|
if (DEBUG)
|
||||||
|
Log.d(TAG, "onDownEvent: [" + mPointerId + "] modifier=" + isModifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onMoveEvent(int touchX, int touchY, long eventTime) {
|
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) {
|
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);
|
int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null);
|
||||||
boolean wasInKeyRepeat = mHandler.isInKeyRepeat();
|
boolean wasInKeyRepeat = mHandler.isInKeyRepeat();
|
||||||
mHandler.cancelKeyTimers();
|
mHandler.cancelKeyTimers();
|
||||||
|
@ -204,6 +221,8 @@ public class PointerTracker {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onCancelEvent(int touchX, int touchY, long eventTime) {
|
public void onCancelEvent(int touchX, int touchY, long eventTime) {
|
||||||
|
if (DEBUG)
|
||||||
|
Log.d(TAG, "onCancelEvent: [" + mPointerId + "]");
|
||||||
mHandler.cancelKeyTimers();
|
mHandler.cancelKeyTimers();
|
||||||
mHandler.cancelPopupPreview();
|
mHandler.cancelPopupPreview();
|
||||||
mProxy.dismissPopupKeyboard();
|
mProxy.dismissPopupKeyboard();
|
||||||
|
@ -305,6 +324,7 @@ public class PointerTracker {
|
||||||
|
|
||||||
private void showKeyPreviewAndUpdateKey(int keyIndex) {
|
private void showKeyPreviewAndUpdateKey(int keyIndex) {
|
||||||
updateKey(keyIndex);
|
updateKey(keyIndex);
|
||||||
|
if (!isModifier())
|
||||||
mProxy.showPreview(keyIndex, this);
|
mProxy.showPreview(keyIndex, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue