Home | History | Annotate | Download | only in dumprendertree
      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 
     32     WebViewEventSender(WebView webView) {
     33         mWebView = webView;
     34         mWebView.getSettings().setBuiltInZoomControls(true);
     35         mTouchPoints = new Vector<TouchPoint>();
     36     }
     37 
     38 	public void resetMouse() {
     39 		mouseX = mouseY = 0;
     40 	}
     41 
     42 	public void enableDOMUIEventLogging(int DOMNode) {
     43 		// TODO Auto-generated method stub
     44 
     45 	}
     46 
     47 	public void fireKeyboardEventsToElement(int DOMNode) {
     48 		// TODO Auto-generated method stub
     49 
     50 	}
     51 
     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 
     70 	public void keyDown(String character) {
     71         keyDown(character, null);
     72 	}
     73 
     74 	public void leapForward(int milliseconds) {
     75 		// TODO Auto-generated method stub
     76 
     77 	}
     78 
     79 	public void mouseClick() {
     80 		mouseDown();
     81 		mouseUp();
     82 	}
     83 
     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 
     90     public void mouseMoveTo(int X, int Y) {
     91         mouseX= X;
     92         mouseY= Y;
     93     }
     94 
     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.
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    351     public void clearTouchPoints() {
    352         mTouchPoints.clear();
    353     }
    354 
    355     public void clearTouchMetaState() {
    356         mTouchMetaState = 0;
    357     }
    358 
    359     private int contentsToWindowX(int x) {
    360         return Math.round(x * mWebView.getScale()) - mWebView.getScrollX();
    361     }
    362 
    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 
    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 
    389         public void setDownTime(long downTime) { mDownTime = downTime; }
    390         public long downTime() { return mDownTime; }
    391         public void cancel() { mCancelled = true; }
    392 
    393         public boolean cancelled() { return mCancelled; }
    394 
    395         public void release() { mReleased = true; }
    396         public boolean isReleased() { return mReleased; }
    397 
    398         public void setMoved(boolean moved) { mMoved = moved; }
    399         public boolean hasMoved() { return mMoved; }
    400 
    401         public int getId() { return mId; }
    402         public int getX() { return mX; }
    403         public int getY() { return mY; }
    404 
    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