Fix NPE in LatinKeyboardBaseView
This change also refactors some mini-keyboard related methods in LatinKeyboardBaseView and PointerTracker class. Bug: 2973236 Change-Id: I3190fe89ea3ac3c6d351ed4b6d77de98a0aa65dbmain
parent
7083b7486e
commit
c5d33b1652
|
@ -190,9 +190,7 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
|
||||||
|
|
||||||
// Popup mini keyboard
|
// Popup mini keyboard
|
||||||
private PopupWindow mMiniKeyboardPopup;
|
private PopupWindow mMiniKeyboardPopup;
|
||||||
private View mMiniKeyboardContainer;
|
|
||||||
private LatinKeyboardBaseView mMiniKeyboard;
|
private LatinKeyboardBaseView mMiniKeyboard;
|
||||||
private boolean mMiniKeyboardOnScreen;
|
|
||||||
private View mMiniKeyboardParent;
|
private View mMiniKeyboardParent;
|
||||||
private Map<Key,View> mMiniKeyboardCache;
|
private Map<Key,View> mMiniKeyboardCache;
|
||||||
private int mMiniKeyboardOriginX;
|
private int mMiniKeyboardOriginX;
|
||||||
|
@ -799,7 +797,7 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
|
||||||
}
|
}
|
||||||
mInvalidatedKey = null;
|
mInvalidatedKey = null;
|
||||||
// Overlay a dark rectangle to dim the keyboard
|
// Overlay a dark rectangle to dim the keyboard
|
||||||
if (mMiniKeyboardOnScreen) {
|
if (mMiniKeyboard != null) {
|
||||||
paint.setColor((int) (mBackgroundDimAmount * 0xFF) << 24);
|
paint.setColor((int) (mBackgroundDimAmount * 0xFF) << 24);
|
||||||
canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
|
canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
|
||||||
}
|
}
|
||||||
|
@ -967,14 +965,8 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
|
||||||
return false;
|
return false;
|
||||||
boolean result = onLongPress(popupKey);
|
boolean result = onLongPress(popupKey);
|
||||||
if (result) {
|
if (result) {
|
||||||
|
tracker.setAlreadyProcessed();
|
||||||
dismissKeyPreview();
|
dismissKeyPreview();
|
||||||
|
|
||||||
long eventTime = tracker.getDownTime();
|
|
||||||
mMiniKeyboardPopupTime = eventTime;
|
|
||||||
MotionEvent downEvent = generateMiniKeyboardMotionEvent(MotionEvent.ACTION_DOWN,
|
|
||||||
tracker.getLastX(), tracker.getLastY(), eventTime);
|
|
||||||
mMiniKeyboard.onTouchEvent(downEvent);
|
|
||||||
downEvent.recycle();
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -990,12 +982,12 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
|
||||||
int popupKeyboardId = popupKey.popupResId;
|
int popupKeyboardId = popupKey.popupResId;
|
||||||
|
|
||||||
if (popupKeyboardId != 0) {
|
if (popupKeyboardId != 0) {
|
||||||
mMiniKeyboardContainer = mMiniKeyboardCache.get(popupKey);
|
View container = mMiniKeyboardCache.get(popupKey);
|
||||||
if (mMiniKeyboardContainer == null) {
|
if (container == null) {
|
||||||
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
|
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
|
||||||
Context.LAYOUT_INFLATER_SERVICE);
|
Context.LAYOUT_INFLATER_SERVICE);
|
||||||
mMiniKeyboardContainer = inflater.inflate(mPopupLayout, null);
|
container = inflater.inflate(mPopupLayout, null);
|
||||||
mMiniKeyboard = (LatinKeyboardBaseView) mMiniKeyboardContainer.findViewById(
|
mMiniKeyboard = (LatinKeyboardBaseView) container.findViewById(
|
||||||
R.id.LatinKeyboardBaseView);
|
R.id.LatinKeyboardBaseView);
|
||||||
mMiniKeyboard.setOnKeyboardActionListener(new OnKeyboardActionListener() {
|
mMiniKeyboard.setOnKeyboardActionListener(new OnKeyboardActionListener() {
|
||||||
public void onKey(int primaryCode, int[] keyCodes, int x, int y) {
|
public void onKey(int primaryCode, int[] keyCodes, int x, int y) {
|
||||||
|
@ -1029,13 +1021,13 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
|
||||||
}
|
}
|
||||||
mMiniKeyboard.setKeyboard(keyboard);
|
mMiniKeyboard.setKeyboard(keyboard);
|
||||||
mMiniKeyboard.setPopupParent(this);
|
mMiniKeyboard.setPopupParent(this);
|
||||||
mMiniKeyboardContainer.measure(
|
container.measure(
|
||||||
MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST),
|
MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST),
|
||||||
MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST));
|
MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST));
|
||||||
|
|
||||||
mMiniKeyboardCache.put(popupKey, mMiniKeyboardContainer);
|
mMiniKeyboardCache.put(popupKey, container);
|
||||||
} else {
|
} else {
|
||||||
mMiniKeyboard = (LatinKeyboardBaseView) mMiniKeyboardContainer.findViewById(
|
mMiniKeyboard = (LatinKeyboardBaseView) container.findViewById(
|
||||||
R.id.LatinKeyboardBaseView);
|
R.id.LatinKeyboardBaseView);
|
||||||
}
|
}
|
||||||
if (mWindowOffset == null) {
|
if (mWindowOffset == null) {
|
||||||
|
@ -1044,35 +1036,36 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
|
||||||
}
|
}
|
||||||
int popupX = popupKey.x + popupKey.width + getPaddingLeft();
|
int popupX = popupKey.x + popupKey.width + getPaddingLeft();
|
||||||
int popupY = popupKey.y + getPaddingTop();
|
int popupY = popupKey.y + getPaddingTop();
|
||||||
popupX -= mMiniKeyboardContainer.getMeasuredWidth();
|
popupX -= container.getMeasuredWidth();
|
||||||
popupY -= mMiniKeyboardContainer.getMeasuredHeight();
|
popupY -= container.getMeasuredHeight();
|
||||||
popupX += mWindowOffset[0];
|
popupX += mWindowOffset[0];
|
||||||
popupY += mWindowOffset[1];
|
popupY += mWindowOffset[1];
|
||||||
final int x = popupX + mMiniKeyboardContainer.getPaddingRight();
|
final int x = popupX + container.getPaddingRight();
|
||||||
final int y = popupY + mMiniKeyboardContainer.getPaddingBottom();
|
final int y = popupY + container.getPaddingBottom();
|
||||||
mMiniKeyboardOriginX = (x < 0 ? 0 : x) + mMiniKeyboardContainer.getPaddingLeft();
|
mMiniKeyboardOriginX = (x < 0 ? 0 : x) + container.getPaddingLeft();
|
||||||
mMiniKeyboardOriginY = y + mMiniKeyboardContainer.getPaddingTop();
|
mMiniKeyboardOriginY = y + container.getPaddingTop();
|
||||||
mMiniKeyboard.setPopupOffset((x < 0) ? 0 : x, y);
|
mMiniKeyboard.setPopupOffset((x < 0) ? 0 : x, y);
|
||||||
mMiniKeyboard.setShifted(isShifted());
|
mMiniKeyboard.setShifted(isShifted());
|
||||||
mMiniKeyboard.setPreviewEnabled(isPreviewEnabled());
|
mMiniKeyboard.setPreviewEnabled(isPreviewEnabled());
|
||||||
mMiniKeyboardPopup.setContentView(mMiniKeyboardContainer);
|
mMiniKeyboardPopup.setContentView(container);
|
||||||
mMiniKeyboardPopup.setWidth(mMiniKeyboardContainer.getMeasuredWidth());
|
mMiniKeyboardPopup.setWidth(container.getMeasuredWidth());
|
||||||
mMiniKeyboardPopup.setHeight(mMiniKeyboardContainer.getMeasuredHeight());
|
mMiniKeyboardPopup.setHeight(container.getMeasuredHeight());
|
||||||
mMiniKeyboardPopup.showAtLocation(this, Gravity.NO_GRAVITY, x, y);
|
mMiniKeyboardPopup.showAtLocation(this, Gravity.NO_GRAVITY, x, y);
|
||||||
mMiniKeyboardOnScreen = true;
|
|
||||||
|
|
||||||
// TODO: down event?
|
// Inject down event on the key to mini keyboard.
|
||||||
|
long eventTime = System.currentTimeMillis();
|
||||||
|
mMiniKeyboardPopupTime = eventTime;
|
||||||
|
MotionEvent downEvent = generateMiniKeyboardMotionEvent(MotionEvent.ACTION_DOWN,
|
||||||
|
popupKey.x + popupKey.width / 2, popupKey.y + popupKey.height / 2, eventTime);
|
||||||
|
mMiniKeyboard.onTouchEvent(downEvent);
|
||||||
|
downEvent.recycle();
|
||||||
|
|
||||||
invalidateAllKeys();
|
invalidateAllKeys();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Should cleanup after refactoring mini-keyboard.
|
|
||||||
public boolean isMiniKeyboardOnScreen() {
|
|
||||||
return mMiniKeyboardOnScreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
private MotionEvent generateMiniKeyboardMotionEvent(int action, int x, int y, long eventTime) {
|
private MotionEvent generateMiniKeyboardMotionEvent(int action, int x, int y, long eventTime) {
|
||||||
return MotionEvent.obtain(mMiniKeyboardPopupTime, eventTime, action,
|
return MotionEvent.obtain(mMiniKeyboardPopupTime, eventTime, action,
|
||||||
x - mMiniKeyboardOriginX, y - mMiniKeyboardOriginY, 0);
|
x - mMiniKeyboardOriginX, y - mMiniKeyboardOriginY, 0);
|
||||||
|
@ -1107,7 +1100,7 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
|
||||||
mSwipeTracker.addMovement(me);
|
mSwipeTracker.addMovement(me);
|
||||||
|
|
||||||
// We must disable gesture detector while mini-keyboard is on the screen.
|
// We must disable gesture detector while mini-keyboard is on the screen.
|
||||||
if (!mMiniKeyboardOnScreen && mGestureDetector.onTouchEvent(me)) {
|
if (mMiniKeyboard == null && mGestureDetector.onTouchEvent(me)) {
|
||||||
dismissKeyPreview();
|
dismissKeyPreview();
|
||||||
mHandler.cancelKeyTimers();
|
mHandler.cancelKeyTimers();
|
||||||
return true;
|
return true;
|
||||||
|
@ -1115,7 +1108,7 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
|
||||||
|
|
||||||
// Needs to be called after the gesture detector gets a turn, as it may have
|
// Needs to be called after the gesture detector gets a turn, as it may have
|
||||||
// displayed the mini keyboard
|
// displayed the mini keyboard
|
||||||
if (mMiniKeyboardOnScreen) {
|
if (mMiniKeyboard != null) {
|
||||||
MotionEvent translated = generateMiniKeyboardMotionEvent(action, (int)me.getX(),
|
MotionEvent translated = generateMiniKeyboardMotionEvent(action, (int)me.getX(),
|
||||||
(int)me.getY(), eventTime);
|
(int)me.getY(), eventTime);
|
||||||
mMiniKeyboard.onTouchEvent(translated);
|
mMiniKeyboard.onTouchEvent(translated);
|
||||||
|
@ -1222,10 +1215,10 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
|
||||||
closing();
|
closing();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dismissPopupKeyboard() {
|
private void dismissPopupKeyboard() {
|
||||||
if (mMiniKeyboardPopup.isShowing()) {
|
if (mMiniKeyboardPopup.isShowing()) {
|
||||||
mMiniKeyboardPopup.dismiss();
|
mMiniKeyboardPopup.dismiss();
|
||||||
mMiniKeyboardOnScreen = false;
|
mMiniKeyboard = null;
|
||||||
mMiniKeyboardOriginX = 0;
|
mMiniKeyboardOriginX = 0;
|
||||||
mMiniKeyboardOriginY = 0;
|
mMiniKeyboardOriginY = 0;
|
||||||
invalidateAllKeys();
|
invalidateAllKeys();
|
||||||
|
|
|
@ -32,9 +32,6 @@ public class PointerTracker {
|
||||||
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);
|
||||||
// TODO: These methods might be temporary.
|
|
||||||
public void dismissPopupKeyboard();
|
|
||||||
public boolean isMiniKeyboardOnScreen();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int mPointerId;
|
public final int mPointerId;
|
||||||
|
@ -63,6 +60,9 @@ public class PointerTracker {
|
||||||
private int mStartY;
|
private int mStartY;
|
||||||
private long mDownTime;
|
private long mDownTime;
|
||||||
|
|
||||||
|
// true if event is already translated to a key action (long press or mini-keyboard)
|
||||||
|
private boolean mKeyAlreadyProcessed;
|
||||||
|
|
||||||
// for move de-bouncing
|
// for move de-bouncing
|
||||||
private int mLastCodeX;
|
private int mLastCodeX;
|
||||||
private int mLastCodeY;
|
private int mLastCodeY;
|
||||||
|
@ -140,12 +140,17 @@ public class PointerTracker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setAlreadyProcessed() {
|
||||||
|
mKeyAlreadyProcessed = true;
|
||||||
|
}
|
||||||
|
|
||||||
public void onDownEvent(int x, int y, long eventTime) {
|
public void onDownEvent(int x, int y, long eventTime) {
|
||||||
int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null);
|
int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null);
|
||||||
mCurrentKey = keyIndex;
|
mCurrentKey = keyIndex;
|
||||||
mStartX = x;
|
mStartX = x;
|
||||||
mStartY = y;
|
mStartY = y;
|
||||||
mDownTime = eventTime;
|
mDownTime = eventTime;
|
||||||
|
mKeyAlreadyProcessed = false;
|
||||||
startMoveDebouncing(x, y);
|
startMoveDebouncing(x, y);
|
||||||
startTimeDebouncing(eventTime);
|
startTimeDebouncing(eventTime);
|
||||||
checkMultiTap(eventTime, keyIndex);
|
checkMultiTap(eventTime, keyIndex);
|
||||||
|
@ -230,7 +235,7 @@ public class PointerTracker {
|
||||||
}
|
}
|
||||||
showKeyPreviewAndUpdateKey(NOT_A_KEY);
|
showKeyPreviewAndUpdateKey(NOT_A_KEY);
|
||||||
// If we're not on a repeating key (which sends on a DOWN event)
|
// If we're not on a repeating key (which sends on a DOWN event)
|
||||||
if (!wasInKeyRepeat && !mProxy.isMiniKeyboardOnScreen()) {
|
if (!wasInKeyRepeat && !mKeyAlreadyProcessed) {
|
||||||
detectAndSendKey(mCurrentKey, (int)x, (int)y, eventTime);
|
detectAndSendKey(mCurrentKey, (int)x, (int)y, eventTime);
|
||||||
}
|
}
|
||||||
if (isValidKeyIndex(keyIndex))
|
if (isValidKeyIndex(keyIndex))
|
||||||
|
@ -242,7 +247,6 @@ public class PointerTracker {
|
||||||
debugLog("onCancelEvt:", x, y);
|
debugLog("onCancelEvt:", x, y);
|
||||||
mHandler.cancelKeyTimers();
|
mHandler.cancelKeyTimers();
|
||||||
mHandler.cancelPopupPreview();
|
mHandler.cancelPopupPreview();
|
||||||
mProxy.dismissPopupKeyboard();
|
|
||||||
showKeyPreviewAndUpdateKey(NOT_A_KEY);
|
showKeyPreviewAndUpdateKey(NOT_A_KEY);
|
||||||
int keyIndex = mCurrentKey;
|
int keyIndex = mCurrentKey;
|
||||||
if (isValidKeyIndex(keyIndex))
|
if (isValidKeyIndex(keyIndex))
|
||||||
|
|
Loading…
Reference in New Issue