Wed, 31 Dec 2014 07:22:50 +0100
Correct previous dual key logic pending first delivery installment.
michael@0 | 1 | package org.mozilla.gecko.tests; |
michael@0 | 2 | |
michael@0 | 3 | import android.app.Instrumentation; |
michael@0 | 4 | import android.os.SystemClock; |
michael@0 | 5 | import android.util.FloatMath; |
michael@0 | 6 | import android.util.Log; |
michael@0 | 7 | import android.view.MotionEvent; |
michael@0 | 8 | |
michael@0 | 9 | class MotionEventHelper { |
michael@0 | 10 | private static final String LOGTAG = "RobocopMotionEventHelper"; |
michael@0 | 11 | |
michael@0 | 12 | private static final long DRAG_EVENTS_PER_SECOND = 20; // 20 move events per second when doing a drag |
michael@0 | 13 | |
michael@0 | 14 | private final Instrumentation mInstrumentation; |
michael@0 | 15 | private final int mSurfaceOffsetX; |
michael@0 | 16 | private final int mSurfaceOffsetY; |
michael@0 | 17 | |
michael@0 | 18 | public MotionEventHelper(Instrumentation inst, int surfaceOffsetX, int surfaceOffsetY) { |
michael@0 | 19 | mInstrumentation = inst; |
michael@0 | 20 | mSurfaceOffsetX = surfaceOffsetX; |
michael@0 | 21 | mSurfaceOffsetY = surfaceOffsetY; |
michael@0 | 22 | Log.i(LOGTAG, "Initialized using offset (" + mSurfaceOffsetX + "," + mSurfaceOffsetY + ")"); |
michael@0 | 23 | } |
michael@0 | 24 | |
michael@0 | 25 | public long down(float x, float y) { |
michael@0 | 26 | Log.d(LOGTAG, "Triggering down at (" + x + "," + y + ")"); |
michael@0 | 27 | long downTime = SystemClock.uptimeMillis(); |
michael@0 | 28 | MotionEvent event = MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_DOWN, mSurfaceOffsetX + x, mSurfaceOffsetY + y, 0); |
michael@0 | 29 | try { |
michael@0 | 30 | mInstrumentation.sendPointerSync(event); |
michael@0 | 31 | } finally { |
michael@0 | 32 | event.recycle(); |
michael@0 | 33 | event = null; |
michael@0 | 34 | } |
michael@0 | 35 | return downTime; |
michael@0 | 36 | } |
michael@0 | 37 | |
michael@0 | 38 | public long move(long downTime, float x, float y) { |
michael@0 | 39 | return move(downTime, SystemClock.uptimeMillis(), x, y); |
michael@0 | 40 | } |
michael@0 | 41 | |
michael@0 | 42 | public long move(long downTime, long moveTime, float x, float y) { |
michael@0 | 43 | Log.d(LOGTAG, "Triggering move to (" + x + "," + y + ")"); |
michael@0 | 44 | MotionEvent event = MotionEvent.obtain(downTime, moveTime, MotionEvent.ACTION_MOVE, mSurfaceOffsetX + x, mSurfaceOffsetY + y, 0); |
michael@0 | 45 | try { |
michael@0 | 46 | mInstrumentation.sendPointerSync(event); |
michael@0 | 47 | } finally { |
michael@0 | 48 | event.recycle(); |
michael@0 | 49 | event = null; |
michael@0 | 50 | } |
michael@0 | 51 | return downTime; |
michael@0 | 52 | } |
michael@0 | 53 | |
michael@0 | 54 | public long up(long downTime, float x, float y) { |
michael@0 | 55 | return up(downTime, SystemClock.uptimeMillis(), x, y); |
michael@0 | 56 | } |
michael@0 | 57 | |
michael@0 | 58 | public long up(long downTime, long upTime, float x, float y) { |
michael@0 | 59 | Log.d(LOGTAG, "Triggering up at (" + x + "," + y + ")"); |
michael@0 | 60 | MotionEvent event = MotionEvent.obtain(downTime, upTime, MotionEvent.ACTION_UP, mSurfaceOffsetX + x, mSurfaceOffsetY + y, 0); |
michael@0 | 61 | try { |
michael@0 | 62 | mInstrumentation.sendPointerSync(event); |
michael@0 | 63 | } finally { |
michael@0 | 64 | event.recycle(); |
michael@0 | 65 | event = null; |
michael@0 | 66 | } |
michael@0 | 67 | return -1L; |
michael@0 | 68 | } |
michael@0 | 69 | |
michael@0 | 70 | public Thread dragAsync(final float startX, final float startY, final float endX, final float endY, final long durationMillis) { |
michael@0 | 71 | Thread t = new Thread() { |
michael@0 | 72 | @Override |
michael@0 | 73 | public void run() { |
michael@0 | 74 | int numEvents = (int)(durationMillis * DRAG_EVENTS_PER_SECOND / 1000); |
michael@0 | 75 | float eventDx = (endX - startX) / numEvents; |
michael@0 | 76 | float eventDy = (endY - startY) / numEvents; |
michael@0 | 77 | long downTime = down(startX, startY); |
michael@0 | 78 | for (int i = 0; i < numEvents - 1; i++) { |
michael@0 | 79 | downTime = move(downTime, startX + (eventDx * i), startY + (eventDy * i)); |
michael@0 | 80 | try { |
michael@0 | 81 | Thread.sleep(1000L / DRAG_EVENTS_PER_SECOND); |
michael@0 | 82 | } catch (InterruptedException ie) { |
michael@0 | 83 | ie.printStackTrace(); |
michael@0 | 84 | } |
michael@0 | 85 | } |
michael@0 | 86 | // sleep a bit before sending the last move so that the calculated |
michael@0 | 87 | // fling velocity is low and we don't end up doing a fling afterwards. |
michael@0 | 88 | try { |
michael@0 | 89 | Thread.sleep(1000L); |
michael@0 | 90 | } catch (InterruptedException ie) { |
michael@0 | 91 | ie.printStackTrace(); |
michael@0 | 92 | } |
michael@0 | 93 | // do the last one using endX/endY directly to avoid rounding errors |
michael@0 | 94 | downTime = move(downTime, endX, endY); |
michael@0 | 95 | downTime = up(downTime, endX, endY); |
michael@0 | 96 | } |
michael@0 | 97 | }; |
michael@0 | 98 | t.start(); |
michael@0 | 99 | return t; |
michael@0 | 100 | } |
michael@0 | 101 | |
michael@0 | 102 | public void dragSync(float startX, float startY, float endX, float endY, long durationMillis) { |
michael@0 | 103 | try { |
michael@0 | 104 | dragAsync(startX, startY, endX, endY, durationMillis).join(); |
michael@0 | 105 | mInstrumentation.waitForIdleSync(); |
michael@0 | 106 | } catch (InterruptedException ie) { |
michael@0 | 107 | ie.printStackTrace(); |
michael@0 | 108 | } |
michael@0 | 109 | } |
michael@0 | 110 | |
michael@0 | 111 | public void dragSync(float startX, float startY, float endX, float endY) { |
michael@0 | 112 | dragSync(startX, startY, endX, endY, 1000); |
michael@0 | 113 | } |
michael@0 | 114 | |
michael@0 | 115 | public Thread flingAsync(final float startX, final float startY, final float endX, final float endY, final float velocity) { |
michael@0 | 116 | // note that the first move after the touch-down is used to get over the panning threshold, and |
michael@0 | 117 | // is basically cancelled out. this means we need to generate (at least) two move events, with |
michael@0 | 118 | // the last move event hitting the target velocity. to do this we just slice the total distance |
michael@0 | 119 | // in half, assuming the first half will get us over the panning threshold and the second half |
michael@0 | 120 | // will trigger the fling. |
michael@0 | 121 | final float dx = (endX - startX) / 2; |
michael@0 | 122 | final float dy = (endY - startY) / 2; |
michael@0 | 123 | float distance = FloatMath.sqrt((dx * dx) + (dy * dy)); |
michael@0 | 124 | final long time = (long)(distance / velocity); |
michael@0 | 125 | if (time <= 0) { |
michael@0 | 126 | throw new IllegalArgumentException( "Fling parameters require too small a time period" ); |
michael@0 | 127 | } |
michael@0 | 128 | Thread t = new Thread() { |
michael@0 | 129 | @Override |
michael@0 | 130 | public void run() { |
michael@0 | 131 | long downTime = down(startX, startY); |
michael@0 | 132 | downTime = move(downTime, downTime + time, startX + dx, startY + dy); |
michael@0 | 133 | downTime = move(downTime, downTime + time + time, endX, endY); |
michael@0 | 134 | downTime = up(downTime, downTime + time, endX, endY); |
michael@0 | 135 | } |
michael@0 | 136 | }; |
michael@0 | 137 | t.start(); |
michael@0 | 138 | return t; |
michael@0 | 139 | } |
michael@0 | 140 | |
michael@0 | 141 | public void flingSync(float startX, float startY, float endX, float endY, float velocity) { |
michael@0 | 142 | try { |
michael@0 | 143 | flingAsync(startX, startY, endX, endY, velocity).join(); |
michael@0 | 144 | mInstrumentation.waitForIdleSync(); |
michael@0 | 145 | } catch (InterruptedException ie) { |
michael@0 | 146 | ie.printStackTrace(); |
michael@0 | 147 | } |
michael@0 | 148 | } |
michael@0 | 149 | |
michael@0 | 150 | public void tap(float x, float y) { |
michael@0 | 151 | long downTime = down(x, y); |
michael@0 | 152 | downTime = up(downTime, x, y); |
michael@0 | 153 | } |
michael@0 | 154 | |
michael@0 | 155 | public void doubleTap(float x, float y) { |
michael@0 | 156 | tap(x, y); |
michael@0 | 157 | tap(x, y); |
michael@0 | 158 | } |
michael@0 | 159 | } |