• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package js.kbars;
2 
3 import android.content.Context;
4 import android.graphics.Canvas;
5 import android.graphics.Paint;
6 import android.graphics.Paint.Cap;
7 import android.graphics.Paint.Style;
8 import android.graphics.Rect;
9 import android.graphics.Typeface;
10 import android.util.Log;
11 import android.view.MotionEvent;
12 import android.view.View;
13 import android.view.View.OnLayoutChangeListener;
14 import android.widget.FrameLayout;
15 import java.util.ArrayList;
16 import java.util.List;
17 import js.kbars.SystemGestureDebugger.DownPointerInfo;
18 import js.kbars.SystemGestureDebugger.ThresholdInfo;
19 
20 public class TouchTrackingLayout extends FrameLayout {
21     private static final boolean DEBUG_EVENTS = true;
22     private static final int MAX_INFO_LINES = 6;
23     private static final int MAX_POINTERS = 5;
24     private static final int MAX_POINTS = 5000;
25     private static final String TAG = Util.logTag(TouchTrackingLayout.class);
26     private boolean mDebug;
27     private final DownPointerInfo mDownPointerInfo = new DownPointerInfo();
28     private final SystemGestureDebugger mGestures;
29     private final Paint mInfoPaint = new Paint();
30     private final StringBuilder[] mInfoText = allocateInfoText();
31     private final int mInfoTextLineHeight;
32     private final int mInfoTextOffset;
33     private final int[] mScribbleCounts = new int[MAX_POINTERS];
34     private final Paint mScribblePaint = new Paint();
35     private final List<float[]> mScribblePoints = allocatePoints();
36     private final int mTextSize;
37     private final ThresholdInfo mThresholdInfo = new ThresholdInfo();
38     private final float[] mThresholdLines = new float[16];
39     private final Paint mThresholdPaint = new Paint();
40 
TouchTrackingLayout(Context context)41     public TouchTrackingLayout(Context context) {
42         super(context);
43         setWillNotDraw(false);
44         int densityDpi = Util.getDensityDpi(context);
45         this.mTextSize = (int) (((float) densityDpi) / 12.0f);
46         this.mInfoTextLineHeight = (int) (((float) densityDpi) / 11.0f);
47         this.mInfoTextOffset = (int) (((float) densityDpi) / 1.7f);
48         Log.d(TAG, "mTextSize=" + this.mTextSize + " mInfoTextLineHeight=" + this.mInfoTextLineHeight + " mInfoTextOffset=" + this.mInfoTextOffset);
49         this.mScribblePaint.setColor(-13388315);
50         this.mScribblePaint.setStrokeWidth((float) this.mTextSize);
51         this.mScribblePaint.setStrokeCap(Cap.ROUND);
52         this.mScribblePaint.setStyle(Style.STROKE);
53         this.mGestures = new SystemGestureDebugger(context, new SystemGestureDebugger.Callbacks() {
54             public void onSwipeFromTop() {
55                 Log.d(TouchTrackingLayout.TAG, "GestureCallbacks.onSwipeFromTop");
56             }
57 
58             public void onSwipeFromRight() {
59                 Log.d(TouchTrackingLayout.TAG, "GestureCallbacks.onSwipeFromRight");
60             }
61 
62             public void onSwipeFromBottom() {
63                 Log.d(TouchTrackingLayout.TAG, "GestureCallbacks.onSwipeFromBottom");
64             }
65 
66             public void onDebug() {
67                 Log.d(TouchTrackingLayout.TAG, "GestureCallbacks.onDebug");
68             }
69         });
70         this.mGestures.getThresholdInfo(this.mThresholdInfo);
71         this.mInfoPaint.setTypeface(Typeface.MONOSPACE);
72         this.mInfoPaint.setTextSize((float) this.mTextSize);
73         this.mInfoPaint.setStyle(Style.STROKE);
74         this.mInfoPaint.setColor(-13388315);
75         this.mThresholdPaint.setColor(-13388315);
76         this.mThresholdPaint.setStrokeWidth(1.0f);
77         this.mThresholdPaint.setStyle(Style.STROKE);
78         addOnLayoutChangeListener(new OnLayoutChangeListener() {
79             public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
80                 TouchTrackingLayout.this.mGestures.screenWidth = right - left;
81                 TouchTrackingLayout.this.mGestures.screenHeight = bottom - top;
82                 TouchTrackingLayout.this.horLine(0, TouchTrackingLayout.this.mThresholdInfo.start);
83                 TouchTrackingLayout.this.horLine(1, TouchTrackingLayout.this.mGestures.screenHeight - TouchTrackingLayout.this.mThresholdInfo.start);
84                 TouchTrackingLayout.this.verLine(2, TouchTrackingLayout.this.mThresholdInfo.start);
85                 TouchTrackingLayout.this.verLine(3, TouchTrackingLayout.this.mGestures.screenWidth - TouchTrackingLayout.this.mThresholdInfo.start);
86             }
87         });
88     }
89 
getDebug()90     public boolean getDebug() {
91         return this.mDebug;
92     }
93 
setDebug(boolean debug)94     public void setDebug(boolean debug) {
95         this.mDebug = debug;
96         invalidate();
97     }
98 
fitSystemWindows(Rect insets)99     protected boolean fitSystemWindows(Rect insets) {
100         Rect insetsBefore = new Rect(insets);
101         boolean rt = super.fitSystemWindows(insets);
102         Log.d(TAG, String.format("fitSystemWindows insetsBefore=%s insetsAfter=%s rt=%s", new Object[]{insetsBefore.toShortString(), insets.toShortString(), Boolean.valueOf(rt)}));
103         return rt;
104     }
105 
horLine(int lineNum, int y)106     private void horLine(int lineNum, int y) {
107         this.mThresholdLines[(lineNum * 4) + 0] = 0.0f;
108         float[] fArr = this.mThresholdLines;
109         int i = (lineNum * 4) + 1;
110         float f = (float) y;
111         this.mThresholdLines[(lineNum * 4) + 3] = f;
112         fArr[i] = f;
113         this.mThresholdLines[(lineNum * 4) + 2] = (float) this.mGestures.screenWidth;
114     }
115 
verLine(int lineNum, int x)116     private void verLine(int lineNum, int x) {
117         float[] fArr = this.mThresholdLines;
118         int i = (lineNum * 4) + 0;
119         float f = (float) x;
120         this.mThresholdLines[(lineNum * 4) + 2] = f;
121         fArr[i] = f;
122         this.mThresholdLines[(lineNum * 4) + 1] = 0.0f;
123         this.mThresholdLines[(lineNum * 4) + 3] = (float) this.mGestures.screenHeight;
124     }
125 
allocateInfoText()126     private static StringBuilder[] allocateInfoText() {
127         StringBuilder[] rt = new StringBuilder[MAX_INFO_LINES];
128         for (int i = 0; i < rt.length; i++) {
129             rt[i] = new StringBuilder();
130         }
131         return rt;
132     }
133 
onTouchEvent(MotionEvent ev)134     public boolean onTouchEvent(MotionEvent ev) {
135         super.onTouchEvent(ev);
136         this.mGestures.onPointerEvent(ev);
137         computeInfoText();
138         onMotionEvent(ev);
139         return true;
140     }
141 
onDraw(Canvas canvas)142     protected void onDraw(Canvas canvas) {
143         int i;
144         for (i = 0; i < this.mScribbleCounts.length; i++) {
145             int c = this.mScribbleCounts[i];
146             if (c > 0) {
147                 canvas.drawLines((float[]) this.mScribblePoints.get(i), 0, c - 2, this.mScribblePaint);
148             }
149         }
150         if (this.mDebug) {
151             int leftMargin = this.mThresholdInfo.start + (this.mTextSize / 4);
152             for (i = 0; i < this.mInfoText.length; i++) {
153                 StringBuilder sb = this.mInfoText[i];
154                 canvas.drawText(sb, 0, sb.length(), (float) leftMargin, (float) (this.mInfoTextOffset + (this.mInfoTextLineHeight * i)), this.mInfoPaint);
155             }
156             canvas.drawLines(this.mThresholdLines, this.mThresholdPaint);
157         }
158     }
159 
computeInfoText()160     private void computeInfoText() {
161         int dpc = this.mGestures.getDownPointers();
162         for (int i = 0; i < this.mInfoText.length; i++) {
163             StringBuilder sb = this.mInfoText[i];
164             sb.delete(0, sb.length());
165             if (i == 0) {
166                 sb.append("th  ");
167                 pad(sb, 9, this.mThresholdInfo.start);
168                 sb.append("   ");
169                 pad(sb, 9, this.mThresholdInfo.distance);
170                 sb.append(' ');
171                 pad(sb, MAX_POINTERS, (int) this.mThresholdInfo.elapsed);
172                 sb.append("ms");
173             } else if (i - 1 < dpc) {
174                 this.mGestures.getDownPointerInfo(i - 1, this.mDownPointerInfo);
175                 sb.append('p');
176                 sb.append(this.mDownPointerInfo.downPointerId);
177                 sb.append(' ');
178                 sb.append('(');
179                 pad(sb, 4, (int) this.mDownPointerInfo.downX);
180                 sb.append(',');
181                 pad(sb, 4, (int) this.mDownPointerInfo.downY);
182                 sb.append(')');
183                 sb.append(' ');
184                 sb.append('(');
185                 pad(sb, 4, (int) (this.mDownPointerInfo.currentX - this.mDownPointerInfo.downX));
186                 sb.append(',');
187                 pad(sb, 4, (int) (this.mDownPointerInfo.currentY - this.mDownPointerInfo.downY));
188                 sb.append(')');
189                 sb.append(' ');
190                 pad(sb, 4, (int) this.mDownPointerInfo.elapsedThreshold);
191                 sb.append("ms");
192             }
193         }
194     }
195 
pad(StringBuilder sb, int len, int num)196     private static void pad(StringBuilder sb, int len, int num) {
197         int n = num;
198         if (num < 0) {
199             n = Math.abs(num);
200             len--;
201         }
202         int nl = n > 0 ? ((int) Math.log10((double) n)) + 1 : 1;
203         while (true) {
204             int nl2 = nl + 1;
205             if (nl >= len) {
206                 break;
207             }
208             sb.append(' ');
209             nl = nl2;
210         }
211         if (num < 0) {
212             sb.append('-');
213         }
214         sb.append(n);
215     }
216 
allocatePoints()217     private static List<float[]> allocatePoints() {
218         List<float[]> points = new ArrayList();
219         for (int i = 0; i < MAX_POINTERS; i++) {
220             points.add(new float[MAX_POINTS]);
221         }
222         return points;
223     }
224 
onMotionEvent(MotionEvent ev)225     private void onMotionEvent(MotionEvent ev) {
226         long evt;
227         int p;
228         Log.d(TAG, "EVENT " + ev);
229         if (ev.getActionMasked() == 0) {
230             clearScribbles();
231         }
232         int hs = ev.getHistorySize();
233         int ps = ev.getPointerCount();
234         for (int h = 0; h < hs; h++) {
235             evt = ev.getHistoricalEventTime(h);
236             for (p = 0; p < ps; p++) {
237                 int pid = ev.getPointerId(p);
238                 float hx = ev.getHistoricalX(p, h);
239                 float hy = ev.getHistoricalY(p, h);
240                 String str = TAG;
241                 Object[] objArr = new Object[MAX_POINTERS];
242                 objArr[0] = Long.valueOf(evt);
243                 objArr[1] = Integer.valueOf(p);
244                 objArr[2] = Integer.valueOf(pid);
245                 objArr[3] = Float.valueOf(hx);
246                 objArr[4] = Float.valueOf(hy);
247                 Log.d(str, String.format("h.evt=%s p=%s pid=%s x=%s y=%s", objArr));
248                 recordScribblePoint(pid, hx, hy);
249             }
250         }
251         evt = ev.getEventTime();
252         for (p = 0; p < ps; p++) {
253             int pid = ev.getPointerId(p);
254             float x = ev.getX(p);
255             float y = ev.getY(p);
256             String str = TAG;
257             Object[] objArr = new Object[MAX_POINTERS];
258             objArr[0] = Long.valueOf(evt);
259             objArr[1] = Integer.valueOf(p);
260             objArr[2] = Integer.valueOf(pid);
261             objArr[3] = Float.valueOf(x);
262             objArr[4] = Float.valueOf(y);
263             Log.d(str, String.format("c.evt=%s p=%s pid=%s x=%s y=%s", objArr));
264             recordScribblePoint(pid, x, y);
265         }
266         invalidate();
267     }
268 
clearScribbles()269     private void clearScribbles() {
270         for (int i = 0; i < this.mScribbleCounts.length; i++) {
271             this.mScribbleCounts[i] = 0;
272         }
273     }
274 
recordScribblePoint(int pid, float x, float y)275     private void recordScribblePoint(int pid, float x, float y) {
276         if (pid < MAX_POINTERS) {
277             float[] pts = (float[]) this.mScribblePoints.get(pid);
278             int oldCount = this.mScribbleCounts[pid];
279             if (oldCount + 4 >= MAX_POINTS) {
280                 return;
281             }
282             int[] iArr;
283             if (oldCount == 0) {
284                 pts[oldCount + 0] = x;
285                 pts[oldCount + 1] = y;
286                 iArr = this.mScribbleCounts;
287                 iArr[pid] = iArr[pid] + 2;
288                 return;
289             }
290             pts[oldCount + 0] = x;
291             pts[oldCount + 1] = y;
292             pts[oldCount + 2] = x;
293             pts[oldCount + 3] = y;
294             iArr = this.mScribbleCounts;
295             iArr[pid] = iArr[pid] + 4;
296         }
297     }
298 }
299