diff options
Diffstat (limited to 'java/src')
8 files changed, 259 insertions, 436 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index 766fdf0e6..582705866 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -125,7 +125,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { // Popup mini keyboard private PopupWindow mMiniKeyboardPopup; - private KeyboardView mMiniKeyboard; + private KeyboardView mMiniKeyboardView; private View mMiniKeyboardParent; private final WeakHashMap<Key, View> mMiniKeyboardCache = new WeakHashMap<Key, View>(); private int mMiniKeyboardOriginX; @@ -134,6 +134,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { private int[] mWindowOffset; private final float mMiniKeyboardSlideAllowance; private int mMiniKeyboardTrackerId; + private final boolean mConfigShowMiniKeyboardAtTouchedPoint; /** Listener for {@link KeyboardActionListener}. */ private KeyboardActionListener mKeyboardActionListener; @@ -296,7 +297,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { public KeyboardView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); - TypedArray a = context.obtainStyledAttributes( + final TypedArray a = context.obtainStyledAttributes( attrs, R.styleable.KeyboardView, defStyle, R.style.KeyboardView); int previewLayout = 0; int keyTextSize = 0; @@ -381,6 +382,8 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { mMiniKeyboardPopup = new PopupWindow(context); mMiniKeyboardPopup.setBackgroundDrawable(null); mMiniKeyboardPopup.setAnimationStyle(R.style.MiniKeyboardAnimation); + // Allow popup window to be drawn off the screen. + mMiniKeyboardPopup.setClippingEnabled(false); mPaint = new Paint(); mPaint.setAntiAlias(true); @@ -395,10 +398,12 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { // TODO: Refer frameworks/base/core/res/res/values/config.xml mDisambiguateSwipe = res.getBoolean(R.bool.config_swipeDisambiguation); mMiniKeyboardSlideAllowance = res.getDimension(R.dimen.mini_keyboard_slide_allowance); + mConfigShowMiniKeyboardAtTouchedPoint = res.getBoolean( + R.bool.config_show_mini_keyboard_at_touched_point); GestureDetector.SimpleOnGestureListener listener = new GestureDetector.SimpleOnGestureListener() { - private boolean mProcessingDoubleTapEvent = false; + private boolean mProcessingShiftDoubleTapEvent = false; @Override public boolean onFling(MotionEvent me1, MotionEvent me2, float velocityX, @@ -419,25 +424,39 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { } @Override - public boolean onDoubleTap(MotionEvent e) { + public boolean onDoubleTap(MotionEvent firstDown) { if (ENABLE_CAPSLOCK_BY_DOUBLETAP && mKeyboard instanceof LatinKeyboard && ((LatinKeyboard) mKeyboard).isAlphaKeyboard()) { - final int pointerIndex = e.getActionIndex(); - final int id = e.getPointerId(pointerIndex); + final int pointerIndex = firstDown.getActionIndex(); + final int id = firstDown.getPointerId(pointerIndex); final PointerTracker tracker = getPointerTracker(id); - if (tracker.isOnShiftKey((int)e.getX(), (int)e.getY())) { - onDoubleTapShiftKey(tracker); - mProcessingDoubleTapEvent = true; + // If the first down event is on shift key. + if (tracker.isOnShiftKey((int)firstDown.getX(), (int)firstDown.getY())) { + mProcessingShiftDoubleTapEvent = true; return true; } } - mProcessingDoubleTapEvent = false; + mProcessingShiftDoubleTapEvent = false; return false; } @Override - public boolean onDoubleTapEvent(MotionEvent e) { - return mProcessingDoubleTapEvent; + public boolean onDoubleTapEvent(MotionEvent secondTap) { + if (mProcessingShiftDoubleTapEvent + && secondTap.getAction() == MotionEvent.ACTION_DOWN) { + final MotionEvent secondDown = secondTap; + final int pointerIndex = secondDown.getActionIndex(); + final int id = secondDown.getPointerId(pointerIndex); + final PointerTracker tracker = getPointerTracker(id); + // If the second down event is also on shift key. + if (tracker.isOnShiftKey((int)secondDown.getX(), (int)secondDown.getY())) { + onDoubleTapShiftKey(tracker); + return true; + } + // Otherwise these events should not be handled as double tap. + mProcessingShiftDoubleTapEvent = false; + } + return mProcessingShiftDoubleTapEvent; } }; @@ -535,10 +554,6 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { return mColorScheme; } - public void setPopupParent(View v) { - mMiniKeyboardParent = v; - } - public void setPopupOffset(int x, int y) { mPopupPreviewOffsetX = x; mPopupPreviewOffsetY = y; @@ -798,7 +813,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { mInvalidatedKey = null; // Overlay a dark rectangle to dim the keyboard - if (mMiniKeyboard != null) { + if (mMiniKeyboardView != null) { paint.setColor((int) (mBackgroundDimAmount * 0xFF) << 24); canvas.drawRect(0, 0, getWidth(), getHeight(), paint); } @@ -1052,7 +1067,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { Key popupKey = tracker.getKey(keyIndex); if (popupKey == null) return false; - boolean result = onLongPress(popupKey); + boolean result = onLongPress(popupKey, tracker); if (result) { dismissKeyPreview(); mMiniKeyboardTrackerId = tracker.mPointerId; @@ -1077,14 +1092,13 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { } private View inflateMiniKeyboardContainer(Key popupKey) { - int popupKeyboardResId = mKeyboard.getPopupKeyboardResId(); - View container = LayoutInflater.from(getContext()).inflate(mPopupLayout, null); + final View container = LayoutInflater.from(getContext()).inflate(mPopupLayout, null); if (container == null) throw new NullPointerException(); - KeyboardView miniKeyboard = + final KeyboardView miniKeyboardView = (KeyboardView)container.findViewById(R.id.KeyboardView); - miniKeyboard.setOnKeyboardActionListener(new KeyboardActionListener() { + miniKeyboardView.setOnKeyboardActionListener(new KeyboardActionListener() { @Override public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) { mKeyboardActionListener.onCodeInput(primaryCode, keyCodes, x, y); @@ -1117,14 +1131,14 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { } }); // Override default ProximityKeyDetector. - miniKeyboard.mKeyDetector = new MiniKeyboardKeyDetector(mMiniKeyboardSlideAllowance); + miniKeyboardView.mKeyDetector = new MiniKeyboardKeyDetector(mMiniKeyboardSlideAllowance); // Remove gesture detector on mini-keyboard - miniKeyboard.mGestureDetector = null; + miniKeyboardView.mGestureDetector = null; - Keyboard keyboard = new MiniKeyboardBuilder(this, popupKeyboardResId, popupKey) - .build(); - miniKeyboard.setKeyboard(keyboard); - miniKeyboard.setPopupParent(this); + final Keyboard keyboard = new MiniKeyboardBuilder(this, mKeyboard.getPopupKeyboardResId(), + popupKey).build(); + miniKeyboardView.setKeyboard(keyboard); + miniKeyboardView.mMiniKeyboardParent = this; container.measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST)); @@ -1152,7 +1166,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { * @return true if the long press is handled, false otherwise. Subclasses should call the * method on the base class if the subclass doesn't wish to handle the call. */ - protected boolean onLongPress(Key popupKey) { + protected boolean onLongPress(Key popupKey, PointerTracker tracker) { if (popupKey.mPopupCharacters == null) return false; @@ -1161,93 +1175,51 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { container = inflateMiniKeyboardContainer(popupKey); mMiniKeyboardCache.put(popupKey, container); } - mMiniKeyboard = (KeyboardView)container.findViewById(R.id.KeyboardView); + mMiniKeyboardView = (KeyboardView)container.findViewById(R.id.KeyboardView); + final MiniKeyboard miniKeyboard = (MiniKeyboard)mMiniKeyboardView.getKeyboard(); + if (mWindowOffset == null) { mWindowOffset = new int[2]; getLocationInWindow(mWindowOffset); } - - // Get width of a key in the mini popup keyboard = "miniKeyWidth". - // On the other hand, "popupKey.width" is width of the pressed key on the main keyboard. - // We adjust the position of mini popup keyboard with the edge key in it: - // a) When we have the leftmost key in popup keyboard directly above the pressed key - // Right edges of both keys should be aligned for consistent default selection - // b) When we have the rightmost key in popup keyboard directly above the pressed key - // Left edges of both keys should be aligned for consistent default selection - final List<Key> miniKeys = mMiniKeyboard.getKeyboard().getKeys(); - final int miniKeyWidth = miniKeys.size() > 0 ? miniKeys.get(0).mWidth : 0; - - // HACK: Have the leftmost number in the popup characters right above the key - boolean isNumberAtLeftmost = - hasMultiplePopupChars(popupKey) && isNumberAtLeftmostPopupChar(popupKey); - int popupX = popupKey.mX + mWindowOffset[0]; - popupX += getPaddingLeft(); - if (isNumberAtLeftmost) { - popupX += popupKey.mWidth - miniKeyWidth; // adjustment for a) described above - popupX -= container.getPaddingLeft(); - } else { - popupX += miniKeyWidth; // adjustment for b) described above - popupX -= container.getMeasuredWidth(); - popupX += container.getPaddingRight(); - } - int popupY = popupKey.mY + mWindowOffset[1]; - popupY += getPaddingTop(); - popupY -= container.getMeasuredHeight(); - popupY += container.getPaddingBottom(); + final int pointX = (mConfigShowMiniKeyboardAtTouchedPoint) ? tracker.getLastX() + : popupKey.mX + popupKey.mWidth / 2; + final int popupX = pointX - miniKeyboard.getDefaultCoordX() + - container.getPaddingLeft() + + getPaddingLeft() + mWindowOffset[0]; + final int popupY = popupKey.mY - mKeyboard.getVerticalGap() + - (container.getMeasuredHeight() - container.getPaddingBottom()) + + getPaddingTop() + mWindowOffset[1]; final int x = popupX; - final int y = mShowPreview && isOneRowKeys(miniKeys) ? mPopupPreviewDisplayedY : popupY; + final int y = mShowPreview && isOneRowKeys(miniKeyboard.getKeys()) + ? mPopupPreviewDisplayedY : popupY; - int adjustedX = x; - if (x < 0) { - adjustedX = 0; - } else if (x > (getMeasuredWidth() - container.getMeasuredWidth())) { - adjustedX = getMeasuredWidth() - container.getMeasuredWidth(); - } - mMiniKeyboardOriginX = adjustedX + container.getPaddingLeft() - mWindowOffset[0]; + mMiniKeyboardOriginX = x + container.getPaddingLeft() - mWindowOffset[0]; mMiniKeyboardOriginY = y + container.getPaddingTop() - mWindowOffset[1]; - mMiniKeyboard.setPopupOffset(adjustedX, y); - Keyboard baseMiniKeyboard = mMiniKeyboard.getKeyboard(); - if (baseMiniKeyboard != null && baseMiniKeyboard.setShifted(mKeyboard == null - ? false : mKeyboard.isShiftedOrShiftLocked())) { - mMiniKeyboard.invalidateAllKeys(); + mMiniKeyboardView.setPopupOffset(x, y); + if (miniKeyboard.setShifted( + mKeyboard == null ? false : mKeyboard.isShiftedOrShiftLocked())) { + mMiniKeyboardView.invalidateAllKeys(); } // Mini keyboard needs no pop-up key preview displayed. - mMiniKeyboard.setPreviewEnabled(false); + mMiniKeyboardView.setPreviewEnabled(false); mMiniKeyboardPopup.setContentView(container); mMiniKeyboardPopup.setWidth(container.getMeasuredWidth()); mMiniKeyboardPopup.setHeight(container.getMeasuredHeight()); mMiniKeyboardPopup.showAtLocation(this, Gravity.NO_GRAVITY, x, y); // Inject down event on the key to mini keyboard. - long eventTime = SystemClock.uptimeMillis(); + final long eventTime = SystemClock.uptimeMillis(); mMiniKeyboardPopupTime = eventTime; - MotionEvent downEvent = generateMiniKeyboardMotionEvent(MotionEvent.ACTION_DOWN, popupKey.mX - + popupKey.mWidth / 2, popupKey.mY + popupKey.mHeight / 2, eventTime); - mMiniKeyboard.onTouchEvent(downEvent); + final MotionEvent downEvent = generateMiniKeyboardMotionEvent(MotionEvent.ACTION_DOWN, + pointX, popupKey.mY + popupKey.mHeight / 2, eventTime); + mMiniKeyboardView.onTouchEvent(downEvent); downEvent.recycle(); invalidateAllKeys(); return true; } - private static boolean hasMultiplePopupChars(Key key) { - if (key.mPopupCharacters != null && key.mPopupCharacters.length > 1) { - return true; - } - return false; - } - - private static boolean isNumberAtLeftmostPopupChar(Key key) { - if (key.mPopupCharacters != null && isAsciiDigit(key.mPopupCharacters[0].charAt(0))) { - return true; - } - return false; - } - - private static boolean isAsciiDigit(char c) { - return (c < 0x80) && Character.isDigit(c); - } - private MotionEvent generateMiniKeyboardMotionEvent(int action, int x, int y, long eventTime) { return MotionEvent.obtain(mMiniKeyboardPopupTime, eventTime, action, x - mMiniKeyboardOriginX, y - mMiniKeyboardOriginY, 0); @@ -1273,8 +1245,8 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { } public boolean isInSlidingKeyInput() { - if (mMiniKeyboard != null) { - return mMiniKeyboard.isInSlidingKeyInput(); + if (mMiniKeyboardView != null) { + return mMiniKeyboardView.isInSlidingKeyInput(); } else { return mPointerQueue.isInSlidingKeyInput(); } @@ -1302,7 +1274,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { mSwipeTracker.addMovement(me); // Gesture detector must be enabled only when mini-keyboard is not on the screen. - if (mMiniKeyboard == null + if (mMiniKeyboardView == null && mGestureDetector != null && mGestureDetector.onTouchEvent(me)) { dismissKeyPreview(); mHandler.cancelKeyTimers(); @@ -1317,14 +1289,14 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { // Needs to be called after the gesture detector gets a turn, as it may have // displayed the mini keyboard - if (mMiniKeyboard != null) { + if (mMiniKeyboardView != null) { final int miniKeyboardPointerIndex = me.findPointerIndex(mMiniKeyboardTrackerId); if (miniKeyboardPointerIndex >= 0 && miniKeyboardPointerIndex < pointerCount) { final int miniKeyboardX = (int)me.getX(miniKeyboardPointerIndex); final int miniKeyboardY = (int)me.getY(miniKeyboardPointerIndex); MotionEvent translated = generateMiniKeyboardMotionEvent(action, miniKeyboardX, miniKeyboardY, eventTime); - mMiniKeyboard.onTouchEvent(translated); + mMiniKeyboardView.onTouchEvent(translated); translated.recycle(); } return true; @@ -1422,7 +1394,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { private void dismissPopupKeyboard() { if (mMiniKeyboardPopup.isShowing()) { mMiniKeyboardPopup.dismiss(); - mMiniKeyboard = null; + mMiniKeyboardView = null; mMiniKeyboardOriginX = 0; mMiniKeyboardOriginY = 0; invalidateAllKeys(); diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java index 888375b93..1977f5fae 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java @@ -315,11 +315,7 @@ public class LatinKeyboard extends Keyboard { int x = pointX; int y = pointY; final int code = key.mCode; - if (code == CODE_SHIFT || code == CODE_DELETE) { - y -= key.mHeight / 10; - if (code == CODE_SHIFT) x += key.mWidth / 6; - if (code == CODE_DELETE) x -= key.mWidth / 6; - } else if (code == CODE_SPACE) { + if (code == CODE_SPACE) { y += LatinKeyboard.sSpacebarVerticalCorrection; if (SubtypeSwitcher.getInstance().useSpacebarLanguageSwitcher() && SubtypeSwitcher.getInstance().getEnabledKeyboardLocaleCount() > 1) { diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java index e9d5580e8..94294e40a 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -94,7 +94,7 @@ public class LatinKeyboardView extends KeyboardView { } @Override - protected boolean onLongPress(Key key) { + protected boolean onLongPress(Key key, PointerTracker tracker) { int primaryCode = key.mCode; if (primaryCode == Keyboard.CODE_SETTINGS) { return invokeOnKey(Keyboard.CODE_SETTINGS_LONGPRESS); @@ -102,7 +102,7 @@ public class LatinKeyboardView extends KeyboardView { // Long pressing on 0 in phone number keypad gives you a '+'. return invokeOnKey('+'); } else { - return super.onLongPress(key); + return super.onLongPress(key, tracker); } } diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java new file mode 100644 index 000000000..3b1408ccf --- /dev/null +++ b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.android.inputmethod.keyboard; + +import android.content.Context; + +public class MiniKeyboard extends Keyboard { + private int mDefaultKeyCoordX; + + public MiniKeyboard(Context context, int xmlLayoutResId, KeyboardId id) { + super(context, xmlLayoutResId, id); + } + + public void setDefaultCoordX(int pos) { + mDefaultKeyCoordX = pos; + } + + public int getDefaultCoordX() { + return mDefaultKeyCoordX; + } +} diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboardBuilder.java index c150baadb..53dab9440 100644 --- a/java/src/com/android/inputmethod/keyboard/MiniKeyboardBuilder.java +++ b/java/src/com/android/inputmethod/keyboard/MiniKeyboardBuilder.java @@ -27,44 +27,141 @@ import java.util.List; public class MiniKeyboardBuilder { private final Resources mRes; - private final Keyboard mKeyboard; + private final MiniKeyboard mKeyboard; private final CharSequence[] mPopupCharacters; - private final int mMiniKeyboardKeyHorizontalPadding; - private final int mKeyWidth; - private final int mMaxColumns; - private final int mNumRows; - private int mColPos; - private int mRowPos; - private int mX; - private int mY; + private final MiniKeyboardLayoutParams mParams; + + /* package */ static class MiniKeyboardLayoutParams { + public final int mKeyWidth; + public final int mRowHeight; + /* package */ final boolean mTopRowNeedsCentering; + public final int mNumRows; + public final int mNumColumns; + public final int mLeftKeys; + public final int mRightKeys; // includes default key. + + /** + * The object holding mini keyboard layout parameters. + * + * @param numKeys number of keys in this mini keyboard. + * @param maxColumns number of maximum columns of this mini keyboard. + * @param keyWidth mini keyboard key width in pixel, including horizontal gap. + * @param rowHeight mini keyboard row height in pixel, including vertical gap. + * @param coordXInParent coordinate x of the popup key in parent keyboard. + * @param parentKeyboardWidth parent keyboard width in pixel. + */ + public MiniKeyboardLayoutParams(int numKeys, int maxColumns, int keyWidth, int rowHeight, + int coordXInParent, int parentKeyboardWidth) { + if (parentKeyboardWidth / keyWidth < maxColumns) + throw new IllegalArgumentException("Keyboard is too small to hold mini keyboard: " + + parentKeyboardWidth + " " + keyWidth + " " + maxColumns); + final int numRows = (numKeys + maxColumns - 1) / maxColumns; + mKeyWidth = keyWidth; + mRowHeight = rowHeight; + mNumRows = numRows; + + final int numColumns = Math.min(numKeys, maxColumns); + final int topRowKeys = numKeys % numColumns; + mNumColumns = numColumns; + mTopRowNeedsCentering = topRowKeys != 0 && (numColumns - topRowKeys) % 2 != 0; + + final int numLeftKeys = (numColumns - 1) / 2; + final int numRightKeys = numColumns - numLeftKeys; // including default key. + final int maxLeftKeys = coordXInParent / keyWidth; + final int maxRightKeys = Math.max(1, (parentKeyboardWidth - coordXInParent) / keyWidth); + if (numLeftKeys > maxLeftKeys) { + mLeftKeys = maxLeftKeys; + mRightKeys = numColumns - maxLeftKeys; + } else if (numRightKeys > maxRightKeys) { + mLeftKeys = numColumns - maxRightKeys; + mRightKeys = maxRightKeys; + } else { + mLeftKeys = numLeftKeys; + mRightKeys = numRightKeys; + } + } + + // Return key position according to column count (0 is default). + /* package */ int getColumnPos(int n) { + final int col = n % mNumColumns; + if (col == 0) { + // default position. + return 0; + } + int pos = 0; + int right = 1; // include default position key. + int left = 0; + int i = 0; + while (true) { + // Assign right key if available. + if (right < mRightKeys) { + pos = right; + right++; + i++; + } + if (i >= col) + break; + // Assign left key if available. + if (left < mLeftKeys) { + left++; + pos = -left; + i++; + } + if (i >= col) + break; + } + return pos; + } + + public int getDefaultKeyCoordX() { + return mLeftKeys * mKeyWidth; + } + + public int getX(int n, int row) { + final int x = getColumnPos(n) * mKeyWidth + getDefaultKeyCoordX(); + if (isLastRow(row) && mTopRowNeedsCentering) + return x - mKeyWidth / 2; + return x; + } + + public int getY(int row) { + return (mNumRows - 1 - row) * mRowHeight; + } + + public int getRowFlags(int row) { + int rowFlags = 0; + if (row == 0) rowFlags |= Keyboard.EDGE_TOP; + if (isLastRow(row)) rowFlags |= Keyboard.EDGE_BOTTOM; + return rowFlags; + } + + private boolean isLastRow(int rowCount) { + return rowCount == mNumRows - 1; + } + } public MiniKeyboardBuilder(KeyboardView view, int layoutTemplateResId, Key popupKey) { final Context context = view.getContext(); mRes = context.getResources(); - final Keyboard keyboard = new Keyboard(context, layoutTemplateResId, null); + final MiniKeyboard keyboard = new MiniKeyboard(context, layoutTemplateResId, null); mKeyboard = keyboard; mPopupCharacters = popupKey.mPopupCharacters; - mMiniKeyboardKeyHorizontalPadding = (int)mRes.getDimension( - R.dimen.mini_keyboard_key_horizontal_padding); - mKeyWidth = getMaxKeyWidth(view, mPopupCharacters, mKeyboard.getKeyWidth()); - final int maxColumns = popupKey.mMaxPopupColumn; - mMaxColumns = maxColumns; - final int numKeys = mPopupCharacters.length; - int numRows = numKeys / maxColumns; - if (numKeys % maxColumns != 0) numRows++; - mNumRows = numRows; - keyboard.setHeight((keyboard.getRowHeight() + keyboard.getVerticalGap()) * numRows - - keyboard.getVerticalGap()); - if (numRows > 1) { - mColPos = numKeys % maxColumns; - if (mColPos > 0) mColPos = maxColumns - mColPos; - // Centering top-row keys. - mX = mColPos * (mKeyWidth + keyboard.getHorizontalGap()) / 2; - } - mKeyboard.setMinWidth(0); + + final int keyWidth = getMaxKeyWidth(view, mPopupCharacters, keyboard.getKeyWidth()); + final MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams( + mPopupCharacters.length, popupKey.mMaxPopupColumn, + keyWidth, keyboard.getRowHeight(), + popupKey.mX + (popupKey.mWidth + popupKey.mGap) / 2 - keyWidth / 2, + view.getMeasuredWidth()); + mParams = params; + + keyboard.setHeight(params.mNumRows * params.mRowHeight - keyboard.getVerticalGap()); + keyboard.setMinWidth(params.mNumColumns * params.mKeyWidth); + keyboard.setDefaultCoordX(params.getDefaultKeyCoordX() + params.mKeyWidth / 2); } - private int getMaxKeyWidth(KeyboardView view, CharSequence[] popupCharacters, int minKeyWidth) { + private static int getMaxKeyWidth(KeyboardView view, CharSequence[] popupCharacters, + int minKeyWidth) { Paint paint = null; Rect bounds = null; int maxWidth = 0; @@ -84,46 +181,22 @@ public class MiniKeyboardBuilder { maxWidth = bounds.width(); } } - return Math.max(minKeyWidth, maxWidth + mMiniKeyboardKeyHorizontalPadding); + final int horizontalPadding = (int)view.getContext().getResources().getDimension( + R.dimen.mini_keyboard_key_horizontal_padding); + return Math.max(minKeyWidth, maxWidth + horizontalPadding); } - public Keyboard build() { - final Keyboard keyboard = mKeyboard; + public MiniKeyboard build() { + final MiniKeyboard keyboard = mKeyboard; final List<Key> keys = keyboard.getKeys(); - for (CharSequence label : mPopupCharacters) { - refresh(); - final Key key = new Key(mRes, keyboard, label, mX, mY, mKeyWidth, getRowFlags()); + final MiniKeyboardLayoutParams params = mParams; + for (int n = 0; n < mPopupCharacters.length; n++) { + final CharSequence label = mPopupCharacters[n]; + final int row = n / params.mNumColumns; + final Key key = new Key(mRes, keyboard, label, params.getX(n, row), params.getY(row), + params.mKeyWidth, params.getRowFlags(row)); keys.add(key); - advance(); } return keyboard; } - - private int getRowFlags() { - final int rowPos = mRowPos; - int rowFlags = 0; - if (rowPos == 0) rowFlags |= Keyboard.EDGE_TOP; - if (rowPos == mNumRows - 1) rowFlags |= Keyboard.EDGE_BOTTOM; - return rowFlags; - } - - private void refresh() { - if (mColPos >= mMaxColumns) { - final Keyboard keyboard = mKeyboard; - // TODO: Allocate key position depending the precedence of popup characters. - mX = 0; - mY += keyboard.getRowHeight() + keyboard.getVerticalGap(); - mColPos = 0; - mRowPos++; - } - } - - private void advance() { - final Keyboard keyboard = mKeyboard; - // TODO: Allocate key position depending the precedence of popup characters. - mX += mKeyWidth + keyboard.getHorizontalGap(); - if (mX > keyboard.getMinWidth()) - keyboard.setMinWidth(mX); - mColPos++; - } } diff --git a/java/src/com/android/inputmethod/latin/ClipTouchEventWindowCallback.java b/java/src/com/android/inputmethod/latin/ClipTouchEventWindowCallback.java deleted file mode 100644 index d12c70075..000000000 --- a/java/src/com/android/inputmethod/latin/ClipTouchEventWindowCallback.java +++ /dev/null @@ -1,75 +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.latin; - -import android.view.MotionEvent; -import android.view.View; -import android.view.Window; - -public class ClipTouchEventWindowCallback extends WindowCallbackAdapter { - private final View mDecorView; - private final int mKeyboardBottomRowVerticalCorrection; - - public ClipTouchEventWindowCallback(Window window, int keyboardBottomRowVerticalCorrection) { - super(window.getCallback()); - mDecorView = window.getDecorView(); - mKeyboardBottomRowVerticalCorrection = keyboardBottomRowVerticalCorrection; - } - - @Override - public boolean dispatchTouchEvent(MotionEvent me) { - final int height = mDecorView.getHeight(); - final MotionEvent event = clipMotionEvent(me, height, - height + mKeyboardBottomRowVerticalCorrection); - return super.dispatchTouchEvent(event); - } - - private static MotionEvent clipMotionEvent(MotionEvent me, int minHeight, int maxHeight) { - final int pointerCount = me.getPointerCount(); - boolean shouldClip = false; - for (int pointerIndex = 0; pointerIndex < pointerCount; pointerIndex++) { - final float y = me.getY(pointerIndex); - if (y >= minHeight && y < maxHeight) { - shouldClip = true; - break; - } - } - if (!shouldClip) - return me; - - if (pointerCount == 1) { - me.setLocation(me.getX(), minHeight - 1); - return me; - } - - final int[] pointerIds = new int[pointerCount]; - final MotionEvent.PointerCoords[] pointerCoords = - new MotionEvent.PointerCoords[pointerCount]; - for (int pointerIndex = 0; pointerIndex < pointerCount; pointerIndex++) { - pointerIds[pointerIndex] = me.getPointerId(pointerIndex); - final MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords(); - me.getPointerCoords(pointerIndex, coords); - pointerCoords[pointerIndex] = coords; - if (coords.y >= minHeight && coords.y < maxHeight) - coords.y = minHeight - 1; - } - return MotionEvent.obtain( - me.getDownTime(), me.getEventTime(), me.getAction(), pointerCount, pointerIds, - pointerCoords, me.getMetaState(), me.getXPrecision(), me.getYPrecision(), - me.getDeviceId(), me.getEdgeFlags(), me.getSource(), me.getFlags()); - } -} diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 84415ecee..78674b4e4 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -157,8 +157,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private int mConfigDelayBeforeFadeoutLanguageOnSpacebar; private int mConfigDurationOfFadeoutLanguageOnSpacebar; private float mConfigFinalFadeoutFactorOfLanguageOnSpacebar; - // For example, to deal with status bar on tablet. - private int mKeyboardBottomRowVerticalCorrection; private int mCorrectionMode; private int mCommittedLength; @@ -375,8 +373,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen R.integer.config_duration_of_fadeout_language_on_spacebar); mConfigFinalFadeoutFactorOfLanguageOnSpacebar = res.getInteger( R.integer.config_final_fadeout_percentage_of_language_on_spacebar) / 100.0f; - mKeyboardBottomRowVerticalCorrection = (int)res.getDimension( - R.dimen.keyboard_bottom_row_vertical_correction); Utils.GCUtils.getInstance().reset(); boolean tryGC = true; @@ -569,14 +565,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mVoiceConnector.onStartInputView(inputView.getWindowToken()); - if (mKeyboardBottomRowVerticalCorrection > 0) { - final Window window = getWindow().getWindow(); - if (!(window.getCallback() instanceof ClipTouchEventWindowCallback)) { - window.setCallback(new ClipTouchEventWindowCallback( - window, mKeyboardBottomRowVerticalCorrection)); - } - } - if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); } @@ -891,13 +879,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (mCandidateViewContainer != null) { ViewParent candidateParent = mCandidateViewContainer.getParent(); if (candidateParent instanceof FrameLayout) { - final FrameLayout fl = (FrameLayout) candidateParent; - // Check frame layout's visibility - if (fl.getVisibility() == View.INVISIBLE) { - y = fl.getHeight(); - height += y; - } else if (fl.getVisibility() == View.VISIBLE) { - height += fl.getHeight(); + FrameLayout fl = (FrameLayout) candidateParent; + if (fl != null) { + // Check frame layout's visibility + if (fl.getVisibility() == View.INVISIBLE) { + y = fl.getHeight(); + height += y; + } else if (fl.getVisibility() == View.VISIBLE) { + height += fl.getHeight(); + } } } } @@ -2234,9 +2224,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen di.dismiss(); switch (position) { case 0: - launchSettings(); - break; - case 1: Intent intent = new Intent( android.provider.Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK @@ -2246,6 +2233,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mInputMethodId); startActivity(intent); break; + case 1: + launchSettings(); + break; } } }; diff --git a/java/src/com/android/inputmethod/latin/WindowCallbackAdapter.java b/java/src/com/android/inputmethod/latin/WindowCallbackAdapter.java deleted file mode 100644 index be9bb2bd8..000000000 --- a/java/src/com/android/inputmethod/latin/WindowCallbackAdapter.java +++ /dev/null @@ -1,168 +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.latin; - -import android.view.ActionMode; -import android.view.ActionMode.Callback; -import android.view.KeyEvent; -import android.view.Menu; -import android.view.MenuItem; -import android.view.MotionEvent; -import android.view.View; -import android.view.Window; -import android.view.WindowManager.LayoutParams; -import android.view.accessibility.AccessibilityEvent; - -public class WindowCallbackAdapter implements Window.Callback { - private final Window.Callback mPreviousCallback; - - public WindowCallbackAdapter(Window.Callback previousCallback) { - mPreviousCallback = previousCallback; - } - - @Override - public boolean dispatchKeyEvent(KeyEvent event) { - if (mPreviousCallback != null) - return mPreviousCallback.dispatchKeyEvent(event); - return false; - } - - @Override - public boolean dispatchKeyShortcutEvent(KeyEvent event) { - if (mPreviousCallback != null) - return mPreviousCallback.dispatchKeyShortcutEvent(event); - return false; - } - - @Override - public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { - if (mPreviousCallback != null) - return mPreviousCallback.dispatchPopulateAccessibilityEvent(event); - return false; - } - - @Override - public boolean dispatchTouchEvent(MotionEvent event) { - if (mPreviousCallback != null) - return mPreviousCallback.dispatchTouchEvent(event); - return false; - } - - @Override - public boolean dispatchTrackballEvent(MotionEvent event) { - if (mPreviousCallback != null) - return mPreviousCallback.dispatchTrackballEvent(event); - return false; - } - - @Override - public void onActionModeFinished(ActionMode mode) { - if (mPreviousCallback != null) - mPreviousCallback.onActionModeFinished(mode); - } - - @Override - public void onActionModeStarted(ActionMode mode) { - if (mPreviousCallback != null) - mPreviousCallback.onActionModeStarted(mode); - } - - @Override - public void onAttachedToWindow() { - if (mPreviousCallback != null) - mPreviousCallback.onAttachedToWindow(); - } - - @Override - public void onContentChanged() { - if (mPreviousCallback != null) - mPreviousCallback.onContentChanged(); - } - - @Override - public boolean onCreatePanelMenu(int featureId, Menu menu) { - if (mPreviousCallback != null) - return mPreviousCallback.onCreatePanelMenu(featureId, menu); - return false; - } - - @Override - public View onCreatePanelView(int featureId) { - if (mPreviousCallback != null) - return mPreviousCallback.onCreatePanelView(featureId); - return null; - } - - @Override - public void onDetachedFromWindow() { - if (mPreviousCallback != null) - mPreviousCallback.onDetachedFromWindow(); - } - - @Override - public boolean onMenuItemSelected(int featureId, MenuItem item) { - if (mPreviousCallback != null) - return mPreviousCallback.onMenuItemSelected(featureId, item); - return false; - } - - @Override - public boolean onMenuOpened(int featureId, Menu menu) { - if (mPreviousCallback != null) - return mPreviousCallback.onMenuOpened(featureId, menu); - return false; - } - - @Override - public void onPanelClosed(int featureId, Menu menu) { - if (mPreviousCallback != null) - mPreviousCallback.onPanelClosed(featureId, menu); - } - - @Override - public boolean onPreparePanel(int featureId, View view, Menu menu) { - if (mPreviousCallback != null) - return mPreviousCallback.onPreparePanel(featureId, view, menu); - return false; - } - - @Override - public boolean onSearchRequested() { - if (mPreviousCallback != null) - return mPreviousCallback.onSearchRequested(); - return false; - } - - @Override - public void onWindowAttributesChanged(LayoutParams attrs) { - if (mPreviousCallback != null) - mPreviousCallback.onWindowAttributesChanged(attrs); - } - - @Override - public void onWindowFocusChanged(boolean hasFocus) { - if (mPreviousCallback != null) - mPreviousCallback.onWindowFocusChanged(hasFocus); - } - - @Override - public ActionMode onWindowStartingActionMode(Callback callback) { - if (mPreviousCallback != null) - return mPreviousCallback.onWindowStartingActionMode(callback); - return null; - } -} |