diff options
Diffstat (limited to 'java/src/com/android')
9 files changed, 290 insertions, 212 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java index b512f5ac7..b807dd325 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java @@ -21,6 +21,7 @@ import android.content.pm.PackageManager; import android.content.res.Resources; import android.content.res.TypedArray; import android.os.Message; +import android.os.SystemClock; import android.util.AttributeSet; import android.util.Log; import android.view.GestureDetector; @@ -36,11 +37,9 @@ import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy; import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy; import com.android.inputmethod.keyboard.PointerTracker.TimerProxy; import com.android.inputmethod.keyboard.internal.MiniKeyboardBuilder; -import com.android.inputmethod.keyboard.internal.PointerTrackerQueue; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.StaticInnerHandlerWrapper; -import java.util.ArrayList; import java.util.WeakHashMap; /** @@ -65,18 +64,14 @@ public class LatinKeyboardBaseView extends KeyboardView implements PointerTracke // Mini keyboard private PopupWindow mPopupWindow; - private PopupPanel mPopupMiniKeyboardPanel; + private PopupPanel mPopupPanel; + private int mPopupPanelPointerTrackerId; private final WeakHashMap<Key, PopupPanel> mPopupPanelCache = new WeakHashMap<Key, PopupPanel>(); /** Listener for {@link KeyboardActionListener}. */ private KeyboardActionListener mKeyboardActionListener; - private final ArrayList<PointerTracker> mPointerTrackers = new ArrayList<PointerTracker>(); - - // TODO: Let the PointerTracker class manage this pointer queue - private final PointerTrackerQueue mPointerQueue; - private final boolean mHasDistinctMultitouch; private int mOldPointerCount = 1; private int mOldKeyIndex; @@ -249,7 +244,7 @@ public class LatinKeyboardBaseView extends KeyboardView implements PointerTracke .hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT); mKeyRepeatInterval = res.getInteger(R.integer.config_key_repeat_interval); - mPointerQueue = mHasDistinctMultitouch ? new PointerTrackerQueue() : null; + PointerTracker.init(mHasDistinctMultitouch, getContext()); } public void startIgnoringDoubleTap() { @@ -259,9 +254,7 @@ public class LatinKeyboardBaseView extends KeyboardView implements PointerTracke public void setKeyboardActionListener(KeyboardActionListener listener) { mKeyboardActionListener = listener; - for (PointerTracker tracker : mPointerTrackers) { - tracker.setKeyboardActionListener(listener); - } + PointerTracker.setKeyboardActionListener(listener); } /** @@ -304,17 +297,15 @@ public class LatinKeyboardBaseView extends KeyboardView implements PointerTracke @Override public void setKeyboard(Keyboard keyboard) { if (getKeyboard() != null) { - dismissAllKeyPreviews(); + PointerTracker.dismissAllKeyPreviews(); } // Remove any pending messages, except dismissing preview mKeyTimerHandler.cancelKeyTimers(); super.setKeyboard(keyboard); mKeyDetector.setKeyboard( keyboard, -getPaddingLeft(), -getPaddingTop() + mVerticalCorrection); - for (PointerTracker tracker : mPointerTrackers) { - tracker.setKeyDetector(mKeyDetector); - } mKeyDetector.setProximityThreshold(keyboard.getMostCommonKeyWidth()); + PointerTracker.setKeyDetector(mKeyDetector); mPopupPanelCache.clear(); } @@ -343,14 +334,6 @@ public class LatinKeyboardBaseView extends KeyboardView implements PointerTracke return mKeyDetector.isProximityCorrectionEnabled(); } - // TODO: clean up this method. - private void dismissAllKeyPreviews() { - for (PointerTracker tracker : mPointerTrackers) { - tracker.setReleasedKeyGraphics(); - dismissKeyPreview(tracker); - } - } - @Override public void cancelAllMessages() { mKeyTimerHandler.cancelAllMessages(); @@ -363,15 +346,13 @@ public class LatinKeyboardBaseView extends KeyboardView implements PointerTracke return false; } + // Check if we are already displaying popup panel. + if (mPopupPanel != null) + return false; final Key parentKey = tracker.getKey(keyIndex); if (parentKey == null) return false; - boolean result = onLongPress(parentKey, tracker); - if (result) { - dismissAllKeyPreviews(); - tracker.onLongPressed(); - } - return result; + return onLongPress(parentKey, tracker); } private void onLongPressShiftKey(PointerTracker tracker) { @@ -398,35 +379,6 @@ public class LatinKeyboardBaseView extends KeyboardView implements PointerTracke final PopupMiniKeyboardView miniKeyboardView = (PopupMiniKeyboardView)container.findViewById(R.id.mini_keyboard_view); - miniKeyboardView.setKeyboardActionListener(new KeyboardActionListener() { - @Override - public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) { - mKeyboardActionListener.onCodeInput(primaryCode, keyCodes, x, y); - dismissMiniKeyboard(); - } - - @Override - public void onTextInput(CharSequence text) { - mKeyboardActionListener.onTextInput(text); - dismissMiniKeyboard(); - } - - @Override - public void onCancelInput() { - mKeyboardActionListener.onCancelInput(); - dismissMiniKeyboard(); - } - - @Override - public void onPress(int primaryCode, boolean withSliding) { - mKeyboardActionListener.onPress(primaryCode, withSliding); - } - @Override - public void onRelease(int primaryCode, boolean withSliding) { - mKeyboardActionListener.onRelease(primaryCode, withSliding); - } - }); - final Keyboard parentKeyboard = getKeyboard(); final Keyboard miniKeyboard = new MiniKeyboardBuilder( this, parentKeyboard.getPopupKeyboardResId(), parentKey, parentKeyboard).build(); @@ -440,7 +392,7 @@ public class LatinKeyboardBaseView extends KeyboardView implements PointerTracke @Override protected boolean needsToDimKeyboard() { - return mPopupMiniKeyboardPanel != null; + return mPopupPanel != null; } /** @@ -466,38 +418,28 @@ public class LatinKeyboardBaseView extends KeyboardView implements PointerTracke // Allow popup window to be drawn off the screen. mPopupWindow.setClippingEnabled(false); } - mPopupMiniKeyboardPanel = popupPanel; + mPopupPanel = popupPanel; + mPopupPanelPointerTrackerId = tracker.mPointerId; + + tracker.onLongPressed(); popupPanel.showPanel(this, parentKey, tracker, mPopupWindow); + final int translatedX = popupPanel.translateX(tracker.getLastX()); + final int translatedY = popupPanel.translateY(tracker.getLastY()); + tracker.onDownEvent(translatedX, translatedY, SystemClock.uptimeMillis(), popupPanel); invalidateAllKeys(); return true; } private PointerTracker getPointerTracker(final int id) { - final ArrayList<PointerTracker> pointers = mPointerTrackers; - final KeyboardActionListener listener = mKeyboardActionListener; - final Keyboard keyboard = getKeyboard(); - - // 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, getContext(), mKeyTimerHandler, mKeyDetector, this, - mPointerQueue); - if (keyboard != null) - tracker.setKeyDetector(mKeyDetector); - if (listener != null) - tracker.setKeyboardActionListener(listener); - pointers.add(tracker); - } - - return pointers.get(id); + return PointerTracker.getPointerTracker(id, this); } public boolean isInSlidingKeyInput() { - if (mPopupMiniKeyboardPanel != null) { - return mPopupMiniKeyboardPanel.isInSlidingKeyInput(); + if (mPopupPanel != null) { + return true; } else { - return mPointerQueue.isInSlidingKeyInput(); + return PointerTracker.isAnyInSlidingKeyInput(); } } @@ -521,9 +463,9 @@ public class LatinKeyboardBaseView extends KeyboardView implements PointerTracke } // Gesture detector must be enabled only when mini-keyboard is not on the screen. - if (mPopupMiniKeyboardPanel == null && mGestureDetector != null + if (mPopupPanel == null && mGestureDetector != null && mGestureDetector.onTouchEvent(me)) { - dismissAllKeyPreviews(); + PointerTracker.dismissAllKeyPreviews(); mKeyTimerHandler.cancelKeyTimers(); return true; } @@ -531,13 +473,13 @@ public class LatinKeyboardBaseView extends KeyboardView implements PointerTracke final long eventTime = me.getEventTime(); final int index = me.getActionIndex(); final int id = me.getPointerId(index); - final int x = (int)me.getX(index); - final int y = (int)me.getY(index); - - // Needs to be called after the gesture detector gets a turn, as it may have displayed the - // mini keyboard - if (mPopupMiniKeyboardPanel != null) { - return mPopupMiniKeyboardPanel.onTouchEvent(me); + final int x, y; + if (mPopupPanel != null && id == mPopupPanelPointerTrackerId) { + x = mPopupPanel.translateX((int)me.getX(index)); + y = mPopupPanel.translateY((int)me.getY(index)); + } else { + x = (int)me.getX(index); + y = (int)me.getY(index); } if (mKeyTimerHandler.isInKeyRepeat()) { @@ -585,7 +527,15 @@ public class LatinKeyboardBaseView extends KeyboardView implements PointerTracke if (action == MotionEvent.ACTION_MOVE) { for (int i = 0; i < pointerCount; i++) { final PointerTracker tracker = getPointerTracker(me.getPointerId(i)); - tracker.onMoveEvent((int)me.getX(i), (int)me.getY(i), eventTime); + final int px, py; + if (mPopupPanel != null && tracker.mPointerId == mPopupPanelPointerTrackerId) { + px = mPopupPanel.translateX((int)me.getX(i)); + py = mPopupPanel.translateY((int)me.getY(i)); + } else { + px = (int)me.getX(i); + py = (int)me.getY(i); + } + tracker.onMoveEvent(px, py, eventTime); } } else { processMotionEvent(getPointerTracker(id), action, x, y, eventTime, this); @@ -621,10 +571,11 @@ public class LatinKeyboardBaseView extends KeyboardView implements PointerTracke mPopupPanelCache.clear(); } - private boolean dismissMiniKeyboard() { + public boolean dismissMiniKeyboard() { if (mPopupWindow != null && mPopupWindow.isShowing()) { mPopupWindow.dismiss(); - mPopupMiniKeyboardPanel = null; + mPopupPanel = null; + mPopupPanelPointerTrackerId = -1; invalidateAllKeys(); return true; } diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java index 39d607d95..5f5475ce8 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -96,8 +96,10 @@ public class LatinKeyboardView extends LatinKeyboardBaseView { protected boolean onLongPress(Key key, PointerTracker tracker) { int primaryCode = key.mCode; if (primaryCode == Keyboard.CODE_SETTINGS) { + tracker.onLongPressed(); return invokeOnKey(Keyboard.CODE_SETTINGS_LONGPRESS); } else if (primaryCode == '0' && getLatinKeyboard().isPhoneKeyboard()) { + tracker.onLongPressed(); // Long pressing on 0 in phone number keypad gives you a '+'. return invokeOnKey('+'); } else { diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 29a575ad0..aa2f3af48 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -18,7 +18,6 @@ package com.android.inputmethod.keyboard; import android.content.Context; import android.content.res.Resources; -import android.os.SystemClock; import android.util.Log; import com.android.inputmethod.keyboard.internal.PointerTrackerQueue; @@ -26,6 +25,7 @@ import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.SubtypeSwitcher; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -78,23 +78,24 @@ public class PointerTracker { public void cancelKeyTimers(); } - public final int mPointerId; - + private static KeyboardSwitcher sKeyboardSwitcher; + private static boolean sConfigSlidingKeyInputEnabled; // Timing constants - private final int mDelayBeforeKeyRepeatStart; - private final int mLongPressKeyTimeout; - private final int mLongPressShiftKeyTimeout; + private static int sDelayBeforeKeyRepeatStart; + private static int sLongPressKeyTimeout; + private static int sLongPressShiftKeyTimeout; + private static int sTouchNoiseThresholdMillis; + private static int sTouchNoiseThresholdDistanceSquared; + + private static final List<PointerTracker> sTrackers = new ArrayList<PointerTracker>(); + private static PointerTrackerQueue sPointerTrackerQueue; + + public final int mPointerId; private DrawingProxy mDrawingProxy; private TimerProxy mTimerProxy; - private final PointerTrackerQueue mPointerTrackerQueue; private KeyDetector mKeyDetector; private KeyboardActionListener mListener = EMPTY_LISTENER; - private final KeyboardSwitcher mKeyboardSwitcher; - private final boolean mConfigSlidingKeyInputEnabled; - - private final int mTouchNoiseThresholdMillis; - private final int mTouchNoiseThresholdDistanceSquared; private Keyboard mKeyboard; private List<Key> mKeys; @@ -124,7 +125,7 @@ public class PointerTracker { private boolean mIsRepeatableKey; // true if this pointer is in sliding key input - private boolean mIsInSlidingKeyInput; + boolean mIsInSlidingKeyInput; // true if sliding key is allowed. private boolean mIsAllowedSlidingKeyInput; @@ -136,7 +137,7 @@ public class PointerTracker { // true if this pointer is in sliding language switch private boolean mIsInSlidingLanguageSwitch; private int mSpaceKeyIndex; - private final SubtypeSwitcher mSubtypeSwitcher; + private static SubtypeSwitcher sSubtypeSwitcher; // Empty {@link KeyboardActionListener} private static final KeyboardActionListener EMPTY_LISTENER = new KeyboardActionListener() { @@ -152,31 +153,72 @@ public class PointerTracker { public void onCancelInput() {} }; - public PointerTracker(int id, Context context, TimerProxy timerProxy, KeyDetector keyDetector, - DrawingProxy drawingProxy, PointerTrackerQueue queue) { - if (drawingProxy == null || timerProxy == null || keyDetector == null) - throw new NullPointerException(); - mPointerId = id; - mDrawingProxy = drawingProxy; - mTimerProxy = timerProxy; - mPointerTrackerQueue = queue; // This is null for non-distinct multi-touch device. - setKeyDetectorInner(keyDetector); - mKeyboardSwitcher = KeyboardSwitcher.getInstance(); + public static void init(boolean hasDistinctMultitouch, Context context) { + if (hasDistinctMultitouch) { + sPointerTrackerQueue = new PointerTrackerQueue(); + } else { + sPointerTrackerQueue = null; + } + final Resources res = context.getResources(); - mConfigSlidingKeyInputEnabled = res.getBoolean(R.bool.config_sliding_key_input_enabled); - mDelayBeforeKeyRepeatStart = res.getInteger(R.integer.config_delay_before_key_repeat_start); - mLongPressKeyTimeout = res.getInteger(R.integer.config_long_press_key_timeout); - mLongPressShiftKeyTimeout = res.getInteger(R.integer.config_long_press_shift_key_timeout); - mTouchNoiseThresholdMillis = res.getInteger(R.integer.config_touch_noise_threshold_millis); + sConfigSlidingKeyInputEnabled = res.getBoolean(R.bool.config_sliding_key_input_enabled); + sDelayBeforeKeyRepeatStart = res.getInteger(R.integer.config_delay_before_key_repeat_start); + sLongPressKeyTimeout = res.getInteger(R.integer.config_long_press_key_timeout); + sLongPressShiftKeyTimeout = res.getInteger(R.integer.config_long_press_shift_key_timeout); + sTouchNoiseThresholdMillis = res.getInteger(R.integer.config_touch_noise_threshold_millis); final float touchNoiseThresholdDistance = res.getDimension( R.dimen.config_touch_noise_threshold_distance); - mTouchNoiseThresholdDistanceSquared = (int)( + sTouchNoiseThresholdDistanceSquared = (int)( touchNoiseThresholdDistance * touchNoiseThresholdDistance); - mSubtypeSwitcher = SubtypeSwitcher.getInstance(); + sKeyboardSwitcher = KeyboardSwitcher.getInstance(); + sSubtypeSwitcher = SubtypeSwitcher.getInstance(); } - public void setKeyboardActionListener(KeyboardActionListener listener) { - mListener = listener; + public static PointerTracker getPointerTracker(final int id, KeyEventHandler handler) { + final List<PointerTracker> trackers = sTrackers; + + // Create pointer trackers until we can get 'id+1'-th tracker, if needed. + for (int i = trackers.size(); i <= id; i++) { + final PointerTracker tracker = new PointerTracker(i, handler); + trackers.add(tracker); + } + + return trackers.get(id); + } + + public static boolean isAnyInSlidingKeyInput() { + return sPointerTrackerQueue != null ? sPointerTrackerQueue.isAnyInSlidingKeyInput() : false; + } + + public static void setKeyboardActionListener(KeyboardActionListener listener) { + for (final PointerTracker tracker : sTrackers) { + tracker.mListener = listener; + } + } + + public static void setKeyDetector(KeyDetector keyDetector) { + for (final PointerTracker tracker : sTrackers) { + tracker.setKeyDetectorInner(keyDetector); + // Mark that keyboard layout has been changed. + tracker.mKeyboardLayoutHasBeenChanged = true; + } + } + + public static void dismissAllKeyPreviews() { + for (final PointerTracker tracker : sTrackers) { + tracker.setReleasedKeyGraphics(); + tracker.dismissKeyPreview(); + } + } + + public PointerTracker(int id, KeyEventHandler handler) { + if (handler == null) + throw new NullPointerException(); + mPointerId = id; + setKeyDetectorInner(handler.getKeyDetector()); + mListener = handler.getKeyboardActionListener(); + mDrawingProxy = handler.getDrawingProxy(); + mTimerProxy = handler.getTimerProxy(); } // Returns true if keyboard has been changed by this callback. @@ -244,14 +286,6 @@ public class PointerTracker { mKeyQuarterWidthSquared = keyQuarterWidth * keyQuarterWidth; } - public void setKeyDetector(KeyDetector keyDetector) { - if (keyDetector == null) - throw new NullPointerException(); - setKeyDetectorInner(keyDetector); - // Mark that keyboard layout has been changed. - mKeyboardLayoutHasBeenChanged = true; - } - public boolean isInSlidingKeyInput() { return mIsInSlidingKeyInput; } @@ -361,15 +395,16 @@ public class PointerTracker { printTouchEvent("onDownEvent:", x, y, eventTime); mDrawingProxy = handler.getDrawingProxy(); + mTimerProxy = handler.getTimerProxy(); setKeyboardActionListener(handler.getKeyboardActionListener()); setKeyDetectorInner(handler.getKeyDetector()); // Naive up-to-down noise filter. final long deltaT = eventTime - mUpTime; - if (deltaT < mTouchNoiseThresholdMillis) { + if (deltaT < sTouchNoiseThresholdMillis) { final int dx = x - mLastX; final int dy = y - mLastY; final int distanceSquared = (dx * dx + dy * dy); - if (distanceSquared < mTouchNoiseThresholdDistanceSquared) { + if (distanceSquared < sTouchNoiseThresholdDistanceSquared) { if (DEBUG_MODE) Log.w(TAG, "onDownEvent: ignore potential noise: time=" + deltaT + " distance=" + distanceSquared); @@ -378,7 +413,7 @@ public class PointerTracker { } } - final PointerTrackerQueue queue = mPointerTrackerQueue; + final PointerTrackerQueue queue = sPointerTrackerQueue; if (queue != null) { if (isOnModifierKey(x, y)) { // Before processing a down event of modifier key, all pointers already being @@ -394,7 +429,7 @@ public class PointerTracker { int keyIndex = onDownKey(x, y, eventTime); // Sliding key is allowed when 1) enabled by configuration, 2) this pointer starts sliding // from modifier key, or 3) this pointer is on mini-keyboard. - mIsAllowedSlidingKeyInput = mConfigSlidingKeyInputEnabled || isModifierInternal(keyIndex) + mIsAllowedSlidingKeyInput = sConfigSlidingKeyInputEnabled || isModifierInternal(keyIndex) || mKeyDetector instanceof MiniKeyboardKeyDetector; mKeyboardLayoutHasBeenChanged = false; mKeyAlreadyProcessed = false; @@ -495,8 +530,8 @@ public class PointerTracker { else if (isSpaceKey(keyIndex) && !mIsInSlidingLanguageSwitch && mKeyboard instanceof LatinKeyboard) { final LatinKeyboard keyboard = ((LatinKeyboard)mKeyboard); - if (mSubtypeSwitcher.useSpacebarLanguageSwitcher() - && mSubtypeSwitcher.getEnabledKeyboardLocaleCount() > 1) { + if (sSubtypeSwitcher.useSpacebarLanguageSwitcher() + && sSubtypeSwitcher.getEnabledKeyboardLocaleCount() > 1) { final int diff = x - mKeyX; if (keyboard.shouldTriggerSpacebarSlidingLanguageSwitch(diff)) { // Detect start sliding language switch. @@ -505,7 +540,7 @@ public class PointerTracker { keyboard.updateSpacebarPreviewIcon(diff); // Display spacebar slide language switcher. showKeyPreview(keyIndex); - final PointerTrackerQueue queue = mPointerTrackerQueue; + final PointerTrackerQueue queue = sPointerTrackerQueue; if (queue != null) queue.releaseAllPointersExcept(this, eventTime, true); } @@ -533,7 +568,7 @@ public class PointerTracker { if (DEBUG_EVENT) printTouchEvent("onUpEvent :", x, y, eventTime); - final PointerTrackerQueue queue = mPointerTrackerQueue; + final PointerTrackerQueue queue = sPointerTrackerQueue; if (queue != null) { if (isModifier()) { // Before processing an up event of modifier key, all pointers already being @@ -598,10 +633,10 @@ public class PointerTracker { public void onLongPressed() { mKeyAlreadyProcessed = true; - final PointerTrackerQueue queue = mPointerTrackerQueue; + setReleasedKeyGraphics(); + dismissKeyPreview(); + final PointerTrackerQueue queue = sPointerTrackerQueue; if (queue != null) { - // TODO: Support chording + long-press input. - queue.releaseAllPointersExcept(this, SystemClock.uptimeMillis(), true); queue.remove(this); } } @@ -610,7 +645,7 @@ public class PointerTracker { if (DEBUG_EVENT) printTouchEvent("onCancelEvt:", x, y, eventTime); - final PointerTrackerQueue queue = mPointerTrackerQueue; + final PointerTrackerQueue queue = sPointerTrackerQueue; if (queue != null) { queue.releaseAllPointersExcept(this, eventTime, true); queue.remove(this); @@ -631,7 +666,7 @@ public class PointerTracker { if (key != null && key.mRepeatable) { dismissKeyPreview(); onRepeatKey(keyIndex); - mTimerProxy.startKeyRepeatTimer(mDelayBeforeKeyRepeatStart, keyIndex, this); + mTimerProxy.startKeyRepeatTimer(sDelayBeforeKeyRepeatStart, keyIndex, this); mIsRepeatableKey = true; } else { mIsRepeatableKey = false; @@ -685,16 +720,16 @@ public class PointerTracker { private void startLongPressTimer(int keyIndex) { Key key = getKey(keyIndex); if (key.mCode == Keyboard.CODE_SHIFT) { - mTimerProxy.startLongPressShiftTimer(mLongPressShiftKeyTimeout, keyIndex, this); + mTimerProxy.startLongPressShiftTimer(sLongPressShiftKeyTimeout, keyIndex, this); } else if (key.hasUppercaseLetter() && mKeyboard.isManualTemporaryUpperCase()) { // We need not start long press timer on the key which has manual temporary upper case // code defined and the keyboard is in manual temporary upper case mode. return; - } else if (mKeyboardSwitcher.isInMomentarySwitchState()) { + } else if (sKeyboardSwitcher.isInMomentarySwitchState()) { // We use longer timeout for sliding finger input started from the symbols mode key. - mTimerProxy.startLongPressTimer(mLongPressKeyTimeout * 3, keyIndex, this); + mTimerProxy.startLongPressTimer(sLongPressKeyTimeout * 3, keyIndex, this); } else { - mTimerProxy.startLongPressTimer(mLongPressKeyTimeout, keyIndex, this); + mTimerProxy.startLongPressTimer(sLongPressKeyTimeout, keyIndex, this); } } diff --git a/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java b/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java index a3d9c0465..af8e59568 100644 --- a/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java @@ -18,26 +18,73 @@ package com.android.inputmethod.keyboard; import android.content.Context; import android.content.res.Resources; -import android.os.SystemClock; +import android.content.res.TypedArray; import android.util.AttributeSet; import android.view.Gravity; -import android.view.MotionEvent; import android.view.View; import android.widget.PopupWindow; +import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy; +import com.android.inputmethod.keyboard.PointerTracker.TimerProxy; import com.android.inputmethod.latin.R; /** * A view that renders a virtual {@link MiniKeyboard}. It handles rendering of keys and detecting * key presses and touch movements. */ -public class PopupMiniKeyboardView extends LatinKeyboardBaseView implements PopupPanel { +public class PopupMiniKeyboardView extends KeyboardView implements PopupPanel { private final int[] mCoordinates = new int[2]; private final boolean mConfigShowMiniKeyboardAtTouchedPoint; + private final KeyDetector mKeyDetector; + private final int mVerticalCorrection; + + private LatinKeyboardBaseView mParentKeyboardView; private int mOriginX; private int mOriginY; - private long mDownTime; + + private static final TimerProxy EMPTY_TIMER_PROXY = new TimerProxy() { + @Override + public void startKeyRepeatTimer(long delay, int keyIndex, PointerTracker tracker) {} + @Override + public void startLongPressTimer(long delay, int keyIndex, PointerTracker tracker) {} + @Override + public void startLongPressShiftTimer(long delay, int keyIndex, PointerTracker tracker) {} + @Override + public void cancelLongPressTimers() {} + @Override + public void cancelKeyTimers() {} + }; + + private final KeyboardActionListener mListner = new KeyboardActionListener() { + @Override + public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) { + mParentKeyboardView.getKeyboardActionListener() + .onCodeInput(primaryCode, keyCodes, x, y); + mParentKeyboardView.dismissMiniKeyboard(); + } + + @Override + public void onTextInput(CharSequence text) { + mParentKeyboardView.getKeyboardActionListener().onTextInput(text); + mParentKeyboardView.dismissMiniKeyboard(); + } + + @Override + public void onCancelInput() { + mParentKeyboardView.getKeyboardActionListener().onCancelInput(); + mParentKeyboardView.dismissMiniKeyboard(); + } + + @Override + public void onPress(int primaryCode, boolean withSliding) { + mParentKeyboardView.getKeyboardActionListener().onPress(primaryCode, withSliding); + } + @Override + public void onRelease(int primaryCode, boolean withSliding) { + mParentKeyboardView.getKeyboardActionListener().onRelease(primaryCode, withSliding); + } + }; public PopupMiniKeyboardView(Context context, AttributeSet attrs) { this(context, attrs, R.attr.popupMiniKeyboardViewStyle); @@ -46,6 +93,12 @@ public class PopupMiniKeyboardView extends LatinKeyboardBaseView implements Popu public PopupMiniKeyboardView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); + final TypedArray a = context.obtainStyledAttributes( + attrs, R.styleable.KeyboardView, defStyle, R.style.KeyboardView); + mVerticalCorrection = a.getDimensionPixelOffset( + R.styleable.KeyboardView_verticalCorrection, 0); + a.recycle(); + final Resources res = context.getResources(); mConfigShowMiniKeyboardAtTouchedPoint = res.getBoolean( R.bool.config_show_mini_keyboard_at_touched_point); @@ -53,11 +106,37 @@ public class PopupMiniKeyboardView extends LatinKeyboardBaseView implements Popu mKeyDetector = new MiniKeyboardKeyDetector(res.getDimension( R.dimen.mini_keyboard_slide_allowance)); // Remove gesture detector on mini-keyboard - mGestureDetector = null; setKeyPreviewPopupEnabled(false, 0); } @Override + public void setKeyboard(Keyboard keyboard) { + super.setKeyboard(keyboard); + mKeyDetector.setKeyboard(keyboard, -getPaddingLeft(), + -getPaddingTop() + mVerticalCorrection); + } + + @Override + public KeyDetector getKeyDetector() { + return mKeyDetector; + } + + @Override + public KeyboardActionListener getKeyboardActionListener() { + return mListner; + } + + @Override + public DrawingProxy getDrawingProxy() { + return this; + } + + @Override + public TimerProxy getTimerProxy() { + return EMPTY_TIMER_PROXY; + } + + @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { // Do nothing for the mini keyboard. } @@ -70,8 +149,9 @@ public class PopupMiniKeyboardView extends LatinKeyboardBaseView implements Popu } @Override - public void showPanel(KeyboardView parentKeyboardView, Key parentKey, + public void showPanel(LatinKeyboardBaseView parentKeyboardView, Key parentKey, PointerTracker tracker, PopupWindow window) { + mParentKeyboardView = parentKeyboardView; final View container = (View)getParent(); final MiniKeyboard miniKeyboard = (MiniKeyboard)getKeyboard(); final Keyboard parentKeyboard = parentKeyboardView.getKeyboard(); @@ -99,19 +179,15 @@ public class PopupMiniKeyboardView extends LatinKeyboardBaseView implements Popu mOriginX = x + container.getPaddingLeft() - mCoordinates[0]; mOriginY = y + container.getPaddingTop() - mCoordinates[1]; - mDownTime = SystemClock.uptimeMillis(); - - // Inject down event on the key to mini keyboard. - final MotionEvent downEvent = MotionEvent.obtain(mDownTime, mDownTime, - MotionEvent.ACTION_DOWN, pointX - mOriginX, - pointY + parentKey.mHeight / 2 - mOriginY, 0); - onTouchEvent(downEvent); - downEvent.recycle(); } @Override - public boolean onTouchEvent(MotionEvent me) { - me.offsetLocation(-mOriginX, -mOriginY); - return super.onTouchEvent(me); + public int translateX(int x) { + return x - mOriginX; + } + + @Override + public int translateY(int y) { + return y - mOriginY; } } diff --git a/java/src/com/android/inputmethod/keyboard/PopupPanel.java b/java/src/com/android/inputmethod/keyboard/PopupPanel.java index 2d9130fcb..f94d1c562 100644 --- a/java/src/com/android/inputmethod/keyboard/PopupPanel.java +++ b/java/src/com/android/inputmethod/keyboard/PopupPanel.java @@ -16,7 +16,6 @@ package com.android.inputmethod.keyboard; -import android.view.MotionEvent; import android.widget.PopupWindow; public interface PopupPanel extends PointerTracker.KeyEventHandler { @@ -27,19 +26,20 @@ public interface PopupPanel extends PointerTracker.KeyEventHandler { * @param tracker the pointer tracker that pressesd the parent key * @param window PopupWindow to be used to show this popup panel */ - public void showPanel(KeyboardView parentKeyboardView, Key parentKey, + public void showPanel(LatinKeyboardBaseView parentKeyboardView, Key parentKey, PointerTracker tracker, PopupWindow window); /** - * Check if the pointer is in siding key input mode. - * @return true if the pointer is sliding key input mode. + * Translate X-coordinate of touch event to the local X-coordinate of this PopupPanel. + * @param x the global X-coordinate + * @return the local X-coordinate to this PopupPanel */ - public boolean isInSlidingKeyInput(); + public int translateX(int x); /** - * The motion event handler. - * @param me the MotionEvent to be processed. - * @return true if the motion event is processed and should be consumed. + * Translate Y-coordinate of touch event to the local Y-coordinate of this PopupPanel. + * @param y the global Y-coordinate + * @return the local Y-coordinate to this PopupPanel */ - public boolean onTouchEvent(MotionEvent me); + public int translateY(int y); } diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java index 1530fed6f..535a6954c 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java @@ -34,21 +34,22 @@ public class KeyboardIconsSet { private static final int ICON_TO_SYMBOL_KEY = 2; private static final int ICON_TO_SYMBOL_KEY_WITH_SHORTCUT = 3; private static final int ICON_DELETE_KEY = 4; - private static final int ICON_SETTINGS_KEY = 5; - private static final int ICON_SHORTCUT_KEY = 6; - private static final int ICON_SPACE_KEY = 7; - private static final int ICON_RETURN_KEY = 8; - private static final int ICON_SEARCH_KEY = 9; - private static final int ICON_TAB_KEY = 10; + private static final int ICON_DELETE_RTL_KEY = 5; + private static final int ICON_SETTINGS_KEY = 6; + private static final int ICON_SHORTCUT_KEY = 7; + private static final int ICON_SPACE_KEY = 8; + private static final int ICON_RETURN_KEY = 9; + private static final int ICON_SEARCH_KEY = 10; + private static final int ICON_TAB_KEY = 11; // This should be aligned with Keyboard.keyIconShifted enum. - private static final int ICON_SHIFTED_SHIFT_KEY = 11; + private static final int ICON_SHIFTED_SHIFT_KEY = 12; // This should be aligned with Keyboard.keyIconPreview enum. - private static final int ICON_PREVIEW_SPACE_KEY = 12; - private static final int ICON_PREVIEW_TAB_KEY = 13; - private static final int ICON_PREVIEW_SETTINGS_KEY = 14; - private static final int ICON_PREVIEW_SHORTCUT_KEY = 15; + private static final int ICON_PREVIEW_SPACE_KEY = 13; + private static final int ICON_PREVIEW_TAB_KEY = 14; + private static final int ICON_PREVIEW_SETTINGS_KEY = 15; + private static final int ICON_PREVIEW_SHORTCUT_KEY = 16; - private static final int ICON_LAST = 15; + private static final int ICON_LAST = 16; private final Drawable mIcons[] = new Drawable[ICON_LAST + 1]; @@ -62,6 +63,8 @@ public class KeyboardIconsSet { return ICON_TO_SYMBOL_KEY_WITH_SHORTCUT; case R.styleable.Keyboard_iconDeleteKey: return ICON_DELETE_KEY; + case R.styleable.Keyboard_iconDeleteRtlKey: + return ICON_DELETE_RTL_KEY; case R.styleable.Keyboard_iconSettingsKey: return ICON_SETTINGS_KEY; case R.styleable.Keyboard_iconShortcutKey: diff --git a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java b/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java index f87cd869e..545b27fdc 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java +++ b/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java @@ -63,7 +63,7 @@ public class PointerTrackerQueue { mQueue.remove(tracker); } - public boolean isInSlidingKeyInput() { + public boolean isAnyInSlidingKeyInput() { for (final PointerTracker tracker : mQueue) { if (tracker.isInSlidingKeyInput()) return true; diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index cec30eaab..5304d830d 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1803,19 +1803,18 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar final InputConnection ic = getCurrentInputConnection(); final CharSequence punctuation = ic.getTextBeforeCursor(1, 0); if (deleteChar) ic.deleteSurroundingText(1, 0); - int toDelete = mCommittedLength; - final CharSequence toTheLeft = ic.getTextBeforeCursor(mCommittedLength, 0); - if (!TextUtils.isEmpty(toTheLeft) - && mSettingsValues.isWordSeparator(toTheLeft.charAt(0))) { - toDelete--; - } - ic.deleteSurroundingText(toDelete, 0); + final CharSequence textToTheLeft = ic.getTextBeforeCursor(mCommittedLength, 0); + final int toDeleteLength = (!TextUtils.isEmpty(textToTheLeft) + && mSettingsValues.isWordSeparator(textToTheLeft.charAt(0))) + ? mCommittedLength - 1 : mCommittedLength; + ic.deleteSurroundingText(toDeleteLength, 0); + // Re-insert punctuation only when the deleted character was word separator and the // composing text wasn't equal to the auto-corrected text. if (deleteChar && !TextUtils.isEmpty(punctuation) && mSettingsValues.isWordSeparator(punctuation.charAt(0)) - && !TextUtils.equals(mComposingStringBuilder, toTheLeft)) { + && !TextUtils.equals(mComposingStringBuilder, textToTheLeft)) { ic.commitText(mComposingStringBuilder, 1); TextEntryState.acceptedTyped(mComposingStringBuilder); ic.commitText(punctuation, 1); diff --git a/java/src/com/android/inputmethod/latin/UserDictionary.java b/java/src/com/android/inputmethod/latin/UserDictionary.java index c06bd736e..2aaa26c8d 100644 --- a/java/src/com/android/inputmethod/latin/UserDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserDictionary.java @@ -16,12 +16,14 @@ package com.android.inputmethod.latin; +import android.content.ContentProviderClient; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.database.ContentObserver; import android.database.Cursor; import android.net.Uri; +import android.os.RemoteException; import android.provider.UserDictionary.Words; public class UserDictionary extends ExpandableDictionary { @@ -99,24 +101,34 @@ public class UserDictionary extends ExpandableDictionary { values.put(Words.APP_ID, 0); final ContentResolver contentResolver = getContext().getContentResolver(); + final ContentProviderClient client = + contentResolver.acquireContentProviderClient(Words.CONTENT_URI); + if (null == client) return; new Thread("addWord") { @Override public void run() { - Cursor cursor = contentResolver.query(Words.CONTENT_URI, PROJECTION_ADD, - "word=? and ((locale IS NULL) or (locale=?))", - new String[] { word, mLocale }, null); - if (cursor != null && cursor.moveToFirst()) { - String locale = cursor.getString(cursor.getColumnIndex(Words.LOCALE)); - // If locale is null, we will not override the entry. - if (locale != null && locale.equals(mLocale.toString())) { - long id = cursor.getLong(cursor.getColumnIndex(Words._ID)); - Uri uri = Uri.withAppendedPath(Words.CONTENT_URI, Long.toString(id)); - // Update the entry with new frequency value. - contentResolver.update(uri, values, null, null); + try { + final Cursor cursor = client.query(Words.CONTENT_URI, PROJECTION_ADD, + "word=? and ((locale IS NULL) or (locale=?))", + new String[] { word, mLocale }, null); + if (cursor != null && cursor.moveToFirst()) { + final String locale = cursor.getString(cursor.getColumnIndex(Words.LOCALE)); + // If locale is null, we will not override the entry. + if (locale != null && locale.equals(mLocale.toString())) { + final long id = cursor.getLong(cursor.getColumnIndex(Words._ID)); + final Uri uri = + Uri.withAppendedPath(Words.CONTENT_URI, Long.toString(id)); + // Update the entry with new frequency value. + client.update(uri, values, null, null); + } + } else { + // Insert new entry. + client.insert(Words.CONTENT_URI, values); } - } else { - // Insert new entry. - contentResolver.insert(Words.CONTENT_URI, values); + } catch (RemoteException e) { + // If we come here, the activity is already about to be killed, and we + // have no means of contacting the content provider any more. + // See ContentResolver#insert, inside the catch(){} } } }.start(); |