• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.dumprendertree;
18 
19 import android.os.SystemClock;
20 import android.util.*;
21 import android.view.KeyEvent;
22 import android.view.MotionEvent;
23 import android.webkit.WebView;
24 
25 import java.util.Arrays;
26 import java.util.Vector;
27 
28 public class WebViewEventSender implements EventSender {
29 
30     private static final String LOGTAG = "WebViewEventSender";
31 
WebViewEventSender(WebView webView)32     WebViewEventSender(WebView webView) {
33         mWebView = webView;
34         mWebView.getSettings().setBuiltInZoomControls(true);
35         mTouchPoints = new Vector<TouchPoint>();
36     }
37 
resetMouse()38 	public void resetMouse() {
39 		mouseX = mouseY = 0;
40 	}
41 
enableDOMUIEventLogging(int DOMNode)42 	public void enableDOMUIEventLogging(int DOMNode) {
43 		// TODO Auto-generated method stub
44 
45 	}
46 
fireKeyboardEventsToElement(int DOMNode)47 	public void fireKeyboardEventsToElement(int DOMNode) {
48 		// TODO Auto-generated method stub
49 
50 	}
51 
keyDown(String character, String[] withModifiers)52 	public void keyDown(String character, String[] withModifiers) {
53         Log.e("EventSender", "KeyDown: " + character + "("
54                 + character.getBytes()[0] + ") Modifiers: "
55                 + Arrays.toString(withModifiers));
56         KeyEvent modifier = null;
57         if (withModifiers != null && withModifiers.length > 0) {
58             for (int i = 0; i < withModifiers.length; i++) {
59                 int keyCode = modifierMapper(withModifiers[i]);
60                 modifier = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
61                 mWebView.onKeyDown(modifier.getKeyCode(), modifier);
62             }
63         }
64         int keyCode = keyMapper(character.toLowerCase().toCharArray()[0]);
65         KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
66         mWebView.onKeyDown(event.getKeyCode(), event);
67 
68     }
69 
keyDown(String character)70 	public void keyDown(String character) {
71         keyDown(character, null);
72 	}
73 
leapForward(int milliseconds)74 	public void leapForward(int milliseconds) {
75 		// TODO Auto-generated method stub
76 
77 	}
78 
mouseClick()79 	public void mouseClick() {
80 		mouseDown();
81 		mouseUp();
82 	}
83 
mouseDown()84     public void mouseDown() {
85         long ts = SystemClock.uptimeMillis();
86         MotionEvent event = MotionEvent.obtain(ts, ts, MotionEvent.ACTION_DOWN, mouseX, mouseY, 0);
87         mWebView.onTouchEvent(event);
88     }
89 
mouseMoveTo(int X, int Y)90     public void mouseMoveTo(int X, int Y) {
91         mouseX= X;
92         mouseY= Y;
93     }
94 
mouseUp()95      public void mouseUp() {
96         long ts = SystemClock.uptimeMillis();
97         MotionEvent event = MotionEvent.obtain(ts, ts, MotionEvent.ACTION_UP, mouseX, mouseY, 0);
98         mWebView.onTouchEvent(event);
99     }
100 
101 	// Assumes lowercase chars, case needs to be
102 	// handled by calling function.
keyMapper(char c)103 	static int keyMapper(char c) {
104 		// handle numbers
105 		if (c >= '0' && c<= '9') {
106 			int offset = c - '0';
107 			return KeyEvent.KEYCODE_0 + offset;
108 		}
109 
110 		// handle characters
111 		if (c >= 'a' && c <= 'z') {
112 			int offset = c - 'a';
113 			return KeyEvent.KEYCODE_A + offset;
114 		}
115 
116 		// handle all others
117 		switch (c) {
118 		case '*':
119 			return KeyEvent.KEYCODE_STAR;
120 		case '#':
121 			return KeyEvent.KEYCODE_POUND;
122 		case ',':
123 			return KeyEvent.KEYCODE_COMMA;
124 		case '.':
125 			return KeyEvent.KEYCODE_PERIOD;
126 		case '\t':
127 			return KeyEvent.KEYCODE_TAB;
128 		case ' ':
129 			return KeyEvent.KEYCODE_SPACE;
130 		case '\n':
131 			return KeyEvent.KEYCODE_ENTER;
132 		case '\b':
133         case 0x7F:
134 			return KeyEvent.KEYCODE_DEL;
135 		case '~':
136 			return KeyEvent.KEYCODE_GRAVE;
137 		case '-':
138 			return KeyEvent.KEYCODE_MINUS;
139 		case '=':
140 			return KeyEvent.KEYCODE_EQUALS;
141 		case '(':
142 			return KeyEvent.KEYCODE_LEFT_BRACKET;
143 		case ')':
144 			return KeyEvent.KEYCODE_RIGHT_BRACKET;
145 		case '\\':
146 			return KeyEvent.KEYCODE_BACKSLASH;
147 		case ';':
148 			return KeyEvent.KEYCODE_SEMICOLON;
149 		case '\'':
150 			return KeyEvent.KEYCODE_APOSTROPHE;
151 		case '/':
152 			return KeyEvent.KEYCODE_SLASH;
153 		default:
154 			break;
155 		}
156 
157 		return c;
158 	}
159 
modifierMapper(String modifier)160 	static int modifierMapper(String modifier) {
161 		if (modifier.equals("ctrlKey")) {
162 			return KeyEvent.KEYCODE_ALT_LEFT;
163 		} else if (modifier.equals("shiftKey")) {
164 			return KeyEvent.KEYCODE_SHIFT_LEFT;
165 		} else if (modifier.equals("altKey")) {
166 			return KeyEvent.KEYCODE_SYM;
167 		} else if (modifier.equals("metaKey")) {
168 			return KeyEvent.KEYCODE_UNKNOWN;
169 		}
170 		return KeyEvent.KEYCODE_UNKNOWN;
171 	}
172 
touchStart()173     public void touchStart() {
174         final int numPoints = mTouchPoints.size();
175         if (numPoints == 0) {
176             return;
177         }
178 
179         int[] pointerIds = new int[numPoints];
180         MotionEvent.PointerCoords[] pointerCoords = new MotionEvent.PointerCoords[numPoints];
181         long downTime = SystemClock.uptimeMillis();
182 
183         for (int i = 0; i < numPoints; ++i) {
184             pointerIds[i] = mTouchPoints.get(i).getId();
185             pointerCoords[i] = new MotionEvent.PointerCoords();
186             pointerCoords[i].x = mTouchPoints.get(i).getX();
187             pointerCoords[i].y = mTouchPoints.get(i).getY();
188             mTouchPoints.get(i).setDownTime(downTime);
189         }
190 
191         MotionEvent event = MotionEvent.obtain(downTime, downTime,
192             MotionEvent.ACTION_DOWN, numPoints, pointerIds, pointerCoords,
193             mTouchMetaState, 1.0f, 1.0f, 0, 0, 0, 0);
194 
195         mWebView.onTouchEvent(event);
196     }
197 
touchMove()198     public void touchMove() {
199         final int numPoints = mTouchPoints.size();
200         if (numPoints == 0) {
201             return;
202         }
203 
204         int[] pointerIds = new int[numPoints];
205         MotionEvent.PointerCoords[] pointerCoords = new MotionEvent.PointerCoords[numPoints];
206         int numMovedPoints = 0;
207         for (int i = 0; i < numPoints; ++i) {
208             TouchPoint tp = mTouchPoints.get(i);
209             if (tp.hasMoved()) {
210                 pointerIds[numMovedPoints] = mTouchPoints.get(i).getId();
211                 pointerCoords[i] = new MotionEvent.PointerCoords();
212                 pointerCoords[numMovedPoints].x = mTouchPoints.get(i).getX();
213                 pointerCoords[numMovedPoints].y = mTouchPoints.get(i).getY();
214                 ++numMovedPoints;
215                 tp.setMoved(false);
216             }
217         }
218 
219         if (numMovedPoints == 0) {
220             return;
221         }
222 
223         MotionEvent event = MotionEvent.obtain(mTouchPoints.get(0).downTime(),
224                 SystemClock.uptimeMillis(), MotionEvent.ACTION_MOVE,
225                 numMovedPoints, pointerIds, pointerCoords,
226                 mTouchMetaState, 1.0f, 1.0f, 0, 0, 0, 0);
227         mWebView.onTouchEvent(event);
228     }
229 
touchEnd()230     public void touchEnd() {
231         final int numPoints = mTouchPoints.size();
232         if (numPoints == 0) {
233             return;
234         }
235 
236         int[] pointerIds = new int[numPoints];
237         MotionEvent.PointerCoords[] pointerCoords = new MotionEvent.PointerCoords[numPoints];
238 
239         for (int i = 0; i < numPoints; ++i) {
240             pointerIds[i] = mTouchPoints.get(i).getId();
241             pointerCoords[i] = new MotionEvent.PointerCoords();
242             pointerCoords[i].x = mTouchPoints.get(i).getX();
243             pointerCoords[i].y = mTouchPoints.get(i).getY();
244         }
245 
246         MotionEvent event = MotionEvent.obtain(mTouchPoints.get(0).downTime(),
247                 SystemClock.uptimeMillis(), MotionEvent.ACTION_UP,
248                 numPoints, pointerIds, pointerCoords,
249                 mTouchMetaState, 1.0f, 1.0f, 0, 0, 0, 0);
250         mWebView.onTouchEvent(event);
251 
252         for (int i = numPoints - 1; i >= 0; --i) {  // remove released points.
253             TouchPoint tp = mTouchPoints.get(i);
254             if (tp.isReleased()) {
255               mTouchPoints.remove(i);
256             }
257         }
258     }
259 
touchCancel()260     public void touchCancel() {
261         final int numPoints = mTouchPoints.size();
262         if (numPoints == 0) {
263             return;
264         }
265 
266         int[] pointerIds = new int[numPoints];
267         MotionEvent.PointerCoords[] pointerCoords = new MotionEvent.PointerCoords[numPoints];
268         long cancelTime = SystemClock.uptimeMillis();
269         int numCanceledPoints = 0;
270 
271         for (int i = 0; i < numPoints; ++i) {
272             TouchPoint tp = mTouchPoints.get(i);
273             if (tp.cancelled()) {
274                 pointerIds[numCanceledPoints] = mTouchPoints.get(i).getId();
275                 pointerCoords[numCanceledPoints] = new MotionEvent.PointerCoords();
276                 pointerCoords[numCanceledPoints].x = mTouchPoints.get(i).getX();
277                 pointerCoords[numCanceledPoints].y = mTouchPoints.get(i).getY();
278                 ++numCanceledPoints;
279             }
280         }
281 
282         if (numCanceledPoints == 0) {
283             return;
284         }
285 
286         MotionEvent event = MotionEvent.obtain(mTouchPoints.get(0).downTime(),
287             SystemClock.uptimeMillis(), MotionEvent.ACTION_CANCEL,
288             numCanceledPoints, pointerIds, pointerCoords,
289             mTouchMetaState, 1.0f, 1.0f, 0, 0, 0, 0);
290 
291         mWebView.onTouchEvent(event);
292     }
293 
cancelTouchPoint(int id)294     public void cancelTouchPoint(int id) {
295         TouchPoint tp = mTouchPoints.get(id);
296         if (tp == null) {
297             return;
298         }
299 
300         tp.cancel();
301     }
302 
addTouchPoint(int x, int y)303     public void addTouchPoint(int x, int y) {
304         final int numPoints = mTouchPoints.size();
305         int id;
306         if (numPoints == 0) {
307           id = 0;
308         } else {
309           id = mTouchPoints.get(numPoints - 1).getId() + 1;
310         }
311 
312         mTouchPoints.add(new TouchPoint(id, contentsToWindowX(x), contentsToWindowY(y)));
313     }
314 
updateTouchPoint(int i, int x, int y)315     public void updateTouchPoint(int i, int x, int y) {
316         TouchPoint tp = mTouchPoints.get(i);
317         if (tp == null) {
318             return;
319         }
320 
321         tp.update(contentsToWindowX(x), contentsToWindowY(y));
322         tp.setMoved(true);
323     }
324 
setTouchModifier(String modifier, boolean enabled)325     public void setTouchModifier(String modifier, boolean enabled) {
326         int mask = 0;
327         if ("alt".equals(modifier.toLowerCase())) {
328             mask = KeyEvent.META_ALT_ON;
329         } else if ("shift".equals(modifier.toLowerCase())) {
330             mask = KeyEvent.META_SHIFT_ON;
331         } else if ("ctrl".equals(modifier.toLowerCase())) {
332             mask = KeyEvent.META_SYM_ON;
333         }
334 
335         if (enabled) {
336             mTouchMetaState |= mask;
337         } else {
338             mTouchMetaState &= ~mask;
339         }
340     }
341 
releaseTouchPoint(int id)342     public void releaseTouchPoint(int id) {
343         TouchPoint tp = mTouchPoints.get(id);
344         if (tp == null) {
345             return;
346         }
347 
348         tp.release();
349     }
350 
clearTouchPoints()351     public void clearTouchPoints() {
352         mTouchPoints.clear();
353     }
354 
clearTouchMetaState()355     public void clearTouchMetaState() {
356         mTouchMetaState = 0;
357     }
358 
contentsToWindowX(int x)359     private int contentsToWindowX(int x) {
360         return Math.round(x * mWebView.getScale()) - mWebView.getScrollX();
361     }
362 
contentsToWindowY(int y)363     private int contentsToWindowY(int y) {
364         return Math.round(y * mWebView.getScale()) - mWebView.getScrollY();
365     }
366 
367     private WebView mWebView = null;
368     private int mouseX;
369     private int mouseY;
370 
371     private class TouchPoint {
372         private int mId;
373         private int mX;
374         private int mY;
375         private long mDownTime;
376         private boolean mReleased;
377         private boolean mMoved;
378         private boolean mCancelled;
379 
TouchPoint(int id, int x, int y)380         public TouchPoint(int id, int x, int y) {
381             mId = id;
382             mX = x;
383             mY = y;
384             mReleased = false;
385             mMoved = false;
386             mCancelled = false;
387         }
388 
setDownTime(long downTime)389         public void setDownTime(long downTime) { mDownTime = downTime; }
downTime()390         public long downTime() { return mDownTime; }
cancel()391         public void cancel() { mCancelled = true; }
392 
cancelled()393         public boolean cancelled() { return mCancelled; }
394 
release()395         public void release() { mReleased = true; }
isReleased()396         public boolean isReleased() { return mReleased; }
397 
setMoved(boolean moved)398         public void setMoved(boolean moved) { mMoved = moved; }
hasMoved()399         public boolean hasMoved() { return mMoved; }
400 
getId()401         public int getId() { return mId; }
getX()402         public int getX() { return mX; }
getY()403         public int getY() { return mY; }
404 
update(int x, int y)405         public void update(int x, int y) {
406             mX = x;
407             mY = y;
408         }
409     }
410 
411     private Vector<TouchPoint> mTouchPoints;
412     private int mTouchMetaState;
413 }
414