Provide gesture data even if the finger stays still

Bug: 7595187
Change-Id: I6f85124815f18706b2b2b5b5da2783dffd246e8c
main
Tadashi G. Takaoka 2012-11-22 11:04:41 +09:00
parent a15ee70d43
commit 72fd0968e5
6 changed files with 72 additions and 15 deletions

View File

@ -145,6 +145,7 @@
<attr name="gestureSamplingMinimumDistance" format="fraction" /> <attr name="gestureSamplingMinimumDistance" format="fraction" />
<!-- Parameters for gesture recognition (msec) and (keyWidth%/sec) --> <!-- Parameters for gesture recognition (msec) and (keyWidth%/sec) -->
<attr name="gestureRecognitionMinimumTime" format="integer" /> <attr name="gestureRecognitionMinimumTime" format="integer" />
<attr name="gestureRecognitionUpdateTime" format="integer" />
<attr name="gestureRecognitionSpeedThreshold" format="fraction" /> <attr name="gestureRecognitionSpeedThreshold" format="fraction" />
<!-- Suppress showing key preview duration after batch input in millisecond --> <!-- Suppress showing key preview duration after batch input in millisecond -->
<attr name="suppressKeyPreviewAfterBatchInputDuration" format="integer" /> <attr name="suppressKeyPreviewAfterBatchInputDuration" format="integer" />

View File

@ -86,6 +86,7 @@
<fraction name="config_gesture_sampling_minimum_distance">16.6666%</fraction> <fraction name="config_gesture_sampling_minimum_distance">16.6666%</fraction>
<!-- Parameters for gesture recognition (msec) and (keyWidth%/sec) --> <!-- Parameters for gesture recognition (msec) and (keyWidth%/sec) -->
<integer name="config_gesture_recognition_minimum_time">100</integer> <integer name="config_gesture_recognition_minimum_time">100</integer>
<integer name="config_gesture_recognition_update_time">300</integer>
<fraction name="config_gesture_recognition_speed_threshold">550%</fraction> <fraction name="config_gesture_recognition_speed_threshold">550%</fraction>
<!-- Suppress showing key preview duration after batch input in millisecond --> <!-- Suppress showing key preview duration after batch input in millisecond -->
<integer name="config_suppress_key_preview_after_batch_input_duration">1000</integer> <integer name="config_suppress_key_preview_after_batch_input_duration">1000</integer>

View File

@ -104,6 +104,7 @@
<item name="gestureDynamicDistanceThresholdTo">@fraction/config_gesture_dynamic_distance_threshold_to</item> <item name="gestureDynamicDistanceThresholdTo">@fraction/config_gesture_dynamic_distance_threshold_to</item>
<item name="gestureSamplingMinimumDistance">@fraction/config_gesture_sampling_minimum_distance</item> <item name="gestureSamplingMinimumDistance">@fraction/config_gesture_sampling_minimum_distance</item>
<item name="gestureRecognitionMinimumTime">@integer/config_gesture_recognition_minimum_time</item> <item name="gestureRecognitionMinimumTime">@integer/config_gesture_recognition_minimum_time</item>
<item name="gestureRecognitionUpdateTime">@integer/config_gesture_recognition_update_time</item>
<item name="gestureRecognitionSpeedThreshold">@fraction/config_gesture_recognition_speed_threshold</item> <item name="gestureRecognitionSpeedThreshold">@fraction/config_gesture_recognition_speed_threshold</item>
<item name="suppressKeyPreviewAfterBatchInputDuration">@integer/config_suppress_key_preview_after_batch_input_duration</item> <item name="suppressKeyPreviewAfterBatchInputDuration">@integer/config_suppress_key_preview_after_batch_input_duration</item>
</style> </style>

View File

@ -29,6 +29,7 @@ import android.graphics.Paint.Align;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Message; import android.os.Message;
import android.os.SystemClock;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log; import android.util.Log;
@ -156,12 +157,14 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
private static final int MSG_REPEAT_KEY = 1; private static final int MSG_REPEAT_KEY = 1;
private static final int MSG_LONGPRESS_KEY = 2; private static final int MSG_LONGPRESS_KEY = 2;
private static final int MSG_DOUBLE_TAP = 3; private static final int MSG_DOUBLE_TAP = 3;
private static final int MSG_UPDATE_BATCH_INPUT = 4;
private final int mKeyRepeatStartTimeout; private final int mKeyRepeatStartTimeout;
private final int mKeyRepeatInterval; private final int mKeyRepeatInterval;
private final int mLongPressKeyTimeout; private final int mLongPressKeyTimeout;
private final int mLongPressShiftKeyTimeout; private final int mLongPressShiftKeyTimeout;
private final int mIgnoreAltCodeKeyTimeout; private final int mIgnoreAltCodeKeyTimeout;
private final int mGestureRecognitionUpdateTime;
public KeyTimerHandler(final MainKeyboardView outerInstance, public KeyTimerHandler(final MainKeyboardView outerInstance,
final TypedArray mainKeyboardViewAttr) { final TypedArray mainKeyboardViewAttr) {
@ -177,6 +180,8 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
R.styleable.MainKeyboardView_longPressShiftKeyTimeout, 0); R.styleable.MainKeyboardView_longPressShiftKeyTimeout, 0);
mIgnoreAltCodeKeyTimeout = mainKeyboardViewAttr.getInt( mIgnoreAltCodeKeyTimeout = mainKeyboardViewAttr.getInt(
R.styleable.MainKeyboardView_ignoreAltCodeKeyTimeout, 0); R.styleable.MainKeyboardView_ignoreAltCodeKeyTimeout, 0);
mGestureRecognitionUpdateTime = mainKeyboardViewAttr.getInt(
R.styleable.MainKeyboardView_gestureRecognitionUpdateTime, 0);
} }
@Override @Override
@ -201,6 +206,10 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
KeyboardSwitcher.getInstance().onLongPressTimeout(msg.arg1); KeyboardSwitcher.getInstance().onLongPressTimeout(msg.arg1);
} }
break; break;
case MSG_UPDATE_BATCH_INPUT:
tracker.updateBatchInputByTimer(SystemClock.uptimeMillis());
startUpdateBatchInputTimer(tracker);
break;
} }
} }
@ -349,8 +358,24 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
cancelLongPressTimer(); cancelLongPressTimer();
} }
@Override
public void startUpdateBatchInputTimer(final PointerTracker tracker) {
if (mGestureRecognitionUpdateTime <= 0) {
return;
}
removeMessages(MSG_UPDATE_BATCH_INPUT, tracker);
sendMessageDelayed(obtainMessage(MSG_UPDATE_BATCH_INPUT, tracker),
mGestureRecognitionUpdateTime);
}
@Override
public void cancelAllUpdateBatchInputTimer() {
removeMessages(MSG_UPDATE_BATCH_INPUT);
}
public void cancelAllMessages() { public void cancelAllMessages() {
cancelKeyTimers(); cancelKeyTimers();
cancelAllUpdateBatchInputTimer();
} }
} }

View File

