diff options
Diffstat (limited to 'java/src')
15 files changed, 165 insertions, 648 deletions
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java index 004ee4c22..812bbc881 100644 --- a/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java +++ b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java @@ -18,7 +18,6 @@ package com.android.inputmethod.accessibility; import android.graphics.Rect; import android.inputmethodservice.InputMethodService; -import android.os.Bundle; import android.support.v4.view.ViewCompat; import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; import android.support.v4.view.accessibility.AccessibilityNodeProviderCompat; @@ -34,10 +33,6 @@ import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardView; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - /** * Exposes a virtual view sub-tree for {@link KeyboardView} and generates * {@link AccessibilityEvent}s for individual {@link Key}s. @@ -95,7 +90,6 @@ public class AccessibilityEntityProvider extends AccessibilityNodeProviderCompat final AccessibilityEvent event = AccessibilityEvent.obtain(eventType); event.setPackageName(mKeyboardView.getContext().getPackageName()); event.setClassName(key.getClass().getName()); - event.getText().add(keyDescription); event.setEnabled(true); final AccessibilityRecordCompat record = new AccessibilityRecordCompat(event); @@ -136,7 +130,6 @@ public class AccessibilityEntityProvider extends AccessibilityNodeProviderCompat ViewCompat.onInitializeAccessibilityNodeInfo(mKeyboardView, info); // Add the virtual children of the root View. - // TODO: Need to assign a unique ID to each key. final Keyboard keyboard = mKeyboardView.getKeyboard(); final Key[] keys = keyboard.mKeys; for (Key key : keys) { @@ -163,8 +156,6 @@ public class AccessibilityEntityProvider extends AccessibilityNodeProviderCompat // Obtain and initialize an AccessibilityNodeInfo with // information about the virtual view. info = AccessibilityNodeInfoCompat.obtain(); - info.addAction(AccessibilityNodeInfoCompat.ACTION_SELECT); - info.addAction(AccessibilityNodeInfoCompat.ACTION_CLEAR_SELECTION); info.setPackageName(mKeyboardView.getContext().getPackageName()); info.setClassName(key.getClass().getName()); info.setBoundsInParent(boundsInParent); @@ -173,155 +164,13 @@ public class AccessibilityEntityProvider extends AccessibilityNodeProviderCompat info.setSource(mKeyboardView, virtualViewId); info.setBoundsInScreen(boundsInScreen); info.setText(keyDescription); - info.setClickable(true); info.setEnabled(true); - info.setLongClickable(true); } return info; } /** - * Performs an accessibility action on a virtual view, i.e. a descendant of - * the host View, with the given <code>virtualViewId</code> or the host View itself if - * <code>virtualViewId</code> equals to {@link View#NO_ID}. - * - * @param virtualViewId A client defined virtual view id. - * @param action The action to perform. - * @param arguments Optional arguments. - * @return True if the action was performed. - * @see #createAccessibilityNodeInfo(int) - * @see AccessibilityNodeInfoCompat - */ - @Override - public boolean performAction(int virtualViewId, int action, Bundle arguments) { - if (virtualViewId == View.NO_ID) { - // Perform the action on the host View. - switch (action) { - case AccessibilityNodeInfoCompat.ACTION_SELECT: - if (!mKeyboardView.isSelected()) { - mKeyboardView.setSelected(true); - return mKeyboardView.isSelected(); - } - break; - case AccessibilityNodeInfoCompat.ACTION_CLEAR_SELECTION: - if (mKeyboardView.isSelected()) { - mKeyboardView.setSelected(false); - return !mKeyboardView.isSelected(); - } - break; - } - } else { - // Find the view that corresponds to the given id. - final Key child = mVirtualViewIdToKey.get(virtualViewId); - if (child == null) - return false; - - // Perform the action on a virtual view. - switch (action) { - case AccessibilityNodeInfoCompat.ACTION_SELECT: - // TODO: Provide some focus indicator. - return true; - case AccessibilityNodeInfoCompat.ACTION_CLEAR_SELECTION: - // TODO: Provide some clear focus indicator. - return true; - } - } - - return false; - } - - /** - * Finds {@link AccessibilityNodeInfoCompat}s by text. The match is case - * insensitive containment. The search is relative to the virtual view, i.e. - * a descendant of the host View, with the given <code>virtualViewId</code> or the host - * View itself <code>virtualViewId</code> equals to {@link View#NO_ID}. - * - * @param virtualViewId A client defined virtual view id which defined the - * root of the tree in which to perform the search. - * @param text The searched text. - * @return A list of node info. - * @see #createAccessibilityNodeInfo(int) - * @see AccessibilityNodeInfoCompat - */ - @Override - public List<AccessibilityNodeInfoCompat> findAccessibilityNodeInfosByText( - String text, int virtualViewId) { - final String searchedLowerCase = text.toLowerCase(); - final Keyboard keyboard = mKeyboardView.getKeyboard(); - - List<AccessibilityNodeInfoCompat> results = null; - - if (virtualViewId == View.NO_ID) { - for (Key key : keyboard.mKeys) { - results = findByTextAndPopulate(searchedLowerCase, key, results); - } - } else { - final Key key = mVirtualViewIdToKey.get(virtualViewId); - - results = findByTextAndPopulate(searchedLowerCase, key, results); - } - - if (results == null) { - return Collections.emptyList(); - } - - return results; - } - - /** - * Helper method for {@link #findAccessibilityNodeInfosByText(String, int)}. - * Takes a current set of results and matches a specified key against a - * lower-case search string. Returns an updated list of results. - * - * @param searchedLowerCase The lower-case search string. - * @param key The key to compare against. - * @param results The current list of results, or {@code null} if no results - * found. - * @return An updated list of results, or {@code null} if no results found. - */ - private List<AccessibilityNodeInfoCompat> findByTextAndPopulate(String searchedLowerCase, - Key key, List<AccessibilityNodeInfoCompat> results) { - if (!keyContainsText(key, searchedLowerCase)) { - return results; - } - - final int childVirtualViewId = generateVirtualViewIdForKey(key); - final AccessibilityNodeInfoCompat nodeInfo = createAccessibilityNodeInfo( - childVirtualViewId); - - if (results == null) { - results = new LinkedList<AccessibilityNodeInfoCompat>(); - } - - results.add(nodeInfo); - - return results; - } - - /** - * Returns whether a key's current description contains the lower-case - * search text. - * - * @param key The key to compare against. - * @param textLowerCase The lower-case search string. - * @return {@code true} if the key contains the search text. - */ - private boolean keyContainsText(Key key, String textLowerCase) { - if (key == null) { - return false; - } - - final String description = getKeyDescription(key); - - if (description == null) { - return false; - } - - return description.toLowerCase().contains(textLowerCase); - } - - /** * Returns the context-specific description for a {@link Key}. * * @param key The key to describe. diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java index 667b109cb..2ea7d83e4 100644 --- a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java +++ b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java @@ -58,7 +58,6 @@ public class AccessibilityUtils { // These only need to be initialized if the kill switch is off. sInstance.initInternal(inputMethod); KeyCodeDescriptionMapper.init(); - AccessibleInputMethodServiceProxy.init(inputMethod); AccessibleKeyboardViewProxy.init(inputMethod); } diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleInputMethodServiceProxy.java b/java/src/com/android/inputmethod/accessibility/AccessibleInputMethodServiceProxy.java deleted file mode 100644 index 961176bb8..000000000 --- a/java/src/com/android/inputmethod/accessibility/AccessibleInputMethodServiceProxy.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * 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.accessibility; - -import android.content.Context; -import android.inputmethodservice.InputMethodService; -import android.media.AudioManager; -import android.os.Vibrator; -import android.view.KeyEvent; - -public class AccessibleInputMethodServiceProxy implements AccessibleKeyboardActionListener { - private static final AccessibleInputMethodServiceProxy sInstance = - new AccessibleInputMethodServiceProxy(); - - /** - * Duration of the key click vibration in milliseconds. - */ - private static final long VIBRATE_KEY_CLICK = 50; - - private static final float FX_VOLUME = -1.0f; - - private InputMethodService mInputMethod; - private Vibrator mVibrator; - private AudioManager mAudioManager; - - public static void init(InputMethodService inputMethod) { - sInstance.initInternal(inputMethod); - } - - public static AccessibleInputMethodServiceProxy getInstance() { - return sInstance; - } - - private AccessibleInputMethodServiceProxy() { - // Not publicly instantiable. - } - - private void initInternal(InputMethodService inputMethod) { - mInputMethod = inputMethod; - mVibrator = (Vibrator) inputMethod.getSystemService(Context.VIBRATOR_SERVICE); - mAudioManager = (AudioManager) inputMethod.getSystemService(Context.AUDIO_SERVICE); - } - - /** - * Handle flick gestures by mapping them to directional pad keys. - */ - @Override - public void onFlickGesture(int direction) { - switch (direction) { - case FlickGestureDetector.FLICK_LEFT: - sendDownUpKeyEvents(KeyEvent.KEYCODE_DPAD_LEFT); - break; - case FlickGestureDetector.FLICK_RIGHT: - sendDownUpKeyEvents(KeyEvent.KEYCODE_DPAD_RIGHT); - break; - } - } - - /** - * Provide haptic feedback and send the specified keyCode to the input - * connection as a pair of down/up events. - * - * @param keyCode - */ - private void sendDownUpKeyEvents(int keyCode) { - mVibrator.vibrate(VIBRATE_KEY_CLICK); - mAudioManager.playSoundEffect(AudioManager.FX_KEYPRESS_STANDARD, FX_VOLUME); - mInputMethod.sendDownUpKeyEvents(keyCode); - } -} diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardActionListener.java b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardActionListener.java deleted file mode 100644 index 31d17d09f..000000000 --- a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardActionListener.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * 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.accessibility; - -public interface AccessibleKeyboardActionListener { - /** - * @param direction the direction of the flick gesture, one of - * <ul> - * <li>{@link FlickGestureDetector#FLICK_UP} - * <li>{@link FlickGestureDetector#FLICK_DOWN} - * <li>{@link FlickGestureDetector#FLICK_LEFT} - * <li>{@link FlickGestureDetector#FLICK_RIGHT} - * </ul> - */ - public void onFlickGesture(int direction); -} diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java index c85a5514e..ba814e390 100644 --- a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java +++ b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java @@ -17,8 +17,6 @@ package com.android.inputmethod.accessibility; import android.content.Context; -import android.graphics.Color; -import android.graphics.Paint; import android.inputmethodservice.InputMethodService; import android.support.v4.view.AccessibilityDelegateCompat; import android.support.v4.view.ViewCompat; @@ -38,16 +36,13 @@ public class AccessibleKeyboardViewProxy extends AccessibilityDelegateCompat { private static final AccessibleKeyboardViewProxy sInstance = new AccessibleKeyboardViewProxy(); private InputMethodService mInputMethod; - private FlickGestureDetector mGestureDetector; private LatinKeyboardView mView; - private AccessibleKeyboardActionListener mListener; private AccessibilityEntityProvider mAccessibilityNodeProvider; private Key mLastHoverKey = null; public static void init(InputMethodService inputMethod) { sInstance.initInternal(inputMethod); - sInstance.mListener = AccessibleInputMethodServiceProxy.getInstance(); } public static AccessibleKeyboardViewProxy getInstance() { @@ -59,14 +54,7 @@ public class AccessibleKeyboardViewProxy extends AccessibilityDelegateCompat { } private void initInternal(InputMethodService inputMethod) { - final Paint paint = new Paint(); - paint.setTextAlign(Paint.Align.LEFT); - paint.setTextSize(14.0f); - paint.setAntiAlias(true); - paint.setColor(Color.YELLOW); - mInputMethod = inputMethod; - mGestureDetector = new KeyboardFlickGestureDetector(inputMethod); } /** @@ -112,19 +100,6 @@ public class AccessibleKeyboardViewProxy extends AccessibilityDelegateCompat { * @return {@code true} if the event is handled */ public boolean dispatchHoverEvent(MotionEvent event, PointerTracker tracker) { - if (mGestureDetector.onHoverEvent(event, this, tracker)) - return true; - - return onHoverEventInternal(event, tracker); - } - - /** - * Handles touch exploration events when Accessibility is turned on. - * - * @param event The touch exploration hover event. - * @return {@code true} if the event was handled - */ - /* package */boolean onHoverEventInternal(MotionEvent event, PointerTracker tracker) { final int x = (int) event.getX(); final int y = (int) event.getY(); final Key key = tracker.getKeyOn(x, y); @@ -214,20 +189,6 @@ public class AccessibleKeyboardViewProxy extends AccessibilityDelegateCompat { mView.getParent().requestSendAccessibilityEvent(mView, event); } - private class KeyboardFlickGestureDetector extends FlickGestureDetector { - public KeyboardFlickGestureDetector(Context context) { - super(context); - } - - @Override - public boolean onFlick(MotionEvent e1, MotionEvent e2, int direction) { - if (mListener != null) { - mListener.onFlickGesture(direction); - } - return true; - } - } - /** * Notifies the user of changes in the keyboard shift state. */ diff --git a/java/src/com/android/inputmethod/accessibility/FlickGestureDetector.java b/java/src/com/android/inputmethod/accessibility/FlickGestureDetector.java deleted file mode 100644 index e8ec37600..000000000 --- a/java/src/com/android/inputmethod/accessibility/FlickGestureDetector.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * 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.accessibility; - -import android.content.Context; -import android.os.Message; -import android.view.MotionEvent; -import android.view.ViewConfiguration; - -import com.android.inputmethod.keyboard.PointerTracker; -import com.android.inputmethod.latin.StaticInnerHandlerWrapper; - -/** - * Detects flick gestures within a stream of hover events. - * <p> - * A flick gesture is defined as a stream of hover events with the following - * properties: - * <ul> - * <li>Begins with a {@link MotionEvent#ACTION_HOVER_ENTER} event - * <li>Contains any number of {@link MotionEvent#ACTION_HOVER_MOVE} - * events - * <li>Ends with a {@link MotionEvent#ACTION_HOVER_EXIT} event - * <li>Maximum duration of 250 milliseconds - * <li>Minimum distance between enter and exit points must be at least equal to - * scaled double tap slop (see - * {@link ViewConfiguration#getScaledDoubleTapSlop()}) - * </ul> - * <p> - * Initial enter events are intercepted and cached until the stream fails to - * satisfy the constraints defined above, at which point the cached enter event - * is sent to its source {@link AccessibleKeyboardViewProxy} and subsequent move - * and exit events are ignored. - */ -public abstract class FlickGestureDetector { - public static final int FLICK_UP = 0; - public static final int FLICK_RIGHT = 1; - public static final int FLICK_LEFT = 2; - public static final int FLICK_DOWN = 3; - - private final FlickHandler mFlickHandler; - private final int mFlickRadiusSquare; - - private AccessibleKeyboardViewProxy mCachedView; - private PointerTracker mCachedTracker; - private MotionEvent mCachedHoverEnter; - - private static class FlickHandler extends StaticInnerHandlerWrapper<FlickGestureDetector> { - private static final int MSG_FLICK_TIMEOUT = 1; - - /** The maximum duration of a flick gesture in milliseconds. */ - private static final int DELAY_FLICK_TIMEOUT = 250; - - public FlickHandler(FlickGestureDetector outerInstance) { - super(outerInstance); - } - - @Override - public void handleMessage(Message msg) { - final FlickGestureDetector gestureDetector = getOuterInstance(); - - switch (msg.what) { - case MSG_FLICK_TIMEOUT: - gestureDetector.clearFlick(true); - } - } - - public void startFlickTimeout() { - cancelFlickTimeout(); - sendEmptyMessageDelayed(MSG_FLICK_TIMEOUT, DELAY_FLICK_TIMEOUT); - } - - public void cancelFlickTimeout() { - removeMessages(MSG_FLICK_TIMEOUT); - } - } - - /** - * Creates a new flick gesture detector. - * - * @param context The parent context. - */ - public FlickGestureDetector(Context context) { - final int doubleTapSlop = ViewConfiguration.get(context).getScaledDoubleTapSlop(); - - mFlickHandler = new FlickHandler(this); - mFlickRadiusSquare = doubleTapSlop * doubleTapSlop; - } - - /** - * Processes motion events to detect flick gestures. - * - * @param event The current event. - * @param view The source of the event. - * @param tracker A pointer tracker for the event. - * @return {@code true} if the event was handled. - */ - public boolean onHoverEvent(MotionEvent event, AccessibleKeyboardViewProxy view, - PointerTracker tracker) { - // Always cache and consume the first hover event. - if (event.getAction() == MotionEvent.ACTION_HOVER_ENTER) { - mCachedView = view; - mCachedTracker = tracker; - mCachedHoverEnter = MotionEvent.obtain(event); - mFlickHandler.startFlickTimeout(); - return true; - } - - // Stop if the event has already been canceled. - if (mCachedHoverEnter == null) { - return false; - } - - final float distanceSquare = calculateDistanceSquare(mCachedHoverEnter, event); - - switch (event.getAction()) { - case MotionEvent.ACTION_HOVER_MOVE: - // Consume all valid move events before timeout. - return true; - case MotionEvent.ACTION_HOVER_EXIT: - // Ignore exit events outside the flick radius. - if (distanceSquare < mFlickRadiusSquare) { - clearFlick(true); - return false; - } else { - return dispatchFlick(mCachedHoverEnter, event); - } - default: - return false; - } - } - - /** - * Clears the cached flick information and optionally forwards the event to - * the source view's internal hover event handler. - * - * @param sendCachedEvent Set to {@code true} to forward the hover event to - * the source view. - */ - private void clearFlick(boolean sendCachedEvent) { - mFlickHandler.cancelFlickTimeout(); - - if (mCachedHoverEnter != null) { - if (sendCachedEvent) { - mCachedView.onHoverEventInternal(mCachedHoverEnter, mCachedTracker); - } - mCachedHoverEnter.recycle(); - mCachedHoverEnter = null; - } - - mCachedTracker = null; - mCachedView = null; - } - - /** - * Computes the direction of a flick gesture and forwards it to - * {@link #onFlick(MotionEvent, MotionEvent, int)} for handling. - * - * @param e1 The {@link MotionEvent#ACTION_HOVER_ENTER} event where the flick started. - * @param e2 The {@link MotionEvent#ACTION_HOVER_EXIT} event where the flick ended. - * @return {@code true} if the flick event was handled. - */ - private boolean dispatchFlick(MotionEvent e1, MotionEvent e2) { - clearFlick(false); - - final float dX = e2.getX() - e1.getX(); - final float dY = e2.getY() - e1.getY(); - final int direction; - - if (dY > dX) { - if (dY > -dX) { - direction = FLICK_DOWN; - } else { - direction = FLICK_LEFT; - } - } else { - if (dY > -dX) { - direction = FLICK_RIGHT; - } else { - direction = FLICK_UP; - } - } - - return onFlick(e1, e2, direction); - } - - private float calculateDistanceSquare(MotionEvent e1, MotionEvent e2) { - final float dX = e2.getX() - e1.getX(); - final float dY = e2.getY() - e1.getY(); - return (dX * dX) + (dY * dY); - } - - /** - * Handles a detected flick gesture. - * - * @param e1 The {@link MotionEventCompatUtils#ACTION_HOVER_ENTER} event - * where the flick started. - * @param e2 The {@link MotionEventCompatUtils#ACTION_HOVER_EXIT} event - * where the flick ended. - * @param direction The direction of the flick event, one of: - * <ul> - * <li>{@link #FLICK_UP} - * <li>{@link #FLICK_DOWN} - * <li>{@link #FLICK_LEFT} - * <li>{@link #FLICK_RIGHT} - * </ul> - * @return {@code true} if the flick event was handled. - */ - public abstract boolean onFlick(MotionEvent e1, MotionEvent e2, int direction); -} diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index 0d2e9f0ad..9be193ba7 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -272,8 +272,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { public final Drawable mPreviewBackground; public final Drawable mPreviewLeftBackground; public final Drawable mPreviewRightBackground; - public final int mPreviewBackgroundWidth; - public final int mPreviewBackgroundHeight; public final int mPreviewTextColor; public final int mPreviewOffset; public final int mPreviewHeight; @@ -283,6 +281,31 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { private final float mPreviewTextRatio; private final float mKeyLetterRatio; + // The graphical geometry of the key preview. + // <-width-> + // +-------+ ^ + // | | | + // |preview| height (visible) + // | | | + // + + ^ v + // \ / |offset + // +-\ /-+ v + // | +-+ | + // |parent | + // | key| + // +-------+ + // The background of a {@link TextView} being used for a key preview may have invisible + // paddings. To align the more keys keyboard panel's visible part with the visible part of + // the background, we need to record the width and height of key preview that don't include + // invisible paddings. + public int mPreviewVisibleWidth; + public int mPreviewVisibleHeight; + // The key preview may have an arbitrary offset and its background that may have a bottom + // padding. To align the more keys keyboard and the key preview we also need to record the + // offset between the top edge of parent key and the bottom of the visible part of key + // preview background. + public int mPreviewVisibleOffset; + public int mPreviewTextSize; public int mKeyLetterSize; public final int[] mCoordinates = new int[2]; @@ -298,10 +321,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { setAlpha(mPreviewBackground, PREVIEW_ALPHA); setAlpha(mPreviewLeftBackground, PREVIEW_ALPHA); setAlpha(mPreviewRightBackground, PREVIEW_ALPHA); - mPreviewBackgroundWidth = a.getDimensionPixelSize( - R.styleable.KeyboardView_keyPreviewBackgroundWidth, 0); - mPreviewBackgroundHeight = a.getDimensionPixelSize( - R.styleable.KeyboardView_keyPreviewBackgroundHeight, 0); mPreviewOffset = a.getDimensionPixelOffset( R.styleable.KeyboardView_keyPreviewOffset, 0); mPreviewHeight = a.getDimensionPixelSize( @@ -839,13 +858,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { } @Override - public void showKeyPreview(PointerTracker tracker) { - if (mShowKeyPreviewPopup) { - showKey(tracker); - } - } - - @Override public void dismissKeyPreview(PointerTracker tracker) { mDrawingHandler.dismissKeyPreview(mDelayAfterPreview, tracker); } @@ -861,7 +873,10 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { keyPreview, ViewLayoutUtils.newLayoutParam(mPreviewPlacer, 0, 0)); } - private void showKey(PointerTracker tracker) { + @Override + public void showKeyPreview(PointerTracker tracker) { + if (!mShowKeyPreviewPopup) return; + final TextView previewText = tracker.getKeyPreviewText(); // If the key preview has no parent view yet, add it to the ViewGroup which can place // key preview absolutely in SoftInputWindow. @@ -878,8 +893,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { return; final KeyPreviewDrawParams params = mKeyPreviewDrawParams; - final int keyDrawX = key.mX + key.mVisualInsetsLeft; - final int keyDrawWidth = key.mWidth - key.mVisualInsetsLeft - key.mVisualInsetsRight; final String label = key.isShiftedLetterActivated() ? key.mHintLabel : key.mLabel; // What we show as preview should match what we show on a key top in onBufferDraw(). if (label != null) { @@ -902,13 +915,24 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { previewText.measure( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); - final int previewWidth = Math.max(previewText.getMeasuredWidth(), keyDrawWidth - + previewText.getPaddingLeft() + previewText.getPaddingRight()); + final int keyDrawWidth = key.mWidth - key.mVisualInsetsLeft - key.mVisualInsetsRight; + final int previewWidth = previewText.getMeasuredWidth(); final int previewHeight = params.mPreviewHeight; + // The width and height of visible part of the key preview background. The content marker + // of the background 9-patch have to cover the visible part of the background. + params.mPreviewVisibleWidth = previewWidth - previewText.getPaddingLeft() + - previewText.getPaddingRight(); + params.mPreviewVisibleHeight = previewHeight - previewText.getPaddingTop() + - previewText.getPaddingBottom(); + // The distance between the top edge of the parent key and the bottom of the visible part + // of the key preview background. + params.mPreviewVisibleOffset = params.mPreviewOffset - previewText.getPaddingBottom(); getLocationInWindow(params.mCoordinates); - int previewX = keyDrawX - (previewWidth - keyDrawWidth) / 2 + params.mCoordinates[0]; - final int previewY = key.mY - previewHeight - + params.mCoordinates[1] + params.mPreviewOffset; + // The key preview is horizontally aligned with the center of the visible part of the + // parent key. If it doesn't fit in this {@link KeyboardView}, it is moved inward to fit and + // the left/right background is used if such background is specified. + int previewX = key.mX + key.mVisualInsetsLeft - (previewWidth - keyDrawWidth) / 2 + + params.mCoordinates[0]; if (previewX < 0) { previewX = 0; if (params.mPreviewLeftBackground != null) { @@ -920,6 +944,10 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { previewText.setBackgroundDrawable(params.mPreviewRightBackground); } } + // The key preview is placed vertically above the top edge of the parent key with an + // arbitrary offset. + final int previewY = key.mY - previewHeight + params.mPreviewOffset + + params.mCoordinates[1]; // Set the preview background state previewText.getBackground().setState( diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java index 58bd845e1..aeca839f1 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -110,7 +110,6 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke private final boolean mConfigShowMoreKeysKeyboardAtTouchedPoint; private final PointerTrackerParams mPointerTrackerParams; - private final boolean mIsSpacebarTriggeringPopupByLongPress; private final SuddenJumpingTouchEventHandler mTouchScreenRegulator; protected KeyDetector mKeyDetector; @@ -197,29 +196,27 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke @Override public void startLongPressTimer(PointerTracker tracker) { cancelLongPressTimer(); - if (tracker != null) { - final Key key = tracker.getKey(); - final int delay; - switch (key.mCode) { - case Keyboard.CODE_SHIFT: - delay = mParams.mLongPressShiftKeyTimeout; - break; - case Keyboard.CODE_SPACE: - delay = mParams.mLongPressSpaceKeyTimeout; - break; - default: - if (KeyboardSwitcher.getInstance().isInMomentarySwitchState()) { - // We use longer timeout for sliding finger input started from the symbols - // mode key. - delay = mParams.mLongPressKeyTimeout * 3; - } else { - delay = mParams.mLongPressKeyTimeout; - } - break; - } - if (delay > 0) { - sendMessageDelayed(obtainMessage(MSG_LONGPRESS_KEY, tracker), delay); + if (tracker == null) { + return; + } + final Key key = tracker.getKey(); + final int delay; + switch (key.mCode) { + case Keyboard.CODE_SHIFT: + delay = mParams.mLongPressShiftKeyTimeout; + break; + default: + if (KeyboardSwitcher.getInstance().isInMomentarySwitchState()) { + // We use longer timeout for sliding finger input started from the symbols + // mode key. + delay = mParams.mLongPressKeyTimeout * 3; + } else { + delay = mParams.mLongPressKeyTimeout; } + break; + } + if (delay > 0) { + sendMessageDelayed(obtainMessage(MSG_LONGPRESS_KEY, tracker), delay); } } @@ -314,7 +311,6 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke public final int mKeyRepeatInterval; public final int mLongPressKeyTimeout; public final int mLongPressShiftKeyTimeout; - public final int mLongPressSpaceKeyTimeout; public final int mIgnoreAltCodeKeyTimeout; public KeyTimerParams(TypedArray latinKeyboardViewAttr) { @@ -326,8 +322,6 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke R.styleable.LatinKeyboardView_longPressKeyTimeout, 0); mLongPressShiftKeyTimeout = latinKeyboardViewAttr.getInt( R.styleable.LatinKeyboardView_longPressShiftKeyTimeout, 0); - mLongPressSpaceKeyTimeout = latinKeyboardViewAttr.getInt( - R.styleable.LatinKeyboardView_longPressSpaceKeyTimeout, 0); mIgnoreAltCodeKeyTimeout = latinKeyboardViewAttr.getInt( R.styleable.LatinKeyboardView_ignoreAltCodeKeyTimeout, 0); } @@ -369,7 +363,6 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke final KeyTimerParams keyTimerParams = new KeyTimerParams(a); mPointerTrackerParams = new PointerTrackerParams(a); - mIsSpacebarTriggeringPopupByLongPress = (keyTimerParams.mLongPressSpaceKeyTimeout > 0); final float keyHysteresisDistance = a.getDimension( R.styleable.LatinKeyboardView_keyHysteresisDistance, 0); @@ -534,9 +527,8 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke final MoreKeysKeyboardView moreKeysKeyboardView = (MoreKeysKeyboardView)container.findViewById(R.id.more_keys_keyboard_view); - final Keyboard parentKeyboard = getKeyboard(); - final Keyboard moreKeysKeyboard = new MoreKeysKeyboard.Builder( - this, parentKeyboard.mMoreKeysTemplate, parentKey, parentKeyboard).build(); + final Keyboard moreKeysKeyboard = new MoreKeysKeyboard.Builder(container, parentKey, this) + .build(); moreKeysKeyboardView.setKeyboard(moreKeysKeyboard); container.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); @@ -605,10 +597,19 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke mMoreKeysPanel = moreKeysPanel; mMoreKeysPanelPointerTrackerId = tracker.mPointerId; - final Keyboard keyboard = getKeyboard(); - final int pointX = (mConfigShowMoreKeysKeyboardAtTouchedPoint) ? tracker.getLastX() + final boolean keyPreviewEnabled = isKeyPreviewPopupEnabled() && !parentKey.noKeyPreview(); + // The more keys keyboard is usually horizontally aligned with the center of the parent key. + // If showMoreKeysKeyboardAtTouchedPoint is true and the key preview is disabled, the more + // keys keyboard is placed at the touch point of the parent key. + final int pointX = (mConfigShowMoreKeysKeyboardAtTouchedPoint && !keyPreviewEnabled) + ? tracker.getLastX() : parentKey.mX + parentKey.mWidth / 2; - final int pointY = parentKey.mY - keyboard.mVerticalGap; + // The more keys keyboard is usually vertically aligned with the top edge of the parent key + // (plus vertical gap). If the key preview is enabled, the more keys keyboard is vertically + // aligned with the bottom edge of the visible part of the key preview. + final int pointY = parentKey.mY + (keyPreviewEnabled + ? mKeyPreviewDrawParams.mPreviewVisibleOffset + : -parentKey.mVerticalGap); moreKeysPanel.showMoreKeysPanel( this, this, pointX, pointY, mMoreKeysWindow, mKeyboardActionListener); final int translatedX = moreKeysPanel.translateX(tracker.getLastX()); @@ -881,9 +882,8 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke drawSpacebar(key, canvas, paint); // Whether space key needs to show the "..." popup hint for special purposes - if (mIsSpacebarTriggeringPopupByLongPress - && ImfUtils.hasMultipleEnabledIMEsOrSubtypes( - getContext(), true /* include aux subtypes */)) { + if (key.isLongPressEnabled() && ImfUtils.hasMultipleEnabledIMEsOrSubtypes( + getContext(), true /* include aux subtypes */)) { drawKeyPopupHint(key, canvas, paint, params); } } else if (key.mCode == Keyboard.CODE_LANGUAGE_SWITCH) { diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java index 7154086e2..b6a06e136 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java @@ -18,6 +18,7 @@ package com.android.inputmethod.keyboard; import android.graphics.Paint; import android.graphics.drawable.Drawable; +import android.view.View; import com.android.inputmethod.keyboard.internal.KeySpecParser.MoreKeySpec; import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; @@ -251,30 +252,38 @@ public class MoreKeysKeyboard extends Keyboard { } } - public Builder(KeyboardView view, int xmlId, Key parentKey, Keyboard parentKeyboard) { - super(view.getContext(), new MoreKeysKeyboardParams()); - load(xmlId, parentKeyboard.mId); + /** + * The builder of MoreKeysKeyboard. + * @param containerView the container of {@link MoreKeysKeyboardView}. + * @param parentKey the {@link Key} that invokes more keys keyboard. + * @param parentKeyboardView the {@link KeyboardView} that contains the parentKey. + */ + public Builder(View containerView, Key parentKey, KeyboardView parentKeyboardView) { + super(containerView.getContext(), new MoreKeysKeyboardParams()); + final Keyboard parentKeyboard = parentKeyboardView.getKeyboard(); + load(parentKeyboard.mMoreKeysTemplate, parentKeyboard.mId); // TODO: More keys keyboard's vertical gap is currently calculated heuristically. // Should revise the algorithm. mParams.mVerticalGap = parentKeyboard.mVerticalGap / 2; mParentKey = parentKey; - final int previewWidth = view.mKeyPreviewDrawParams.mPreviewBackgroundWidth; - final int previewHeight = view.mKeyPreviewDrawParams.mPreviewBackgroundHeight; final int width, height; - // Use pre-computed width and height if these values are available and more keys - // keyboard has only one key to mitigate visual flicker between key preview and more - // keys keyboard. - final boolean validKeyPreview = view.isKeyPreviewPopupEnabled() - && !parentKey.noKeyPreview() && (previewWidth > 0) && (previewHeight > 0); - final boolean singleMoreKeyWithPreview = validKeyPreview - && parentKey.mMoreKeys.length == 1; + final boolean singleMoreKeyWithPreview = parentKeyboardView.isKeyPreviewPopupEnabled() + && !parentKey.noKeyPreview() && parentKey.mMoreKeys.length == 1; if (singleMoreKeyWithPreview) { - width = previewWidth; - height = previewHeight + mParams.mVerticalGap; + // Use pre-computed width and height if this more keys keyboard has only one key to + // mitigate visual flicker between key preview and more keys keyboard. + // Caveats for the visual assets: To achieve this effect, both the key preview + // backgrounds and the more keys keyboard panel background have the exact same + // left/right/top paddings. The bottom paddings of both backgrounds don't need to + // be considered because the vertical positions of both backgrounds were already + // adjusted with their bottom paddings deducted. + width = parentKeyboardView.mKeyPreviewDrawParams.mPreviewVisibleWidth; + height = parentKeyboardView.mKeyPreviewDrawParams.mPreviewVisibleHeight + + mParams.mVerticalGap; } else { - width = getMaxKeyWidth(view, parentKey, mParams.mDefaultKeyWidth); + width = getMaxKeyWidth(parentKeyboardView, parentKey, mParams.mDefaultKeyWidth); height = parentKeyboard.mMostCommonKeyHeight; } final int dividerWidth; @@ -288,8 +297,9 @@ public class MoreKeysKeyboard extends Keyboard { dividerWidth = 0; } mParams.setParameters(parentKey.mMoreKeys.length, parentKey.getMoreKeysColumn(), - width, height, parentKey.mX + parentKey.mWidth / 2, view.getMeasuredWidth(), - parentKey.isFixedColumnOrderMoreKeys(), dividerWidth); + width, height, parentKey.mX + parentKey.mWidth / 2, + parentKeyboardView.getMeasuredWidth(), parentKey.isFixedColumnOrderMoreKeys(), + dividerWidth); } private static int getMaxKeyWidth(KeyboardView view, Key parentKey, int minKeyWidth) { diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java index e60fc9598..b4fa86dd5 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java @@ -141,10 +141,8 @@ public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel final MoreKeysKeyboard pane = (MoreKeysKeyboard)getKeyboard(); final int defaultCoordX = pane.getDefaultCoordX(); // The coordinates of panel's left-top corner in parentView's coordinate system. - final int x = pointX - defaultCoordX - container.getPaddingLeft() - + parentView.getPaddingLeft(); - final int y = pointY - container.getMeasuredHeight() + container.getPaddingBottom() - + parentView.getPaddingTop(); + final int x = pointX - defaultCoordX - container.getPaddingLeft(); + final int y = pointY - container.getMeasuredHeight() + container.getPaddingBottom(); window.setContentView(container); window.setWidth(container.getMeasuredWidth()); diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 37d9b6ac7..c62c3ddbc 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -606,7 +606,7 @@ public class PointerTracker { if (ProductionFlag.IS_EXPERIMENTAL) { ResearchLogger.pointerTracker_onMoveEvent(x, y, lastX, lastY); } - onUpEventInternal(lastX, lastY, eventTime); + onUpEventInternal(); onDownEventInternal(x, y, eventTime); } else { mKeyAlreadyProcessed = true; @@ -646,7 +646,7 @@ public class PointerTracker { } queue.remove(this); } - onUpEventInternal(x, y, eventTime); + onUpEventInternal(); } // Let this pointer tracker know that one of newer-than-this pointer trackers got an up event. @@ -655,24 +655,15 @@ public class PointerTracker { public void onPhantomUpEvent(int x, int y, long eventTime) { if (DEBUG_EVENT) printTouchEvent("onPhntEvent:", x, y, eventTime); - onUpEventInternal(x, y, eventTime); + onUpEventInternal(); mKeyAlreadyProcessed = true; } - private void onUpEventInternal(int x, int y, long eventTime) { + private void onUpEventInternal() { mTimerProxy.cancelKeyTimers(); mIsInSlidingKeyInput = false; - final int keyX, keyY; - if (isMajorEnoughMoveToBeOnNewKey(x, y, onMoveKey(x, y))) { - keyX = x; - keyY = y; - } else { - // Use previous fixed key coordinates. - keyX = mKeyX; - keyY = mKeyY; - } - final Key key = onUpKey(keyX, keyY, eventTime); - setReleasedKeyGraphics(key); + // Release the last pressed key. + setReleasedKeyGraphics(mCurrentKey); if (mIsShowingMoreKeysPanel) { mDrawingProxy.dismissMoreKeysPanel(); mIsShowingMoreKeysPanel = false; @@ -680,7 +671,7 @@ public class PointerTracker { if (mKeyAlreadyProcessed) return; if (!mIsRepeatableKey) { - detectAndSendKey(key, keyX, keyY); + detectAndSendKey(mCurrentKey, mKeyX, mKeyY); } } diff --git a/java/src/com/android/inputmethod/latin/EditingUtils.java b/java/src/com/android/inputmethod/latin/EditingUtils.java index 7d673175e..93106ac27 100644 --- a/java/src/com/android/inputmethod/latin/EditingUtils.java +++ b/java/src/com/android/inputmethod/latin/EditingUtils.java @@ -38,8 +38,7 @@ public class EditingUtils { private static int getCursorPosition(InputConnection connection) { if (null == connection) return INVALID_CURSOR_POSITION; - ExtractedText extracted = connection.getExtractedText( - new ExtractedTextRequest(), 0); + final ExtractedText extracted = connection.getExtractedText(new ExtractedTextRequest(), 0); if (extracted == null) { return INVALID_CURSOR_POSITION; } diff --git a/java/src/com/android/inputmethod/latin/InputAttributes.java b/java/src/com/android/inputmethod/latin/InputAttributes.java index 9c32f947c..229ae2f3c 100644 --- a/java/src/com/android/inputmethod/latin/InputAttributes.java +++ b/java/src/com/android/inputmethod/latin/InputAttributes.java @@ -29,6 +29,7 @@ public class InputAttributes { final public boolean mInputTypeNoAutoCorrect; final public boolean mIsSettingsSuggestionStripOn; final public boolean mApplicationSpecifiedCompletionOn; + final public int mEditorAction; public InputAttributes(final EditorInfo editorInfo, final boolean isFullscreenMode) { final int inputType = null != editorInfo ? editorInfo.inputType : 0; @@ -91,6 +92,8 @@ public class InputAttributes { mApplicationSpecifiedCompletionOn = flagAutoComplete && isFullscreenMode; } + mEditorAction = (editorInfo == null) ? EditorInfo.IME_ACTION_UNSPECIFIED + : editorInfo.imeOptions & EditorInfo.IME_MASK_ACTION; } @SuppressWarnings("unused") diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 7232a4883..213c0ac82 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1026,13 +1026,25 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } public boolean getCurrentAutoCapsState() { + if (!mSettingsValues.mAutoCap) return false; + + final EditorInfo ei = getCurrentInputEditorInfo(); + if (ei == null) return false; + + final int inputType = ei.inputType; + if ((inputType & InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS) != 0) return true; + + final boolean noNeedToCheckCapsMode = (inputType & (InputType.TYPE_TEXT_FLAG_CAP_SENTENCES + | InputType.TYPE_TEXT_FLAG_CAP_WORDS)) == 0; + if (noNeedToCheckCapsMode) return false; + final InputConnection ic = getCurrentInputConnection(); - EditorInfo ei = getCurrentInputEditorInfo(); - if (mSettingsValues.mAutoCap && ic != null && ei != null - && ei.inputType != InputType.TYPE_NULL) { - return ic.getCursorCapsMode(ei.inputType) != 0; - } - return false; + if (ic == null) return false; + // TODO: This blocking IPC call is heavy. Consider doing this without using IPC calls. + // Note: getCursorCapsMode() returns the current capitalization mode that is any + // combination of CAP_MODE_CHARACTERS, CAP_MODE_WORDS, and CAP_MODE_SENTENCES. 0 means none + // of them. + return ic.getCursorCapsMode(inputType) != 0; } // "ic" may be null @@ -1257,6 +1269,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen handleLanguageSwitchKey(); break; default: + if (primaryCode == Keyboard.CODE_TAB + && mInputAttributes.mEditorAction == EditorInfo.IME_ACTION_NEXT) { + performEditorAction(EditorInfo.IME_ACTION_NEXT); + break; + } mSpaceState = SPACE_STATE_NONE; if (mSettingsValues.isWordSeparator(primaryCode)) { didAutoCorrect = handleSeparator(primaryCode, x, y, spaceState); @@ -1473,22 +1490,23 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen sendKeyCodePoint(Keyboard.CODE_SPACE); } - if ((isAlphabet(primaryCode) + // NOTE: isCursorTouchingWord() is a blocking IPC call, so it often takes several + // dozen milliseconds. Avoid calling it as much as possible, since we are on the UI + // thread here. + if (!isComposingWord && (isAlphabet(primaryCode) || mSettingsValues.isSymbolExcludedFromWordSeparators(primaryCode)) && isSuggestionsRequested() && !isCursorTouchingWord()) { - if (!isComposingWord) { - // Reset entirely the composing state anyway, then start composing a new word unless - // the character is a single quote. The idea here is, single quote is not a - // separator and it should be treated as a normal character, except in the first - // position where it should not start composing a word. - isComposingWord = (Keyboard.CODE_SINGLE_QUOTE != primaryCode); - // Here we don't need to reset the last composed word. It will be reset - // when we commit this one, if we ever do; if on the other hand we backspace - // it entirely and resume suggestions on the previous word, we'd like to still - // have touch coordinates for it. - resetComposingState(false /* alsoResetLastComposedWord */); - clearSuggestions(); - } + // Reset entirely the composing state anyway, then start composing a new word unless + // the character is a single quote. The idea here is, single quote is not a + // separator and it should be treated as a normal character, except in the first + // position where it should not start composing a word. + isComposingWord = (Keyboard.CODE_SINGLE_QUOTE != primaryCode); + // Here we don't need to reset the last composed word. It will be reset + // when we commit this one, if we ever do; if on the other hand we backspace + // it entirely and resume suggestions on the previous word, we'd like to still + // have touch coordinates for it. + resetComposingState(false /* alsoResetLastComposedWord */); + clearSuggestions(); } if (isComposingWord) { mWordComposer.add( diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java index e64e7a685..8a29dcc13 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java @@ -149,10 +149,8 @@ public class MoreSuggestionsView extends KeyboardView implements MoreKeysPanel { final MoreSuggestions pane = (MoreSuggestions)getKeyboard(); final int defaultCoordX = pane.mOccupiedWidth / 2; // The coordinates of panel's left-top corner in parentView's coordinate system. - final int x = pointX - defaultCoordX - container.getPaddingLeft() - + parentView.getPaddingLeft(); - final int y = pointY - container.getMeasuredHeight() + container.getPaddingBottom() - + parentView.getPaddingTop(); + final int x = pointX - defaultCoordX - container.getPaddingLeft(); + final int y = pointY - container.getMeasuredHeight() + container.getPaddingBottom(); window.setContentView(container); window.setWidth(container.getMeasuredWidth()); |