Merge "Move non-distinct multitouch support to a separate class"

This commit is contained in:
Tadashi G. Takaoka 2013-08-01 09:22:49 +00:00 committed by Android (Google) Code Review
commit b7f6260195
3 changed files with 112 additions and 67 deletions

View file

@ -53,6 +53,7 @@ import com.android.inputmethod.keyboard.internal.GestureFloatingPreviewText;
import com.android.inputmethod.keyboard.internal.GestureTrailsPreview;
import com.android.inputmethod.keyboard.internal.KeyDrawParams;
import com.android.inputmethod.keyboard.internal.KeyPreviewDrawParams;
import com.android.inputmethod.keyboard.internal.NonDistinctMultitouchHelper;
import com.android.inputmethod.keyboard.internal.PreviewPlacerView;
import com.android.inputmethod.keyboard.internal.SlidingKeyInputPreview;
import com.android.inputmethod.latin.Constants;
@ -179,9 +180,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
private int mGestureFloatingPreviewTextLingerTimeout;
private KeyDetector mKeyDetector;
private final boolean mHasDistinctMultitouch;
private int mOldPointerCount = 1;
private Key mOldKey;
private final NonDistinctMultitouchHelper mNonDistinctMultitouchHelper;
private final KeyTimerHandler mKeyTimerHandler;
@ -423,13 +422,16 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
public MainKeyboardView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
PointerTracker.init(getResources());
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
final boolean forceNonDistinctMultitouch = prefs.getBoolean(
DebugSettings.PREF_FORCE_NON_DISTINCT_MULTITOUCH, false);
final boolean hasDistinctMultitouch = context.getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT);
mHasDistinctMultitouch = hasDistinctMultitouch && !forceNonDistinctMultitouch;
PointerTracker.init(getResources());
.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT)
&& !forceNonDistinctMultitouch;
mNonDistinctMultitouchHelper = hasDistinctMultitouch ? null
: new NonDistinctMultitouchHelper();
mPreviewPlacerView = new PreviewPlacerView(context, attrs);
final TypedArray mainKeyboardViewAttr = context.obtainStyledAttributes(
@ -1032,25 +1034,21 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
if (getKeyboard() == null) {
return false;
}
// TODO: Add multi-touch to single-touch event converter for non-distinct multi-touch
// device.
if (mNonDistinctMultitouchHelper != null) {
if (me.getPointerCount() > 1 && mKeyTimerHandler.isInKeyRepeat()) {
// Key repeating timer will be canceled if 2 or more keys are in action.
mKeyTimerHandler.cancelKeyRepeatTimer();
}
// Non distinct multitouch screen support
mNonDistinctMultitouchHelper.processMotionEvent(me, this);
return true;
}
return processMotionEvent(me);
}
public boolean processMotionEvent(final MotionEvent me) {
final boolean nonDistinctMultitouch = !mHasDistinctMultitouch;
final int action = me.getActionMasked();
final int pointerCount = me.getPointerCount();
final int oldPointerCount = mOldPointerCount;
mOldPointerCount = pointerCount;
// TODO: cleanup this code into a multi-touch to single-touch event converter class?
// If the device does not have distinct multi-touch support panel, ignore all multi-touch
// events except a transition from/to single-touch.
if (nonDistinctMultitouch && pointerCount > 1 && oldPointerCount > 1) {
return true;
}
final long eventTime = me.getEventTime();
final int index = me.getActionIndex();
final int id = me.getPointerId(index);
@ -1068,50 +1066,6 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
me, action, eventTime, index, id, x, y);
}
if (mKeyTimerHandler.isInKeyRepeat()) {
final PointerTracker tracker = PointerTracker.getPointerTracker(id, this);
// Key repeating timer will be canceled if 2 or more keys are in action, and current
// event (UP or DOWN) is non-modifier key.
if (pointerCount > 1 && !tracker.isModifier()) {
mKeyTimerHandler.cancelKeyRepeatTimer();
}
// Up event will pass through.
}
// TODO: cleanup this code into a multi-touch to single-touch event converter class?
// Translate mutli-touch event to single-touch events on the device that has no distinct
// multi-touch panel.
if (nonDistinctMultitouch) {
// Use only main (id=0) pointer tracker.
final PointerTracker tracker = PointerTracker.getPointerTracker(0, this);
if (pointerCount == 1 && oldPointerCount == 2) {
// Multi-touch to single touch transition.
// Send a down event for the latest pointer if the key is different from the
// previous key.
final Key newKey = tracker.getKeyOn(x, y);
if (mOldKey != newKey) {
tracker.onDownEvent(x, y, eventTime, this);
if (action == MotionEvent.ACTION_UP) {
tracker.onUpEvent(x, y, eventTime);
}
}
} else if (pointerCount == 2 && oldPointerCount == 1) {
// Single-touch to multi-touch transition.
// Send an up event for the last pointer.
final int[] lastCoords = CoordinateUtils.newInstance();
mOldKey = tracker.getKeyOn(
CoordinateUtils.x(lastCoords), CoordinateUtils.y(lastCoords));
tracker.onUpEvent(
CoordinateUtils.x(lastCoords), CoordinateUtils.y(lastCoords), eventTime);
} else if (pointerCount == 1 && oldPointerCount == 1) {
tracker.processMotionEvent(action, x, y, eventTime, this);
} else {
Log.w(TAG, "Unknown touch panel behavior: pointer count is " + pointerCount
+ " (old " + oldPointerCount + ")");
}
return true;
}
if (action == MotionEvent.ACTION_MOVE) {
for (int i = 0; i < pointerCount; i++) {
final int pointerId = me.getPointerId(i);

View file

@ -478,6 +478,10 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
mPointerId = id;
mGestureStrokeWithPreviewPoints = new GestureStrokeWithPreviewPoints(
id, sGestureStrokeParams, sGesturePreviewParams);
setKeyEventHandler(handler);
}
private void setKeyEventHandler(final KeyEventHandler handler) {
setKeyDetectorInner(handler.getKeyDetector());
mListener = handler.getKeyboardActionListener();
mDrawingProxy = handler.getDrawingProxy();
@ -891,10 +895,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
if (DEBUG_EVENT) {
printTouchEvent("onDownEvent:", x, y, eventTime);
}
mDrawingProxy = handler.getDrawingProxy();
mTimerProxy = handler.getTimerProxy();
setKeyboardActionListener(handler.getKeyboardActionListener());
setKeyDetectorInner(handler.getKeyDetector());
setKeyEventHandler(handler);
// Naive up-to-down noise filter.
final long deltaT = eventTime - mUpTime;
if (deltaT < sParams.mTouchNoiseThresholdTime) {

View file

@ -0,0 +1,90 @@
/*
* Copyright (C) 2013 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.keyboard.internal;
import android.util.Log;
import android.view.MotionEvent;
import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.PointerTracker;
import com.android.inputmethod.keyboard.PointerTracker.KeyEventHandler;
import com.android.inputmethod.latin.utils.CoordinateUtils;
public final class NonDistinctMultitouchHelper {
private static final String TAG = NonDistinctMultitouchHelper.class.getSimpleName();
private int mOldPointerCount = 1;
private Key mOldKey;
public void processMotionEvent(final MotionEvent me, final KeyEventHandler keyEventHandler) {
final int pointerCount = me.getPointerCount();
final int oldPointerCount = mOldPointerCount;
mOldPointerCount = pointerCount;
// Ignore continuous multitouch events because we can't trust the coordinates in mulitouch
// events.
if (pointerCount > 1 && oldPointerCount > 1) {
return;
}
final int action = me.getActionMasked();
final int index = me.getActionIndex();
final long eventTime = me.getEventTime();
final int x = (int)me.getX(index);
final int y = (int)me.getY(index);
// Use only main (id=0) pointer tracker.
final PointerTracker mainTracker = PointerTracker.getPointerTracker(0, keyEventHandler);
// In single touch.
if (oldPointerCount == 1 && pointerCount == 1) {
mainTracker.processMotionEvent(action, x, y, eventTime, keyEventHandler);
return;
}
// Single-touch to multi-touch transition.
if (oldPointerCount == 1 && pointerCount == 2) {
// Send an up event for the last pointer, be cause we can't trust the corrdinates of
// this multitouch event.
final int[] lastCoords = CoordinateUtils.newInstance();
mainTracker.getLastCoordinates(lastCoords);
mOldKey = mainTracker.getKeyOn(
CoordinateUtils.x(lastCoords), CoordinateUtils.y(lastCoords));
// TODO: Stop calling PointerTracker.onUpEvent directly.
mainTracker.onUpEvent(
CoordinateUtils.x(lastCoords), CoordinateUtils.y(lastCoords), eventTime);
return;
}
// Multi-touch to single touch transition.
if (oldPointerCount == 2 && pointerCount == 1) {
// Send a down event for the latest pointer if the key is different from the
// previous key.
final Key newKey = mainTracker.getKeyOn(x, y);
if (mOldKey != newKey) {
// TODO: Stop calling PointerTracker.onDownEvent directly.
mainTracker.onDownEvent(x, y, eventTime, keyEventHandler);
if (action == MotionEvent.ACTION_UP) {
// TODO: Stop calling PointerTracker.onUpEvent directly.
mainTracker.onUpEvent(x, y, eventTime);
}
}
return;
}
Log.w(TAG, "Unknown touch panel behavior: pointer count is "
+ pointerCount + " (previously " + oldPointerCount + ")");
}
}