mobile/android/base/GeckoEvent.java

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
michael@0 2 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 package org.mozilla.gecko;
michael@0 7
michael@0 8 import org.mozilla.gecko.gfx.DisplayPortMetrics;
michael@0 9 import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
michael@0 10 import org.mozilla.gecko.mozglue.JNITarget;
michael@0 11 import org.mozilla.gecko.mozglue.generatorannotations.GeneratorOptions;
michael@0 12 import org.mozilla.gecko.mozglue.generatorannotations.WrapEntireClassForJNI;
michael@0 13 import org.mozilla.gecko.mozglue.RobocopTarget;
michael@0 14
michael@0 15 import android.content.res.Resources;
michael@0 16 import android.graphics.Point;
michael@0 17 import android.graphics.PointF;
michael@0 18 import android.graphics.Rect;
michael@0 19 import android.hardware.Sensor;
michael@0 20 import android.hardware.SensorEvent;
michael@0 21 import android.hardware.SensorManager;
michael@0 22 import android.location.Address;
michael@0 23 import android.location.Location;
michael@0 24 import android.os.Build;
michael@0 25 import android.os.SystemClock;
michael@0 26 import android.util.DisplayMetrics;
michael@0 27 import android.util.Log;
michael@0 28 import android.util.SparseArray;
michael@0 29 import android.view.KeyEvent;
michael@0 30 import android.view.MotionEvent;
michael@0 31
michael@0 32 import java.nio.ByteBuffer;
michael@0 33 import java.util.concurrent.ArrayBlockingQueue;
michael@0 34
michael@0 35 /* We're not allowed to hold on to most events given to us
michael@0 36 * so we save the parts of the events we want to use in GeckoEvent.
michael@0 37 * Fields have different meanings depending on the event type.
michael@0 38 */
michael@0 39
michael@0 40 /* This class is referenced by Robocop via reflection; use care when
michael@0 41 * modifying the signature.
michael@0 42 */
michael@0 43 @JNITarget
michael@0 44 public class GeckoEvent {
michael@0 45 private static final String LOGTAG = "GeckoEvent";
michael@0 46
michael@0 47 private static final int EVENT_FACTORY_SIZE = 5;
michael@0 48
michael@0 49 // Maybe we're probably better to just make mType non final, and just store GeckoEvents in here...
michael@0 50 private static SparseArray<ArrayBlockingQueue<GeckoEvent>> mEvents = new SparseArray<ArrayBlockingQueue<GeckoEvent>>();
michael@0 51
michael@0 52 public static GeckoEvent get(NativeGeckoEvent type) {
michael@0 53 synchronized (mEvents) {
michael@0 54 ArrayBlockingQueue<GeckoEvent> events = mEvents.get(type.value);
michael@0 55 if (events != null && events.size() > 0) {
michael@0 56 return events.poll();
michael@0 57 }
michael@0 58 }
michael@0 59
michael@0 60 return new GeckoEvent(type);
michael@0 61 }
michael@0 62
michael@0 63 public void recycle() {
michael@0 64 synchronized (mEvents) {
michael@0 65 ArrayBlockingQueue<GeckoEvent> events = mEvents.get(mType);
michael@0 66 if (events == null) {
michael@0 67 events = new ArrayBlockingQueue<GeckoEvent>(EVENT_FACTORY_SIZE);
michael@0 68 mEvents.put(mType, events);
michael@0 69 }
michael@0 70
michael@0 71 events.offer(this);
michael@0 72 }
michael@0 73 }
michael@0 74
michael@0 75 // Make sure to keep these values in sync with the enum in
michael@0 76 // AndroidGeckoEvent in widget/android/AndroidJavaWrappers.h
michael@0 77 @JNITarget
michael@0 78 private enum NativeGeckoEvent {
michael@0 79 NATIVE_POKE(0),
michael@0 80 KEY_EVENT(1),
michael@0 81 MOTION_EVENT(2),
michael@0 82 SENSOR_EVENT(3),
michael@0 83 LOCATION_EVENT(5),
michael@0 84 IME_EVENT(6),
michael@0 85 DRAW(7),
michael@0 86 SIZE_CHANGED(8),
michael@0 87 APP_BACKGROUNDING(9),
michael@0 88 APP_FOREGROUNDING(10),
michael@0 89 LOAD_URI(12),
michael@0 90 NOOP(15),
michael@0 91 BROADCAST(19),
michael@0 92 VIEWPORT(20),
michael@0 93 VISITED(21),
michael@0 94 NETWORK_CHANGED(22),
michael@0 95 THUMBNAIL(25),
michael@0 96 SCREENORIENTATION_CHANGED(27),
michael@0 97 COMPOSITOR_CREATE(28),
michael@0 98 COMPOSITOR_PAUSE(29),
michael@0 99 COMPOSITOR_RESUME(30),
michael@0 100 NATIVE_GESTURE_EVENT(31),
michael@0 101 IME_KEY_EVENT(32),
michael@0 102 CALL_OBSERVER(33),
michael@0 103 REMOVE_OBSERVER(34),
michael@0 104 LOW_MEMORY(35),
michael@0 105 NETWORK_LINK_CHANGE(36),
michael@0 106 TELEMETRY_HISTOGRAM_ADD(37),
michael@0 107 PREFERENCES_OBSERVE(39),
michael@0 108 PREFERENCES_GET(40),
michael@0 109 PREFERENCES_REMOVE_OBSERVERS(41),
michael@0 110 TELEMETRY_UI_SESSION_START(42),
michael@0 111 TELEMETRY_UI_SESSION_STOP(43),
michael@0 112 TELEMETRY_UI_EVENT(44);
michael@0 113
michael@0 114 public final int value;
michael@0 115
michael@0 116 private NativeGeckoEvent(int value) {
michael@0 117 this.value = value;
michael@0 118 }
michael@0 119 }
michael@0 120
michael@0 121 /**
michael@0 122 * The DomKeyLocation enum encapsulates the DOM KeyboardEvent's constants.
michael@0 123 * @see https://developer.mozilla.org/en-US/docs/DOM/KeyboardEvent#Key_location_constants
michael@0 124 */
michael@0 125 @GeneratorOptions(generatedClassName = "JavaDomKeyLocation")
michael@0 126 @WrapEntireClassForJNI
michael@0 127 public enum DomKeyLocation {
michael@0 128 DOM_KEY_LOCATION_STANDARD(0),
michael@0 129 DOM_KEY_LOCATION_LEFT(1),
michael@0 130 DOM_KEY_LOCATION_RIGHT(2),
michael@0 131 DOM_KEY_LOCATION_NUMPAD(3),
michael@0 132 DOM_KEY_LOCATION_MOBILE(4),
michael@0 133 DOM_KEY_LOCATION_JOYSTICK(5);
michael@0 134
michael@0 135 public final int value;
michael@0 136
michael@0 137 private DomKeyLocation(int value) {
michael@0 138 this.value = value;
michael@0 139 }
michael@0 140 }
michael@0 141
michael@0 142 // Encapsulation of common IME actions.
michael@0 143 @JNITarget
michael@0 144 public enum ImeAction {
michael@0 145 IME_SYNCHRONIZE(0),
michael@0 146 IME_REPLACE_TEXT(1),
michael@0 147 IME_SET_SELECTION(2),
michael@0 148 IME_ADD_COMPOSITION_RANGE(3),
michael@0 149 IME_UPDATE_COMPOSITION(4),
michael@0 150 IME_REMOVE_COMPOSITION(5),
michael@0 151 IME_ACKNOWLEDGE_FOCUS(6);
michael@0 152
michael@0 153 public final int value;
michael@0 154
michael@0 155 private ImeAction(int value) {
michael@0 156 this.value = value;
michael@0 157 }
michael@0 158 }
michael@0 159
michael@0 160 public static final int IME_RANGE_CARETPOSITION = 1;
michael@0 161 public static final int IME_RANGE_RAWINPUT = 2;
michael@0 162 public static final int IME_RANGE_SELECTEDRAWTEXT = 3;
michael@0 163 public static final int IME_RANGE_CONVERTEDTEXT = 4;
michael@0 164 public static final int IME_RANGE_SELECTEDCONVERTEDTEXT = 5;
michael@0 165
michael@0 166 public static final int IME_RANGE_LINE_NONE = 0;
michael@0 167 public static final int IME_RANGE_LINE_DOTTED = 1;
michael@0 168 public static final int IME_RANGE_LINE_DASHED = 2;
michael@0 169 public static final int IME_RANGE_LINE_SOLID = 3;
michael@0 170 public static final int IME_RANGE_LINE_DOUBLE = 4;
michael@0 171 public static final int IME_RANGE_LINE_WAVY = 5;
michael@0 172
michael@0 173 public static final int IME_RANGE_UNDERLINE = 1;
michael@0 174 public static final int IME_RANGE_FORECOLOR = 2;
michael@0 175 public static final int IME_RANGE_BACKCOLOR = 4;
michael@0 176 public static final int IME_RANGE_LINECOLOR = 8;
michael@0 177
michael@0 178 public static final int ACTION_MAGNIFY_START = 11;
michael@0 179 public static final int ACTION_MAGNIFY = 12;
michael@0 180 public static final int ACTION_MAGNIFY_END = 13;
michael@0 181
michael@0 182 private final int mType;
michael@0 183 private int mAction;
michael@0 184 private boolean mAckNeeded;
michael@0 185 private long mTime;
michael@0 186 private Point[] mPoints;
michael@0 187 private int[] mPointIndicies;
michael@0 188 private int mPointerIndex; // index of the point that has changed
michael@0 189 private float[] mOrientations;
michael@0 190 private float[] mPressures;
michael@0 191 private Point[] mPointRadii;
michael@0 192 private Rect mRect;
michael@0 193 private double mX;
michael@0 194 private double mY;
michael@0 195 private double mZ;
michael@0 196
michael@0 197 private int mMetaState;
michael@0 198 private int mFlags;
michael@0 199 private int mKeyCode;
michael@0 200 private int mUnicodeChar;
michael@0 201 private int mBaseUnicodeChar; // mUnicodeChar without meta states applied
michael@0 202 private int mDOMPrintableKeyValue;
michael@0 203 private int mRepeatCount;
michael@0 204 private int mCount;
michael@0 205 private int mStart;
michael@0 206 private int mEnd;
michael@0 207 private String mCharacters;
michael@0 208 private String mCharactersExtra;
michael@0 209 private String mData;
michael@0 210 private int mRangeType;
michael@0 211 private int mRangeStyles;
michael@0 212 private int mRangeLineStyle;
michael@0 213 private boolean mRangeBoldLine;
michael@0 214 private int mRangeForeColor;
michael@0 215 private int mRangeBackColor;
michael@0 216 private int mRangeLineColor;
michael@0 217 private Location mLocation;
michael@0 218 private Address mAddress;
michael@0 219 private DomKeyLocation mDomKeyLocation;
michael@0 220
michael@0 221 private int mConnectionType;
michael@0 222 private boolean mIsWifi;
michael@0 223 private int mDHCPGateway;
michael@0 224
michael@0 225 private int mNativeWindow;
michael@0 226
michael@0 227 private short mScreenOrientation;
michael@0 228
michael@0 229 private ByteBuffer mBuffer;
michael@0 230
michael@0 231 private int mWidth;
michael@0 232 private int mHeight;
michael@0 233
michael@0 234 private String[] mPrefNames;
michael@0 235
michael@0 236 private GeckoEvent(NativeGeckoEvent event) {
michael@0 237 mType = event.value;
michael@0 238 }
michael@0 239
michael@0 240 public static GeckoEvent createAppBackgroundingEvent() {
michael@0 241 return GeckoEvent.get(NativeGeckoEvent.APP_BACKGROUNDING);
michael@0 242 }
michael@0 243
michael@0 244 public static GeckoEvent createAppForegroundingEvent() {
michael@0 245 return GeckoEvent.get(NativeGeckoEvent.APP_FOREGROUNDING);
michael@0 246 }
michael@0 247
michael@0 248 public static GeckoEvent createNoOpEvent() {
michael@0 249 return GeckoEvent.get(NativeGeckoEvent.NOOP);
michael@0 250 }
michael@0 251
michael@0 252 public static GeckoEvent createKeyEvent(KeyEvent k, int metaState) {
michael@0 253 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.KEY_EVENT);
michael@0 254 event.initKeyEvent(k, metaState);
michael@0 255 return event;
michael@0 256 }
michael@0 257
michael@0 258 public static GeckoEvent createCompositorCreateEvent(int width, int height) {
michael@0 259 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.COMPOSITOR_CREATE);
michael@0 260 event.mWidth = width;
michael@0 261 event.mHeight = height;
michael@0 262 return event;
michael@0 263 }
michael@0 264
michael@0 265 public static GeckoEvent createCompositorPauseEvent() {
michael@0 266 return GeckoEvent.get(NativeGeckoEvent.COMPOSITOR_PAUSE);
michael@0 267 }
michael@0 268
michael@0 269 public static GeckoEvent createCompositorResumeEvent() {
michael@0 270 return GeckoEvent.get(NativeGeckoEvent.COMPOSITOR_RESUME);
michael@0 271 }
michael@0 272
michael@0 273 private void initKeyEvent(KeyEvent k, int metaState) {
michael@0 274 mAction = k.getAction();
michael@0 275 mTime = k.getEventTime();
michael@0 276 // Normally we expect k.getMetaState() to reflect the current meta-state; however,
michael@0 277 // some software-generated key events may not have k.getMetaState() set, e.g. key
michael@0 278 // events from Swype. Therefore, it's necessary to combine the key's meta-states
michael@0 279 // with the meta-states that we keep separately in KeyListener
michael@0 280 mMetaState = k.getMetaState() | metaState;
michael@0 281 mFlags = k.getFlags();
michael@0 282 mKeyCode = k.getKeyCode();
michael@0 283 mUnicodeChar = k.getUnicodeChar(mMetaState);
michael@0 284 // e.g. for Ctrl+A, Android returns 0 for mUnicodeChar,
michael@0 285 // but Gecko expects 'a', so we return that in mBaseUnicodeChar
michael@0 286 mBaseUnicodeChar = k.getUnicodeChar(0);
michael@0 287 mRepeatCount = k.getRepeatCount();
michael@0 288 mCharacters = k.getCharacters();
michael@0 289 if (mUnicodeChar >= ' ') {
michael@0 290 mDOMPrintableKeyValue = mUnicodeChar;
michael@0 291 } else {
michael@0 292 int unmodifiedMetaState =
michael@0 293 mMetaState & ~(KeyEvent.META_ALT_MASK |
michael@0 294 KeyEvent.META_CTRL_MASK |
michael@0 295 KeyEvent.META_META_MASK);
michael@0 296 if (unmodifiedMetaState != mMetaState) {
michael@0 297 mDOMPrintableKeyValue = k.getUnicodeChar(unmodifiedMetaState);
michael@0 298 }
michael@0 299 }
michael@0 300 mDomKeyLocation = isJoystickButton(mKeyCode) ? DomKeyLocation.DOM_KEY_LOCATION_JOYSTICK
michael@0 301 : DomKeyLocation.DOM_KEY_LOCATION_MOBILE;
michael@0 302 }
michael@0 303
michael@0 304 /**
michael@0 305 * This method tests if a key is one of the described in:
michael@0 306 * https://bugzilla.mozilla.org/show_bug.cgi?id=756504#c0
michael@0 307 * @param keyCode int with the key code (Android key constant from KeyEvent)
michael@0 308 * @return true if the key is one of the listed above, false otherwise.
michael@0 309 */
michael@0 310 private static boolean isJoystickButton(int keyCode) {
michael@0 311 switch (keyCode) {
michael@0 312 case KeyEvent.KEYCODE_DPAD_CENTER:
michael@0 313 case KeyEvent.KEYCODE_DPAD_LEFT:
michael@0 314 case KeyEvent.KEYCODE_DPAD_RIGHT:
michael@0 315 case KeyEvent.KEYCODE_DPAD_DOWN:
michael@0 316 case KeyEvent.KEYCODE_DPAD_UP:
michael@0 317 return true;
michael@0 318 default:
michael@0 319 if (Build.VERSION.SDK_INT >= 12) {
michael@0 320 return KeyEvent.isGamepadButton(keyCode);
michael@0 321 }
michael@0 322 return GeckoEvent.isGamepadButton(keyCode);
michael@0 323 }
michael@0 324 }
michael@0 325
michael@0 326 /**
michael@0 327 * This method is a replacement for the the KeyEvent.isGamepadButton method to be
michael@0 328 * compatible with Build.VERSION.SDK_INT < 12. This is an implementantion of the
michael@0 329 * same method isGamepadButton available after SDK 12.
michael@0 330 * @param keyCode int with the key code (Android key constant from KeyEvent).
michael@0 331 * @return True if the keycode is a gamepad button, such as {@link #KEYCODE_BUTTON_A}.
michael@0 332 */
michael@0 333 private static boolean isGamepadButton(int keyCode) {
michael@0 334 switch (keyCode) {
michael@0 335 case KeyEvent.KEYCODE_BUTTON_A:
michael@0 336 case KeyEvent.KEYCODE_BUTTON_B:
michael@0 337 case KeyEvent.KEYCODE_BUTTON_C:
michael@0 338 case KeyEvent.KEYCODE_BUTTON_X:
michael@0 339 case KeyEvent.KEYCODE_BUTTON_Y:
michael@0 340 case KeyEvent.KEYCODE_BUTTON_Z:
michael@0 341 case KeyEvent.KEYCODE_BUTTON_L1:
michael@0 342 case KeyEvent.KEYCODE_BUTTON_R1:
michael@0 343 case KeyEvent.KEYCODE_BUTTON_L2:
michael@0 344 case KeyEvent.KEYCODE_BUTTON_R2:
michael@0 345 case KeyEvent.KEYCODE_BUTTON_THUMBL:
michael@0 346 case KeyEvent.KEYCODE_BUTTON_THUMBR:
michael@0 347 case KeyEvent.KEYCODE_BUTTON_START:
michael@0 348 case KeyEvent.KEYCODE_BUTTON_SELECT:
michael@0 349 case KeyEvent.KEYCODE_BUTTON_MODE:
michael@0 350 case KeyEvent.KEYCODE_BUTTON_1:
michael@0 351 case KeyEvent.KEYCODE_BUTTON_2:
michael@0 352 case KeyEvent.KEYCODE_BUTTON_3:
michael@0 353 case KeyEvent.KEYCODE_BUTTON_4:
michael@0 354 case KeyEvent.KEYCODE_BUTTON_5:
michael@0 355 case KeyEvent.KEYCODE_BUTTON_6:
michael@0 356 case KeyEvent.KEYCODE_BUTTON_7:
michael@0 357 case KeyEvent.KEYCODE_BUTTON_8:
michael@0 358 case KeyEvent.KEYCODE_BUTTON_9:
michael@0 359 case KeyEvent.KEYCODE_BUTTON_10:
michael@0 360 case KeyEvent.KEYCODE_BUTTON_11:
michael@0 361 case KeyEvent.KEYCODE_BUTTON_12:
michael@0 362 case KeyEvent.KEYCODE_BUTTON_13:
michael@0 363 case KeyEvent.KEYCODE_BUTTON_14:
michael@0 364 case KeyEvent.KEYCODE_BUTTON_15:
michael@0 365 case KeyEvent.KEYCODE_BUTTON_16:
michael@0 366 return true;
michael@0 367 default:
michael@0 368 return false;
michael@0 369 }
michael@0 370 }
michael@0 371
michael@0 372 public static GeckoEvent createNativeGestureEvent(int action, PointF pt, double size) {
michael@0 373 try {
michael@0 374 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.NATIVE_GESTURE_EVENT);
michael@0 375 event.mAction = action;
michael@0 376 event.mCount = 1;
michael@0 377 event.mPoints = new Point[1];
michael@0 378
michael@0 379 PointF geckoPoint = new PointF(pt.x, pt.y);
michael@0 380 geckoPoint = GeckoAppShell.getLayerView().convertViewPointToLayerPoint(geckoPoint);
michael@0 381
michael@0 382 if (geckoPoint == null) {
michael@0 383 // This could happen if Gecko isn't ready yet.
michael@0 384 return null;
michael@0 385 }
michael@0 386
michael@0 387 event.mPoints[0] = new Point(Math.round(geckoPoint.x), Math.round(geckoPoint.y));
michael@0 388
michael@0 389 event.mX = size;
michael@0 390 event.mTime = System.currentTimeMillis();
michael@0 391 return event;
michael@0 392 } catch (Exception e) {
michael@0 393 // This can happen if Gecko isn't ready yet
michael@0 394 return null;
michael@0 395 }
michael@0 396 }
michael@0 397
michael@0 398 /**
michael@0 399 * Creates a GeckoEvent that contains the data from the MotionEvent.
michael@0 400 * The keepInViewCoordinates parameter can be set to false to convert from the Java
michael@0 401 * coordinate system (device pixels relative to the LayerView) to a coordinate system
michael@0 402 * relative to gecko's coordinate system (CSS pixels relative to gecko scroll position).
michael@0 403 */
michael@0 404 public static GeckoEvent createMotionEvent(MotionEvent m, boolean keepInViewCoordinates) {
michael@0 405 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.MOTION_EVENT);
michael@0 406 event.initMotionEvent(m, keepInViewCoordinates);
michael@0 407 return event;
michael@0 408 }
michael@0 409
michael@0 410 private void initMotionEvent(MotionEvent m, boolean keepInViewCoordinates) {
michael@0 411 mAction = m.getActionMasked();
michael@0 412 mTime = (System.currentTimeMillis() - SystemClock.elapsedRealtime()) + m.getEventTime();
michael@0 413 mMetaState = m.getMetaState();
michael@0 414
michael@0 415 switch (mAction) {
michael@0 416 case MotionEvent.ACTION_CANCEL:
michael@0 417 case MotionEvent.ACTION_UP:
michael@0 418 case MotionEvent.ACTION_POINTER_UP:
michael@0 419 case MotionEvent.ACTION_POINTER_DOWN:
michael@0 420 case MotionEvent.ACTION_DOWN:
michael@0 421 case MotionEvent.ACTION_MOVE:
michael@0 422 case MotionEvent.ACTION_HOVER_ENTER:
michael@0 423 case MotionEvent.ACTION_HOVER_MOVE:
michael@0 424 case MotionEvent.ACTION_HOVER_EXIT: {
michael@0 425 mCount = m.getPointerCount();
michael@0 426 mPoints = new Point[mCount];
michael@0 427 mPointIndicies = new int[mCount];
michael@0 428 mOrientations = new float[mCount];
michael@0 429 mPressures = new float[mCount];
michael@0 430 mPointRadii = new Point[mCount];
michael@0 431 mPointerIndex = m.getActionIndex();
michael@0 432 for (int i = 0; i < mCount; i++) {
michael@0 433 addMotionPoint(i, i, m, keepInViewCoordinates);
michael@0 434 }
michael@0 435 break;
michael@0 436 }
michael@0 437 default: {
michael@0 438 mCount = 0;
michael@0 439 mPointerIndex = -1;
michael@0 440 mPoints = new Point[mCount];
michael@0 441 mPointIndicies = new int[mCount];
michael@0 442 mOrientations = new float[mCount];
michael@0 443 mPressures = new float[mCount];
michael@0 444 mPointRadii = new Point[mCount];
michael@0 445 }
michael@0 446 }
michael@0 447 }
michael@0 448
michael@0 449 private void addMotionPoint(int index, int eventIndex, MotionEvent event, boolean keepInViewCoordinates) {
michael@0 450 try {
michael@0 451 PointF geckoPoint = new PointF(event.getX(eventIndex), event.getY(eventIndex));
michael@0 452 if (!keepInViewCoordinates) {
michael@0 453 geckoPoint = GeckoAppShell.getLayerView().convertViewPointToLayerPoint(geckoPoint);
michael@0 454 }
michael@0 455
michael@0 456 mPoints[index] = new Point(Math.round(geckoPoint.x), Math.round(geckoPoint.y));
michael@0 457 mPointIndicies[index] = event.getPointerId(eventIndex);
michael@0 458 // getToolMajor, getToolMinor and getOrientation are API Level 9 features
michael@0 459 if (Build.VERSION.SDK_INT >= 9) {
michael@0 460 double radians = event.getOrientation(eventIndex);
michael@0 461 mOrientations[index] = (float) Math.toDegrees(radians);
michael@0 462 // w3c touchevents spec does not allow orientations == 90
michael@0 463 // this shifts it to -90, which will be shifted to zero below
michael@0 464 if (mOrientations[index] == 90)
michael@0 465 mOrientations[index] = -90;
michael@0 466
michael@0 467 // w3c touchevent radius are given by an orientation between 0 and 90
michael@0 468 // the radius is found by removing the orientation and measuring the x and y
michael@0 469 // radius of the resulting ellipse
michael@0 470 // for android orientations >= 0 and < 90, the major axis should correspond to
michael@0 471 // just reporting the y radius as the major one, and x as minor
michael@0 472 // however, for a radius < 0, we have to shift the orientation by adding 90, and
michael@0 473 // reverse which radius is major and minor
michael@0 474 if (mOrientations[index] < 0) {
michael@0 475 mOrientations[index] += 90;
michael@0 476 mPointRadii[index] = new Point((int)event.getToolMajor(eventIndex)/2,
michael@0 477 (int)event.getToolMinor(eventIndex)/2);
michael@0 478 } else {
michael@0 479 mPointRadii[index] = new Point((int)event.getToolMinor(eventIndex)/2,
michael@0 480 (int)event.getToolMajor(eventIndex)/2);
michael@0 481 }
michael@0 482 } else {
michael@0 483 float size = event.getSize(eventIndex);
michael@0 484 Resources resources = GeckoAppShell.getContext().getResources();
michael@0 485 DisplayMetrics displaymetrics = resources.getDisplayMetrics();
michael@0 486 size = size*Math.min(displaymetrics.heightPixels, displaymetrics.widthPixels);
michael@0 487 mPointRadii[index] = new Point((int)size,(int)size);
michael@0 488 mOrientations[index] = 0;
michael@0 489 }
michael@0 490 if (!keepInViewCoordinates) {
michael@0 491 // If we are converting to gecko CSS pixels, then we should adjust the
michael@0 492 // radii as well
michael@0 493 float zoom = GeckoAppShell.getLayerView().getViewportMetrics().zoomFactor;
michael@0 494 mPointRadii[index].x /= zoom;
michael@0 495 mPointRadii[index].y /= zoom;
michael@0 496 }
michael@0 497 mPressures[index] = event.getPressure(eventIndex);
michael@0 498 } catch (Exception ex) {
michael@0 499 Log.e(LOGTAG, "Error creating motion point " + index, ex);
michael@0 500 mPointRadii[index] = new Point(0, 0);
michael@0 501 mPoints[index] = new Point(0, 0);
michael@0 502 }
michael@0 503 }
michael@0 504
michael@0 505 private static int HalSensorAccuracyFor(int androidAccuracy) {
michael@0 506 switch (androidAccuracy) {
michael@0 507 case SensorManager.SENSOR_STATUS_UNRELIABLE:
michael@0 508 return GeckoHalDefines.SENSOR_ACCURACY_UNRELIABLE;
michael@0 509 case SensorManager.SENSOR_STATUS_ACCURACY_LOW:
michael@0 510 return GeckoHalDefines.SENSOR_ACCURACY_LOW;
michael@0 511 case SensorManager.SENSOR_STATUS_ACCURACY_MEDIUM:
michael@0 512 return GeckoHalDefines.SENSOR_ACCURACY_MED;
michael@0 513 case SensorManager.SENSOR_STATUS_ACCURACY_HIGH:
michael@0 514 return GeckoHalDefines.SENSOR_ACCURACY_HIGH;
michael@0 515 }
michael@0 516 return GeckoHalDefines.SENSOR_ACCURACY_UNKNOWN;
michael@0 517 }
michael@0 518
michael@0 519 public static GeckoEvent createSensorEvent(SensorEvent s) {
michael@0 520 int sensor_type = s.sensor.getType();
michael@0 521 GeckoEvent event = null;
michael@0 522
michael@0 523 switch(sensor_type) {
michael@0 524
michael@0 525 case Sensor.TYPE_ACCELEROMETER:
michael@0 526 event = GeckoEvent.get(NativeGeckoEvent.SENSOR_EVENT);
michael@0 527 event.mFlags = GeckoHalDefines.SENSOR_ACCELERATION;
michael@0 528 event.mMetaState = HalSensorAccuracyFor(s.accuracy);
michael@0 529 event.mX = s.values[0];
michael@0 530 event.mY = s.values[1];
michael@0 531 event.mZ = s.values[2];
michael@0 532 break;
michael@0 533
michael@0 534 case 10 /* Requires API Level 9, so just use the raw value - Sensor.TYPE_LINEAR_ACCELEROMETER*/ :
michael@0 535 event = GeckoEvent.get(NativeGeckoEvent.SENSOR_EVENT);
michael@0 536 event.mFlags = GeckoHalDefines.SENSOR_LINEAR_ACCELERATION;
michael@0 537 event.mMetaState = HalSensorAccuracyFor(s.accuracy);
michael@0 538 event.mX = s.values[0];
michael@0 539 event.mY = s.values[1];
michael@0 540 event.mZ = s.values[2];
michael@0 541 break;
michael@0 542
michael@0 543 case Sensor.TYPE_ORIENTATION:
michael@0 544 event = GeckoEvent.get(NativeGeckoEvent.SENSOR_EVENT);
michael@0 545 event.mFlags = GeckoHalDefines.SENSOR_ORIENTATION;
michael@0 546 event.mMetaState = HalSensorAccuracyFor(s.accuracy);
michael@0 547 event.mX = s.values[0];
michael@0 548 event.mY = s.values[1];
michael@0 549 event.mZ = s.values[2];
michael@0 550 break;
michael@0 551
michael@0 552 case Sensor.TYPE_GYROSCOPE:
michael@0 553 event = GeckoEvent.get(NativeGeckoEvent.SENSOR_EVENT);
michael@0 554 event.mFlags = GeckoHalDefines.SENSOR_GYROSCOPE;
michael@0 555 event.mMetaState = HalSensorAccuracyFor(s.accuracy);
michael@0 556 event.mX = Math.toDegrees(s.values[0]);
michael@0 557 event.mY = Math.toDegrees(s.values[1]);
michael@0 558 event.mZ = Math.toDegrees(s.values[2]);
michael@0 559 break;
michael@0 560
michael@0 561 case Sensor.TYPE_PROXIMITY:
michael@0 562 event = GeckoEvent.get(NativeGeckoEvent.SENSOR_EVENT);
michael@0 563 event.mFlags = GeckoHalDefines.SENSOR_PROXIMITY;
michael@0 564 event.mMetaState = HalSensorAccuracyFor(s.accuracy);
michael@0 565 event.mX = s.values[0];
michael@0 566 event.mY = 0;
michael@0 567 event.mZ = s.sensor.getMaximumRange();
michael@0 568 break;
michael@0 569
michael@0 570 case Sensor.TYPE_LIGHT:
michael@0 571 event = GeckoEvent.get(NativeGeckoEvent.SENSOR_EVENT);
michael@0 572 event.mFlags = GeckoHalDefines.SENSOR_LIGHT;
michael@0 573 event.mMetaState = HalSensorAccuracyFor(s.accuracy);
michael@0 574 event.mX = s.values[0];
michael@0 575 break;
michael@0 576 }
michael@0 577 return event;
michael@0 578 }
michael@0 579
michael@0 580 public static GeckoEvent createLocationEvent(Location l) {
michael@0 581 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.LOCATION_EVENT);
michael@0 582 event.mLocation = l;
michael@0 583 return event;
michael@0 584 }
michael@0 585
michael@0 586 public static GeckoEvent createIMEEvent(ImeAction action) {
michael@0 587 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.IME_EVENT);
michael@0 588 event.mAction = action.value;
michael@0 589 return event;
michael@0 590 }
michael@0 591
michael@0 592 public static GeckoEvent createIMEKeyEvent(KeyEvent k) {
michael@0 593 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.IME_KEY_EVENT);
michael@0 594 event.initKeyEvent(k, 0);
michael@0 595 return event;
michael@0 596 }
michael@0 597
michael@0 598 public static GeckoEvent createIMEReplaceEvent(int start, int end,
michael@0 599 String text) {
michael@0 600 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.IME_EVENT);
michael@0 601 event.mAction = ImeAction.IME_REPLACE_TEXT.value;
michael@0 602 event.mStart = start;
michael@0 603 event.mEnd = end;
michael@0 604 event.mCharacters = text;
michael@0 605 return event;
michael@0 606 }
michael@0 607
michael@0 608 public static GeckoEvent createIMESelectEvent(int start, int end) {
michael@0 609 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.IME_EVENT);
michael@0 610 event.mAction = ImeAction.IME_SET_SELECTION.value;
michael@0 611 event.mStart = start;
michael@0 612 event.mEnd = end;
michael@0 613 return event;
michael@0 614 }
michael@0 615
michael@0 616 public static GeckoEvent createIMECompositionEvent(int start, int end) {
michael@0 617 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.IME_EVENT);
michael@0 618 event.mAction = ImeAction.IME_UPDATE_COMPOSITION.value;
michael@0 619 event.mStart = start;
michael@0 620 event.mEnd = end;
michael@0 621 return event;
michael@0 622 }
michael@0 623
michael@0 624 public static GeckoEvent createIMERangeEvent(int start,
michael@0 625 int end, int rangeType,
michael@0 626 int rangeStyles,
michael@0 627 int rangeLineStyle,
michael@0 628 boolean rangeBoldLine,
michael@0 629 int rangeForeColor,
michael@0 630 int rangeBackColor,
michael@0 631 int rangeLineColor) {
michael@0 632 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.IME_EVENT);
michael@0 633 event.mAction = ImeAction.IME_ADD_COMPOSITION_RANGE.value;
michael@0 634 event.mStart = start;
michael@0 635 event.mEnd = end;
michael@0 636 event.mRangeType = rangeType;
michael@0 637 event.mRangeStyles = rangeStyles;
michael@0 638 event.mRangeLineStyle = rangeLineStyle;
michael@0 639 event.mRangeBoldLine = rangeBoldLine;
michael@0 640 event.mRangeForeColor = rangeForeColor;
michael@0 641 event.mRangeBackColor = rangeBackColor;
michael@0 642 event.mRangeLineColor = rangeLineColor;
michael@0 643 return event;
michael@0 644 }
michael@0 645
michael@0 646 public static GeckoEvent createDrawEvent(Rect rect) {
michael@0 647 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.DRAW);
michael@0 648 event.mRect = rect;
michael@0 649 return event;
michael@0 650 }
michael@0 651
michael@0 652 public static GeckoEvent createSizeChangedEvent(int w, int h, int screenw, int screenh) {
michael@0 653 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.SIZE_CHANGED);
michael@0 654 event.mPoints = new Point[2];
michael@0 655 event.mPoints[0] = new Point(w, h);
michael@0 656 event.mPoints[1] = new Point(screenw, screenh);
michael@0 657 return event;
michael@0 658 }
michael@0 659
michael@0 660 @RobocopTarget
michael@0 661 public static GeckoEvent createBroadcastEvent(String subject, String data) {
michael@0 662 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.BROADCAST);
michael@0 663 event.mCharacters = subject;
michael@0 664 event.mCharactersExtra = data;
michael@0 665 return event;
michael@0 666 }
michael@0 667
michael@0 668 public static GeckoEvent createViewportEvent(ImmutableViewportMetrics metrics, DisplayPortMetrics displayPort) {
michael@0 669 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.VIEWPORT);
michael@0 670 event.mCharacters = "Viewport:Change";
michael@0 671 StringBuilder sb = new StringBuilder(256);
michael@0 672 sb.append("{ \"x\" : ").append(metrics.viewportRectLeft)
michael@0 673 .append(", \"y\" : ").append(metrics.viewportRectTop)
michael@0 674 .append(", \"zoom\" : ").append(metrics.zoomFactor)
michael@0 675 .append(", \"fixedMarginLeft\" : ").append(metrics.marginLeft)
michael@0 676 .append(", \"fixedMarginTop\" : ").append(metrics.marginTop)
michael@0 677 .append(", \"fixedMarginRight\" : ").append(metrics.marginRight)
michael@0 678 .append(", \"fixedMarginBottom\" : ").append(metrics.marginBottom)
michael@0 679 .append(", \"displayPort\" :").append(displayPort.toJSON())
michael@0 680 .append('}');
michael@0 681 event.mCharactersExtra = sb.toString();
michael@0 682 return event;
michael@0 683 }
michael@0 684
michael@0 685 public static GeckoEvent createURILoadEvent(String uri) {
michael@0 686 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.LOAD_URI);
michael@0 687 event.mCharacters = uri;
michael@0 688 event.mCharactersExtra = "";
michael@0 689 return event;
michael@0 690 }
michael@0 691
michael@0 692 public static GeckoEvent createWebappLoadEvent(String uri) {
michael@0 693 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.LOAD_URI);
michael@0 694 event.mCharacters = uri;
michael@0 695 event.mCharactersExtra = "-webapp";
michael@0 696 return event;
michael@0 697 }
michael@0 698
michael@0 699 public static GeckoEvent createBookmarkLoadEvent(String uri) {
michael@0 700 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.LOAD_URI);
michael@0 701 event.mCharacters = uri;
michael@0 702 event.mCharactersExtra = "-bookmark";
michael@0 703 return event;
michael@0 704 }
michael@0 705
michael@0 706 public static GeckoEvent createVisitedEvent(String data) {
michael@0 707 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.VISITED);
michael@0 708 event.mCharacters = data;
michael@0 709 return event;
michael@0 710 }
michael@0 711
michael@0 712 public static GeckoEvent createNetworkEvent(int connectionType, boolean isWifi, int DHCPGateway) {
michael@0 713 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.NETWORK_CHANGED);
michael@0 714 event.mConnectionType = connectionType;
michael@0 715 event.mIsWifi = isWifi;
michael@0 716 event.mDHCPGateway = DHCPGateway;
michael@0 717 return event;
michael@0 718 }
michael@0 719
michael@0 720 public static GeckoEvent createThumbnailEvent(int tabId, int bufw, int bufh, ByteBuffer buffer) {
michael@0 721 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.THUMBNAIL);
michael@0 722 event.mPoints = new Point[1];
michael@0 723 event.mPoints[0] = new Point(bufw, bufh);
michael@0 724 event.mMetaState = tabId;
michael@0 725 event.mBuffer = buffer;
michael@0 726 return event;
michael@0 727 }
michael@0 728
michael@0 729 public static GeckoEvent createScreenOrientationEvent(short aScreenOrientation) {
michael@0 730 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.SCREENORIENTATION_CHANGED);
michael@0 731 event.mScreenOrientation = aScreenOrientation;
michael@0 732 return event;
michael@0 733 }
michael@0 734
michael@0 735 public static GeckoEvent createCallObserverEvent(String observerKey, String topic, String data) {
michael@0 736 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.CALL_OBSERVER);
michael@0 737 event.mCharacters = observerKey;
michael@0 738 event.mCharactersExtra = topic;
michael@0 739 event.mData = data;
michael@0 740 return event;
michael@0 741 }
michael@0 742
michael@0 743 public static GeckoEvent createRemoveObserverEvent(String observerKey) {
michael@0 744 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.REMOVE_OBSERVER);
michael@0 745 event.mCharacters = observerKey;
michael@0 746 return event;
michael@0 747 }
michael@0 748
michael@0 749 @RobocopTarget
michael@0 750 public static GeckoEvent createPreferencesObserveEvent(int requestId, String[] prefNames) {
michael@0 751 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.PREFERENCES_OBSERVE);
michael@0 752 event.mCount = requestId;
michael@0 753 event.mPrefNames = prefNames;
michael@0 754 return event;
michael@0 755 }
michael@0 756
michael@0 757 @RobocopTarget
michael@0 758 public static GeckoEvent createPreferencesGetEvent(int requestId, String[] prefNames) {
michael@0 759 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.PREFERENCES_GET);
michael@0 760 event.mCount = requestId;
michael@0 761 event.mPrefNames = prefNames;
michael@0 762 return event;
michael@0 763 }
michael@0 764
michael@0 765 @RobocopTarget
michael@0 766 public static GeckoEvent createPreferencesRemoveObserversEvent(int requestId) {
michael@0 767 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.PREFERENCES_REMOVE_OBSERVERS);
michael@0 768 event.mCount = requestId;
michael@0 769 return event;
michael@0 770 }
michael@0 771
michael@0 772 public static GeckoEvent createLowMemoryEvent(int level) {
michael@0 773 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.LOW_MEMORY);
michael@0 774 event.mMetaState = level;
michael@0 775 return event;
michael@0 776 }
michael@0 777
michael@0 778 public static GeckoEvent createNetworkLinkChangeEvent(String status) {
michael@0 779 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.NETWORK_LINK_CHANGE);
michael@0 780 event.mCharacters = status;
michael@0 781 return event;
michael@0 782 }
michael@0 783
michael@0 784 public static GeckoEvent createTelemetryHistogramAddEvent(String histogram,
michael@0 785 int value) {
michael@0 786 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.TELEMETRY_HISTOGRAM_ADD);
michael@0 787 event.mCharacters = histogram;
michael@0 788 event.mCount = value;
michael@0 789 return event;
michael@0 790 }
michael@0 791
michael@0 792 public static GeckoEvent createTelemetryUISessionStartEvent(String session, long timestamp) {
michael@0 793 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.TELEMETRY_UI_SESSION_START);
michael@0 794 event.mCharacters = session;
michael@0 795 event.mTime = timestamp;
michael@0 796 return event;
michael@0 797 }
michael@0 798
michael@0 799 public static GeckoEvent createTelemetryUISessionStopEvent(String session, String reason, long timestamp) {
michael@0 800 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.TELEMETRY_UI_SESSION_STOP);
michael@0 801 event.mCharacters = session;
michael@0 802 event.mCharactersExtra = reason;
michael@0 803 event.mTime = timestamp;
michael@0 804 return event;
michael@0 805 }
michael@0 806
michael@0 807 public static GeckoEvent createTelemetryUIEvent(String action, String method, long timestamp, String extras) {
michael@0 808 GeckoEvent event = GeckoEvent.get(NativeGeckoEvent.TELEMETRY_UI_EVENT);
michael@0 809 event.mData = action;
michael@0 810 event.mCharacters = method;
michael@0 811 event.mCharactersExtra = extras;
michael@0 812 event.mTime = timestamp;
michael@0 813 return event;
michael@0 814 }
michael@0 815
michael@0 816 public void setAckNeeded(boolean ackNeeded) {
michael@0 817 mAckNeeded = ackNeeded;
michael@0 818 }
michael@0 819 }

mercurial