@ -94,6 +94,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
public void cancelDoubleTapTimer(); public void cancelDoubleTapTimer();
public boolean isInDoubleTapTimeout(); public boolean isInDoubleTapTimeout();
public void cancelKeyTimers(); public void cancelKeyTimers();
public void startUpdateBatchInputTimer(PointerTracker tracker);
public void cancelAllUpdateBatchInputTimer();
public static class Adapter implements TimerProxy { public static class Adapter implements TimerProxy {
@Override @Override
@ -116,6 +118,10 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
public boolean isInDoubleTapTimeout() { return false; } public boolean isInDoubleTapTimeout() { return false; }
@Override @Override
public void cancelKeyTimers() {} public void cancelKeyTimers() {}
@Override
public void startUpdateBatchInputTimer(PointerTracker tracker) {}
@Override
public void cancelAllUpdateBatchInputTimer() {}
} }
} }
@ -705,27 +711,38 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
mDrawingProxy.showGesturePreviewTrail(this, isOldestTrackerInQueue(this)); mDrawingProxy.showGesturePreviewTrail(this, isOldestTrackerInQueue(this));
} }
public void updateBatchInputByTimer(final long eventTime) {
final int gestureTime = (int)(eventTime - sGestureFirstDownTime);
mGestureStrokeWithPreviewPoints.duplicateLastPointWith(gestureTime);
updateBatchInput(eventTime);
}
private void mayUpdateBatchInput(final long eventTime, final Key key) { private void mayUpdateBatchInput(final long eventTime, final Key key) {
if (key != null) { if (key != null) {
synchronized (sAggregratedPointers) { updateBatchInput(eventTime);
final GestureStroke stroke = mGestureStrokeWithPreviewPoints;
stroke.appendIncrementalBatchPoints(sAggregratedPointers);
final int size = sAggregratedPointers.getPointerSize();
if (size > sLastRecognitionPointSize
&& stroke.hasRecognitionTimePast(eventTime, sLastRecognitionTime)) {
sLastRecognitionPointSize = size;
sLastRecognitionTime = eventTime;
if (DEBUG_LISTENER) {
Log.d(TAG, String.format("[%d] onUpdateBatchInput: batchPoints=%d",
mPointerId, size));
}
mListener.onUpdateBatchInput(sAggregratedPointers);
}
}
} }
mDrawingProxy.showGesturePreviewTrail(this, isOldestTrackerInQueue(this)); mDrawingProxy.showGesturePreviewTrail(this, isOldestTrackerInQueue(this));
} }
private void updateBatchInput(final long eventTime) {
synchronized (sAggregratedPointers) {
final GestureStroke stroke = mGestureStrokeWithPreviewPoints;
stroke.appendIncrementalBatchPoints(sAggregratedPointers);
final int size = sAggregratedPointers.getPointerSize();
if (size > sLastRecognitionPointSize
&& stroke.hasRecognitionTimePast(eventTime, sLastRecognitionTime)) {
sLastRecognitionPointSize = size;
sLastRecognitionTime = eventTime;
if (DEBUG_LISTENER) {
Log.d(TAG, String.format("[%d] onUpdateBatchInput: batchPoints=%d", mPointerId,
size));
}
mTimerProxy.startUpdateBatchInputTimer(this);
mListener.onUpdateBatchInput(sAggregratedPointers);
}
}
}
private void mayEndBatchInput(final long eventTime) { private void mayEndBatchInput(final long eventTime) {
synchronized (sAggregratedPointers) { synchronized (sAggregratedPointers) {
mGestureStrokeWithPreviewPoints.appendAllBatchPoints(sAggregratedPointers); mGestureStrokeWithPreviewPoints.appendAllBatchPoints(sAggregratedPointers);
@ -737,6 +754,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
Log.d(TAG, String.format("[%d] onEndBatchInput : batchPoints=%d", Log.d(TAG, String.format("[%d] onEndBatchInput : batchPoints=%d",
mPointerId, sAggregratedPointers.getPointerSize())); mPointerId, sAggregratedPointers.getPointerSize()));
} }
mTimerProxy.cancelAllUpdateBatchInputTimer();
mListener.onEndBatchInput(sAggregratedPointers); mListener.onEndBatchInput(sAggregratedPointers);
} }
} }

View File

@ -228,6 +228,17 @@ public class GestureStroke {
return isStartOfAGesture; return isStartOfAGesture;
} }
public void duplicateLastPointWith(final int time) {
final int lastIndex = mEventTimes.getLength() - 1;
if (lastIndex >= 0) {
final int x = mXCoordinates.get(lastIndex);
final int y = mYCoordinates.get(lastIndex);
// TODO: Have appendMajorPoint()
appendPoint(x, y, time);
updateIncrementalRecognitionSize(x, y, time);
}
}
protected void reset() { protected void reset() {
mIncrementalRecognitionSize = 0; mIncrementalRecognitionSize = 0;
mLastIncrementalBatchSize = 0; mLastIncrementalBatchSize = 0;