Fix NPE in LatinKeyboardBaseView

This change also refactors some mini-keyboard related methods in
LatinKeyboardBaseView and PointerTracker class.

Bug: 2973236
Change-Id: I3190fe89ea3ac3c6d351ed4b6d77de98a0aa65db
main
Tadashi G. Takaoka 2010-09-03 12:51:03 +09:00
parent 7083b7486e
commit c5d33b1652
2 changed files with 39 additions and 42 deletions

View File

@ -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();

View File

@ -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))