am dfbc5080: Refactor SwipeTracker class
Merge commit 'dfbc5080a1b639fda448098ab080d632639591dc' into gingerbread-plus-aosp * commit 'dfbc5080a1b639fda448098ab080d632639591dc': Refactor SwipeTracker classmain
commit
6056fee826
|
@ -1286,7 +1286,6 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener
|
||||||
}
|
}
|
||||||
|
|
||||||
// Track the last few movements to look for spurious swipes.
|
// Track the last few movements to look for spurious swipes.
|
||||||
if (action == MotionEvent.ACTION_DOWN) mSwipeTracker.clear();
|
|
||||||
mSwipeTracker.addMovement(me);
|
mSwipeTracker.addMovement(me);
|
||||||
|
|
||||||
// Ignore all motion events until a DOWN.
|
// Ignore all motion events until a DOWN.
|
||||||
|
|
|
@ -16,70 +16,40 @@
|
||||||
|
|
||||||
package com.android.inputmethod.latin;
|
package com.android.inputmethod.latin;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
|
||||||
class SwipeTracker {
|
class SwipeTracker {
|
||||||
|
private static final int NUM_PAST = 4;
|
||||||
|
private static final int LONGEST_PAST_TIME = 200;
|
||||||
|
|
||||||
static final int NUM_PAST = 4;
|
final EventRingBuffer mBuffer = new EventRingBuffer(NUM_PAST);
|
||||||
static final int LONGEST_PAST_TIME = 200;
|
|
||||||
|
|
||||||
final float mPastX[] = new float[NUM_PAST];
|
private float mYVelocity;
|
||||||
final float mPastY[] = new float[NUM_PAST];
|
private float mXVelocity;
|
||||||
final long mPastTime[] = new long[NUM_PAST];
|
|
||||||
|
|
||||||
float mYVelocity;
|
|
||||||
float mXVelocity;
|
|
||||||
|
|
||||||
public void clear() {
|
|
||||||
mPastTime[0] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addMovement(MotionEvent ev) {
|
public void addMovement(MotionEvent ev) {
|
||||||
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
|
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
|
||||||
clear();
|
mBuffer.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
long time = ev.getEventTime();
|
long time = ev.getEventTime();
|
||||||
final int N = ev.getHistorySize();
|
final int count = ev.getHistorySize();
|
||||||
for (int i=0; i<N; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
addPoint(ev.getHistoricalX(i), ev.getHistoricalY(i),
|
addPoint(ev.getHistoricalX(i), ev.getHistoricalY(i), ev.getHistoricalEventTime(i));
|
||||||
ev.getHistoricalEventTime(i));
|
|
||||||
}
|
}
|
||||||
addPoint(ev.getX(), ev.getY(), time);
|
addPoint(ev.getX(), ev.getY(), time);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addPoint(float x, float y, long time) {
|
private void addPoint(float x, float y, long time) {
|
||||||
int drop = -1;
|
final EventRingBuffer buffer = mBuffer;
|
||||||
int i;
|
while (buffer.size() > 0) {
|
||||||
final long[] pastTime = mPastTime;
|
long lastT = buffer.getTime(0);
|
||||||
for (i=0; i<NUM_PAST; i++) {
|
if (lastT >= time - LONGEST_PAST_TIME)
|
||||||
if (pastTime[i] == 0) {
|
|
||||||
break;
|
break;
|
||||||
} else if (pastTime[i] < time-LONGEST_PAST_TIME) {
|
buffer.dropOldest();
|
||||||
drop = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i == NUM_PAST && drop < 0) {
|
|
||||||
drop = 0;
|
|
||||||
}
|
|
||||||
if (drop == i) drop--;
|
|
||||||
final float[] pastX = mPastX;
|
|
||||||
final float[] pastY = mPastY;
|
|
||||||
if (drop >= 0) {
|
|
||||||
final int start = drop+1;
|
|
||||||
final int count = NUM_PAST-drop-1;
|
|
||||||
System.arraycopy(pastX, start, pastX, 0, count);
|
|
||||||
System.arraycopy(pastY, start, pastY, 0, count);
|
|
||||||
System.arraycopy(pastTime, start, pastTime, 0, count);
|
|
||||||
i -= (drop+1);
|
|
||||||
}
|
|
||||||
pastX[i] = x;
|
|
||||||
pastY[i] = y;
|
|
||||||
pastTime[i] = time;
|
|
||||||
i++;
|
|
||||||
if (i < NUM_PAST) {
|
|
||||||
pastTime[i] = 0;
|
|
||||||
}
|
}
|
||||||
|
buffer.add(x, y, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void computeCurrentVelocity(int units) {
|
public void computeCurrentVelocity(int units) {
|
||||||
|
@ -87,32 +57,23 @@ class SwipeTracker {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void computeCurrentVelocity(int units, float maxVelocity) {
|
public void computeCurrentVelocity(int units, float maxVelocity) {
|
||||||
final float[] pastX = mPastX;
|
final EventRingBuffer buffer = mBuffer;
|
||||||
final float[] pastY = mPastY;
|
final float oldestX = buffer.getX(0);
|
||||||
final long[] pastTime = mPastTime;
|
final float oldestY = buffer.getY(0);
|
||||||
|
final long oldestTime = buffer.getTime(0);
|
||||||
|
|
||||||
final float oldestX = pastX[0];
|
|
||||||
final float oldestY = pastY[0];
|
|
||||||
final long oldestTime = pastTime[0];
|
|
||||||
float accumX = 0;
|
float accumX = 0;
|
||||||
float accumY = 0;
|
float accumY = 0;
|
||||||
int N=0;
|
final int count = buffer.size();
|
||||||
while (N < NUM_PAST) {
|
for (int pos = 1; pos < count; pos++) {
|
||||||
if (pastTime[N] == 0) {
|
final int dur = (int)(buffer.getTime(pos) - oldestTime);
|
||||||
break;
|
|
||||||
}
|
|
||||||
N++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i=1; i < N; i++) {
|
|
||||||
final int dur = (int)(pastTime[i] - oldestTime);
|
|
||||||
if (dur == 0) continue;
|
if (dur == 0) continue;
|
||||||
float dist = pastX[i] - oldestX;
|
float dist = buffer.getX(pos) - oldestX;
|
||||||
float vel = (dist / dur) * units; // pixels/frame.
|
float vel = (dist / dur) * units; // pixels/frame.
|
||||||
if (accumX == 0) accumX = vel;
|
if (accumX == 0) accumX = vel;
|
||||||
else accumX = (accumX + vel) * .5f;
|
else accumX = (accumX + vel) * .5f;
|
||||||
|
|
||||||
dist = pastY[i] - oldestY;
|
dist = buffer.getY(pos) - oldestY;
|
||||||
vel = (dist / dur) * units; // pixels/frame.
|
vel = (dist / dur) * units; // pixels/frame.
|
||||||
if (accumY == 0) accumY = vel;
|
if (accumY == 0) accumY = vel;
|
||||||
else accumY = (accumY + vel) * .5f;
|
else accumY = (accumY + vel) * .5f;
|
||||||
|
@ -130,4 +91,68 @@ class SwipeTracker {
|
||||||
public float getYVelocity() {
|
public float getYVelocity() {
|
||||||
return mYVelocity;
|
return mYVelocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class EventRingBuffer {
|
||||||
|
private final int bufSize;
|
||||||
|
private final float xBuf[];
|
||||||
|
private final float yBuf[];
|
||||||
|
private final long timeBuf[];
|
||||||
|
private int top; // points new event
|
||||||
|
private int end; // points oldest event
|
||||||
|
private int count; // the number of valid data
|
||||||
|
|
||||||
|
public EventRingBuffer(int max) {
|
||||||
|
this.bufSize = max;
|
||||||
|
xBuf = new float[max];
|
||||||
|
yBuf = new float[max];
|
||||||
|
timeBuf = new long[max];
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
top = end = count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Position 0 points oldest event
|
||||||
|
private int index(int pos) {
|
||||||
|
return (end + pos) % bufSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int advance(int index) {
|
||||||
|
return (index + 1) % bufSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(float x, float y, long time) {
|
||||||
|
xBuf[top] = x;
|
||||||
|
yBuf[top] = y;
|
||||||
|
timeBuf[top] = time;
|
||||||
|
top = advance(top);
|
||||||
|
if (count < bufSize) {
|
||||||
|
count++;
|
||||||
|
} else {
|
||||||
|
end = advance(end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getX(int pos) {
|
||||||
|
return xBuf[index(pos)];
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getY(int pos) {
|
||||||
|
return yBuf[index(pos)];
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTime(int pos) {
|
||||||
|
return timeBuf[index(pos)];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dropOldest() {
|
||||||
|
count--;
|
||||||
|
end = advance(end);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,154 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010 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.latin;
|
||||||
|
|
||||||
|
import com.android.inputmethod.latin.SwipeTracker.EventRingBuffer;
|
||||||
|
|
||||||
|
import android.test.AndroidTestCase;
|
||||||
|
|
||||||
|
public class EventRingBufferTests extends AndroidTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void tearDown() throws Exception {
|
||||||
|
super.tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float X_BASE = 1000f;
|
||||||
|
|
||||||
|
private static float Y_BASE = 2000f;
|
||||||
|
|
||||||
|
private static long TIME_BASE = 3000l;
|
||||||
|
|
||||||
|
private static float x(int id) {
|
||||||
|
return X_BASE + id;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float y(int id) {
|
||||||
|
return Y_BASE + id;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long time(int id) {
|
||||||
|
return TIME_BASE + id;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addEvent(EventRingBuffer buf, int id) {
|
||||||
|
buf.add(x(id), y(id), time(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void assertEventSize(EventRingBuffer buf, int size) {
|
||||||
|
assertEquals(size, buf.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void assertEvent(EventRingBuffer buf, int pos, int id) {
|
||||||
|
assertEquals(x(id), buf.getX(pos), 0f);
|
||||||
|
assertEquals(y(id), buf.getY(pos), 0f);
|
||||||
|
assertEquals(time(id), buf.getTime(pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testClearBuffer() {
|
||||||
|
EventRingBuffer buf = new EventRingBuffer(4);
|
||||||
|
assertEventSize(buf, 0);
|
||||||
|
|
||||||
|
addEvent(buf, 0);
|
||||||
|
addEvent(buf, 1);
|
||||||
|
addEvent(buf, 2);
|
||||||
|
addEvent(buf, 3);
|
||||||
|
addEvent(buf, 4);
|
||||||
|
assertEventSize(buf, 4);
|
||||||
|
|
||||||
|
buf.clear();
|
||||||
|
assertEventSize(buf, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRingBuffer() {
|
||||||
|
EventRingBuffer buf = new EventRingBuffer(4);
|
||||||
|
assertEventSize(buf, 0); // [0]
|
||||||
|
|
||||||
|
addEvent(buf, 0);
|
||||||
|
assertEventSize(buf, 1); // [1] 0
|
||||||
|
assertEvent(buf, 0, 0);
|
||||||
|
|
||||||
|
addEvent(buf, 1);
|
||||||
|
addEvent(buf, 2);
|
||||||
|
assertEventSize(buf, 3); // [3] 2 1 0
|
||||||
|
assertEvent(buf, 0, 0);
|
||||||
|
assertEvent(buf, 1, 1);
|
||||||
|
assertEvent(buf, 2, 2);
|
||||||
|
|
||||||
|
addEvent(buf, 3);
|
||||||
|
assertEventSize(buf, 4); // [4] 3 2 1 0
|
||||||
|
assertEvent(buf, 0, 0);
|
||||||
|
assertEvent(buf, 1, 1);
|
||||||
|
assertEvent(buf, 2, 2);
|
||||||
|
assertEvent(buf, 3, 3);
|
||||||
|
|
||||||
|
addEvent(buf, 4);
|
||||||
|
addEvent(buf, 5);
|
||||||
|
assertEventSize(buf, 4); // [4] 5 4|3 2(1 0)
|
||||||
|
assertEvent(buf, 0, 2);
|
||||||
|
assertEvent(buf, 1, 3);
|
||||||
|
assertEvent(buf, 2, 4);
|
||||||
|
assertEvent(buf, 3, 5);
|
||||||
|
|
||||||
|
addEvent(buf, 6);
|
||||||
|
addEvent(buf, 7);
|
||||||
|
addEvent(buf, 8);
|
||||||
|
assertEventSize(buf, 4); // [4] 8 7 6 5|(4 3 2)1|0
|
||||||
|
assertEvent(buf, 0, 5);
|
||||||
|
assertEvent(buf, 1, 6);
|
||||||
|
assertEvent(buf, 2, 7);
|
||||||
|
assertEvent(buf, 3, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDropOldest() {
|
||||||
|
EventRingBuffer buf = new EventRingBuffer(4);
|
||||||
|
|
||||||
|
addEvent(buf, 0);
|
||||||
|
assertEventSize(buf, 1); // [1] 0
|
||||||
|
assertEvent(buf, 0, 0);
|
||||||
|
|
||||||
|
buf.dropOldest();
|
||||||
|
assertEventSize(buf, 0); // [0] (0)
|
||||||
|
|
||||||
|
addEvent(buf, 1);
|
||||||
|
addEvent(buf, 2);
|
||||||
|
addEvent(buf, 3);
|
||||||
|
addEvent(buf, 4);
|
||||||
|
assertEventSize(buf, 4); // [4] 4|3 2 1(0)
|
||||||
|
assertEvent(buf, 0, 1);
|
||||||
|
|
||||||
|
buf.dropOldest();
|
||||||
|
assertEventSize(buf, 3); // [3] 4|3 2(1)0
|
||||||
|
assertEvent(buf, 0, 2);
|
||||||
|
|
||||||
|
buf.dropOldest();
|
||||||
|
assertEventSize(buf, 2); // [2] 4|3(2)10
|
||||||
|
assertEvent(buf, 0, 3);
|
||||||
|
|
||||||
|
buf.dropOldest();
|
||||||
|
assertEventSize(buf, 1); // [1] 4|(3)210
|
||||||
|
assertEvent(buf, 0, 4);
|
||||||
|
|
||||||
|
buf.dropOldest();
|
||||||
|
assertEventSize(buf, 0); // [0] (4)|3210
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue