Merge "Move non-distinct multitouch support to a separate class"
This commit is contained in:
commit
b7f6260195
3 changed files with 112 additions and 67 deletions
|
@ -53,6 +53,7 @@ import com.android.inputmethod.keyboard.internal.GestureFloatingPreviewText;
|
||||||
import com.android.inputmethod.keyboard.internal.GestureTrailsPreview;
|
import com.android.inputmethod.keyboard.internal.GestureTrailsPreview;
|
||||||
import com.android.inputmethod.keyboard.internal.KeyDrawParams;
|
import com.android.inputmethod.keyboard.internal.KeyDrawParams;
|
||||||
import com.android.inputmethod.keyboard.internal.KeyPreviewDrawParams;
|
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.PreviewPlacerView;
|
||||||
import com.android.inputmethod.keyboard.internal.SlidingKeyInputPreview;
|
import com.android.inputmethod.keyboard.internal.SlidingKeyInputPreview;
|
||||||
import com.android.inputmethod.latin.Constants;
|
import com.android.inputmethod.latin.Constants;
|
||||||
|
@ -179,9 +180,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
|
||||||
private int mGestureFloatingPreviewTextLingerTimeout;
|
private int mGestureFloatingPreviewTextLingerTimeout;
|
||||||
|
|
||||||
private KeyDetector mKeyDetector;
|
private KeyDetector mKeyDetector;
|
||||||
private final boolean mHasDistinctMultitouch;
|
private final NonDistinctMultitouchHelper mNonDistinctMultitouchHelper;
|
||||||
private int mOldPointerCount = 1;
|
|
||||||
private Key mOldKey;
|
|
||||||
|
|
||||||
private final KeyTimerHandler mKeyTimerHandler;
|
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) {
|
public MainKeyboardView(final Context context, final AttributeSet attrs, final int defStyle) {
|
||||||
super(context, attrs, defStyle);
|
super(context, attrs, defStyle);
|
||||||
|
|
||||||
|
PointerTracker.init(getResources());
|
||||||
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
final boolean forceNonDistinctMultitouch = prefs.getBoolean(
|
final boolean forceNonDistinctMultitouch = prefs.getBoolean(
|
||||||
DebugSettings.PREF_FORCE_NON_DISTINCT_MULTITOUCH, false);
|
DebugSettings.PREF_FORCE_NON_DISTINCT_MULTITOUCH, false);
|
||||||
final boolean hasDistinctMultitouch = context.getPackageManager()
|
final boolean hasDistinctMultitouch = context.getPackageManager()
|
||||||
.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT);
|
.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT)
|
||||||
mHasDistinctMultitouch = hasDistinctMultitouch && !forceNonDistinctMultitouch;
|
&& !forceNonDistinctMultitouch;
|
||||||
PointerTracker.init(getResources());
|
mNonDistinctMultitouchHelper = hasDistinctMultitouch ? null
|
||||||
|
: new NonDistinctMultitouchHelper();
|
||||||
|
|
||||||
mPreviewPlacerView = new PreviewPlacerView(context, attrs);
|
mPreviewPlacerView = new PreviewPlacerView(context, attrs);
|
||||||
|
|
||||||
final TypedArray mainKeyboardViewAttr = context.obtainStyledAttributes(
|
final TypedArray mainKeyboardViewAttr = context.obtainStyledAttributes(
|
||||||
|
@ -1032,25 +1034,21 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
|
||||||
if (getKeyboard() == null) {
|
if (getKeyboard() == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// TODO: Add multi-touch to single-touch event converter for non-distinct multi-touch
|
if (mNonDistinctMultitouchHelper != null) {
|
||||||
// device.
|
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);
|
return processMotionEvent(me);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean processMotionEvent(final MotionEvent me) {
|
public boolean processMotionEvent(final MotionEvent me) {
|
||||||
final boolean nonDistinctMultitouch = !mHasDistinctMultitouch;
|
|
||||||
final int action = me.getActionMasked();
|
final int action = me.getActionMasked();
|
||||||
final int pointerCount = me.getPointerCount();
|
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 long eventTime = me.getEventTime();
|
||||||
final int index = me.getActionIndex();
|
final int index = me.getActionIndex();
|
||||||
final int id = me.getPointerId(index);
|
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);
|
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) {
|
if (action == MotionEvent.ACTION_MOVE) {
|
||||||
for (int i = 0; i < pointerCount; i++) {
|
for (int i = 0; i < pointerCount; i++) {
|
||||||
final int pointerId = me.getPointerId(i);
|
final int pointerId = me.getPointerId(i);
|
||||||
|
|
|
@ -478,6 +478,10 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
|
||||||
mPointerId = id;
|
mPointerId = id;
|
||||||
mGestureStrokeWithPreviewPoints = new GestureStrokeWithPreviewPoints(
|
mGestureStrokeWithPreviewPoints = new GestureStrokeWithPreviewPoints(
|
||||||
id, sGestureStrokeParams, sGesturePreviewParams);
|
id, sGestureStrokeParams, sGesturePreviewParams);
|
||||||
|
setKeyEventHandler(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setKeyEventHandler(final KeyEventHandler handler) {
|
||||||
setKeyDetectorInner(handler.getKeyDetector());
|
setKeyDetectorInner(handler.getKeyDetector());
|
||||||
mListener = handler.getKeyboardActionListener();
|
mListener = handler.getKeyboardActionListener();
|
||||||
mDrawingProxy = handler.getDrawingProxy();
|
mDrawingProxy = handler.getDrawingProxy();
|
||||||
|
@ -891,10 +895,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
|
||||||
if (DEBUG_EVENT) {
|
if (DEBUG_EVENT) {
|
||||||
printTouchEvent("onDownEvent:", x, y, eventTime);
|
printTouchEvent("onDownEvent:", x, y, eventTime);
|
||||||
}
|
}
|
||||||
mDrawingProxy = handler.getDrawingProxy();
|
setKeyEventHandler(handler);
|
||||||
mTimerProxy = handler.getTimerProxy();
|
|
||||||
setKeyboardActionListener(handler.getKeyboardActionListener());
|
|
||||||
setKeyDetectorInner(handler.getKeyDetector());
|
|
||||||
// Naive up-to-down noise filter.
|
// Naive up-to-down noise filter.
|
||||||
final long deltaT = eventTime - mUpTime;
|
final long deltaT = eventTime - mUpTime;
|
||||||
if (deltaT < sParams.mTouchNoiseThresholdTime) {
|
if (deltaT < sParams.mTouchNoiseThresholdTime) {
|
||||||
|
|
|
@ -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 + ")");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue