Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "AndroidJavaWrappers.h"
7 #include "AndroidBridge.h"
8 #include "AndroidBridgeUtilities.h"
9 #include "nsIDOMKeyEvent.h"
10 #include "nsIWidget.h"
11 #include "mozilla/BasicEvents.h"
12 #include "mozilla/TouchEvents.h"
14 using namespace mozilla;
15 using namespace mozilla::dom;
16 using namespace mozilla::widget::android;
18 jclass AndroidGeckoEvent::jGeckoEventClass = 0;
19 jfieldID AndroidGeckoEvent::jActionField = 0;
20 jfieldID AndroidGeckoEvent::jTypeField = 0;
21 jfieldID AndroidGeckoEvent::jAckNeededField = 0;
22 jfieldID AndroidGeckoEvent::jTimeField = 0;
23 jfieldID AndroidGeckoEvent::jPoints = 0;
24 jfieldID AndroidGeckoEvent::jPointIndicies = 0;
25 jfieldID AndroidGeckoEvent::jPressures = 0;
26 jfieldID AndroidGeckoEvent::jPointRadii = 0;
27 jfieldID AndroidGeckoEvent::jOrientations = 0;
28 jfieldID AndroidGeckoEvent::jXField = 0;
29 jfieldID AndroidGeckoEvent::jYField = 0;
30 jfieldID AndroidGeckoEvent::jZField = 0;
31 jfieldID AndroidGeckoEvent::jDistanceField = 0;
32 jfieldID AndroidGeckoEvent::jRectField = 0;
33 jfieldID AndroidGeckoEvent::jNativeWindowField = 0;
35 jfieldID AndroidGeckoEvent::jCharactersField = 0;
36 jfieldID AndroidGeckoEvent::jCharactersExtraField = 0;
37 jfieldID AndroidGeckoEvent::jDataField = 0;
38 jfieldID AndroidGeckoEvent::jDOMPrintableKeyValueField = 0;
39 jfieldID AndroidGeckoEvent::jKeyCodeField = 0;
40 jfieldID AndroidGeckoEvent::jMetaStateField = 0;
41 jfieldID AndroidGeckoEvent::jDomKeyLocationField = 0;
42 jfieldID AndroidGeckoEvent::jFlagsField = 0;
43 jfieldID AndroidGeckoEvent::jUnicodeCharField = 0;
44 jfieldID AndroidGeckoEvent::jBaseUnicodeCharField = 0;
45 jfieldID AndroidGeckoEvent::jRepeatCountField = 0;
46 jfieldID AndroidGeckoEvent::jCountField = 0;
47 jfieldID AndroidGeckoEvent::jStartField = 0;
48 jfieldID AndroidGeckoEvent::jEndField = 0;
49 jfieldID AndroidGeckoEvent::jPointerIndexField = 0;
50 jfieldID AndroidGeckoEvent::jRangeTypeField = 0;
51 jfieldID AndroidGeckoEvent::jRangeStylesField = 0;
52 jfieldID AndroidGeckoEvent::jRangeLineStyleField = 0;
53 jfieldID AndroidGeckoEvent::jRangeBoldLineField = 0;
54 jfieldID AndroidGeckoEvent::jRangeForeColorField = 0;
55 jfieldID AndroidGeckoEvent::jRangeBackColorField = 0;
56 jfieldID AndroidGeckoEvent::jRangeLineColorField = 0;
57 jfieldID AndroidGeckoEvent::jLocationField = 0;
58 jfieldID AndroidGeckoEvent::jConnectionTypeField = 0;
59 jfieldID AndroidGeckoEvent::jIsWifiField = 0;
60 jfieldID AndroidGeckoEvent::jDHCPGatewayField = 0;
61 jfieldID AndroidGeckoEvent::jScreenOrientationField = 0;
62 jfieldID AndroidGeckoEvent::jByteBufferField = 0;
63 jfieldID AndroidGeckoEvent::jWidthField = 0;
64 jfieldID AndroidGeckoEvent::jHeightField = 0;
65 jfieldID AndroidGeckoEvent::jPrefNamesField = 0;
67 jclass AndroidGeckoEvent::jDomKeyLocationClass = 0;
68 jfieldID AndroidGeckoEvent::jDomKeyLocationValueField = 0;
70 jclass AndroidPoint::jPointClass = 0;
71 jfieldID AndroidPoint::jXField = 0;
72 jfieldID AndroidPoint::jYField = 0;
74 jclass AndroidRect::jRectClass = 0;
75 jfieldID AndroidRect::jBottomField = 0;
76 jfieldID AndroidRect::jLeftField = 0;
77 jfieldID AndroidRect::jRightField = 0;
78 jfieldID AndroidRect::jTopField = 0;
80 jclass AndroidRectF::jRectClass = 0;
81 jfieldID AndroidRectF::jBottomField = 0;
82 jfieldID AndroidRectF::jLeftField = 0;
83 jfieldID AndroidRectF::jRightField = 0;
84 jfieldID AndroidRectF::jTopField = 0;
86 jclass AndroidLocation::jLocationClass = 0;
87 jmethodID AndroidLocation::jGetLatitudeMethod = 0;
88 jmethodID AndroidLocation::jGetLongitudeMethod = 0;
89 jmethodID AndroidLocation::jGetAltitudeMethod = 0;
90 jmethodID AndroidLocation::jGetAccuracyMethod = 0;
91 jmethodID AndroidLocation::jGetBearingMethod = 0;
92 jmethodID AndroidLocation::jGetSpeedMethod = 0;
93 jmethodID AndroidLocation::jGetTimeMethod = 0;
95 jclass AndroidLayerRendererFrame::jLayerRendererFrameClass = 0;
96 jmethodID AndroidLayerRendererFrame::jBeginDrawingMethod = 0;
97 jmethodID AndroidLayerRendererFrame::jDrawBackgroundMethod = 0;
98 jmethodID AndroidLayerRendererFrame::jDrawForegroundMethod = 0;
99 jmethodID AndroidLayerRendererFrame::jEndDrawingMethod = 0;
101 RefCountedJavaObject::~RefCountedJavaObject() {
102 if (mObject)
103 GetJNIForThread()->DeleteGlobalRef(mObject);
104 mObject = nullptr;
105 }
107 void
108 mozilla::InitAndroidJavaWrappers(JNIEnv *jEnv)
109 {
110 AndroidGeckoEvent::InitGeckoEventClass(jEnv);
111 AndroidPoint::InitPointClass(jEnv);
112 AndroidLocation::InitLocationClass(jEnv);
113 AndroidRect::InitRectClass(jEnv);
114 AndroidRectF::InitRectFClass(jEnv);
115 AndroidLayerRendererFrame::InitLayerRendererFrameClass(jEnv);
116 InitStubs(jEnv);
117 }
119 void
120 AndroidGeckoEvent::InitGeckoEventClass(JNIEnv *jEnv)
121 {
122 initInit();
124 jGeckoEventClass = getClassGlobalRef("org/mozilla/gecko/GeckoEvent");
126 jActionField = getField("mAction", "I");
127 jTypeField = getField("mType", "I");
128 jAckNeededField = getField("mAckNeeded", "Z");
129 jTimeField = getField("mTime", "J");
130 jPoints = getField("mPoints", "[Landroid/graphics/Point;");
131 jPointIndicies = getField("mPointIndicies", "[I");
132 jOrientations = getField("mOrientations", "[F");
133 jPressures = getField("mPressures", "[F");
134 jPointRadii = getField("mPointRadii", "[Landroid/graphics/Point;");
135 jXField = getField("mX", "D");
136 jYField = getField("mY", "D");
137 jZField = getField("mZ", "D");
138 jRectField = getField("mRect", "Landroid/graphics/Rect;");
140 jCharactersField = getField("mCharacters", "Ljava/lang/String;");
141 jCharactersExtraField = getField("mCharactersExtra", "Ljava/lang/String;");
142 jDataField = getField("mData", "Ljava/lang/String;");
143 jKeyCodeField = getField("mKeyCode", "I");
144 jMetaStateField = getField("mMetaState", "I");
145 jDomKeyLocationField = getField("mDomKeyLocation", "Lorg/mozilla/gecko/GeckoEvent$DomKeyLocation;");
146 jFlagsField = getField("mFlags", "I");
147 jUnicodeCharField = getField("mUnicodeChar", "I");
148 jBaseUnicodeCharField = getField("mBaseUnicodeChar", "I");
149 jDOMPrintableKeyValueField = getField("mDOMPrintableKeyValue", "I");
150 jRepeatCountField = getField("mRepeatCount", "I");
151 jCountField = getField("mCount", "I");
152 jStartField = getField("mStart", "I");
153 jEndField = getField("mEnd", "I");
154 jPointerIndexField = getField("mPointerIndex", "I");
155 jRangeTypeField = getField("mRangeType", "I");
156 jRangeStylesField = getField("mRangeStyles", "I");
157 jRangeLineStyleField = getField("mRangeLineStyle", "I");
158 jRangeBoldLineField = getField("mRangeBoldLine", "Z");
159 jRangeForeColorField = getField("mRangeForeColor", "I");
160 jRangeBackColorField = getField("mRangeBackColor", "I");
161 jRangeLineColorField = getField("mRangeLineColor", "I");
162 jLocationField = getField("mLocation", "Landroid/location/Location;");
163 jConnectionTypeField = getField("mConnectionType", "I");
164 jIsWifiField = getField("mIsWifi", "Z");
165 jDHCPGatewayField = getField("mDHCPGateway", "I");
166 jScreenOrientationField = getField("mScreenOrientation", "S");
167 jByteBufferField = getField("mBuffer", "Ljava/nio/ByteBuffer;");
168 jWidthField = getField("mWidth", "I");
169 jHeightField = getField("mHeight", "I");
170 jPrefNamesField = getField("mPrefNames", "[Ljava/lang/String;");
172 // Init GeckoEvent.DomKeyLocation enum
173 jDomKeyLocationClass = getClassGlobalRef("org/mozilla/gecko/GeckoEvent$DomKeyLocation");
174 jDomKeyLocationValueField = getField("value", "I");
175 }
177 void
178 AndroidLocation::InitLocationClass(JNIEnv *jEnv)
179 {
180 initInit();
182 jLocationClass = getClassGlobalRef("android/location/Location");
183 jGetLatitudeMethod = getMethod("getLatitude", "()D");
184 jGetLongitudeMethod = getMethod("getLongitude", "()D");
185 jGetAltitudeMethod = getMethod("getAltitude", "()D");
186 jGetAccuracyMethod = getMethod("getAccuracy", "()F");
187 jGetBearingMethod = getMethod("getBearing", "()F");
188 jGetSpeedMethod = getMethod("getSpeed", "()F");
189 jGetTimeMethod = getMethod("getTime", "()J");
190 }
192 nsGeoPosition*
193 AndroidLocation::CreateGeoPosition(JNIEnv *jenv, jobject jobj)
194 {
195 AutoLocalJNIFrame jniFrame(jenv);
197 double latitude = jenv->CallDoubleMethod(jobj, jGetLatitudeMethod);
198 if (jniFrame.CheckForException()) return nullptr;
199 double longitude = jenv->CallDoubleMethod(jobj, jGetLongitudeMethod);
200 if (jniFrame.CheckForException()) return nullptr;
201 double altitude = jenv->CallDoubleMethod(jobj, jGetAltitudeMethod);
202 if (jniFrame.CheckForException()) return nullptr;
203 float accuracy = jenv->CallFloatMethod (jobj, jGetAccuracyMethod);
204 if (jniFrame.CheckForException()) return nullptr;
205 float bearing = jenv->CallFloatMethod (jobj, jGetBearingMethod);
206 if (jniFrame.CheckForException()) return nullptr;
207 float speed = jenv->CallFloatMethod (jobj, jGetSpeedMethod);
208 if (jniFrame.CheckForException()) return nullptr;
209 long long time = jenv->CallLongMethod (jobj, jGetTimeMethod);
210 if (jniFrame.CheckForException()) return nullptr;
212 return new nsGeoPosition(latitude, longitude,
213 altitude, accuracy,
214 accuracy, bearing,
215 speed, time);
216 }
218 void
219 AndroidPoint::InitPointClass(JNIEnv *jEnv)
220 {
221 initInit();
223 jPointClass = getClassGlobalRef("android/graphics/Point");
225 jXField = getField("x", "I");
226 jYField = getField("y", "I");
227 }
229 void
230 AndroidRect::InitRectClass(JNIEnv *jEnv)
231 {
232 initInit();
234 jRectClass = getClassGlobalRef("android/graphics/Rect");
236 jBottomField = getField("bottom", "I");
237 jLeftField = getField("left", "I");
238 jTopField = getField("top", "I");
239 jRightField = getField("right", "I");
240 }
242 void
243 AndroidRectF::InitRectFClass(JNIEnv *jEnv)
244 {
245 initInit();
247 jRectClass = getClassGlobalRef("android/graphics/RectF");
249 jBottomField = getField("bottom", "F");
250 jLeftField = getField("left", "F");
251 jTopField = getField("top", "F");
252 jRightField = getField("right", "F");
253 }
255 void
256 AndroidLayerRendererFrame::InitLayerRendererFrameClass(JNIEnv *jEnv)
257 {
258 initInit();
260 jLayerRendererFrameClass = getClassGlobalRef("org/mozilla/gecko/gfx/LayerRenderer$Frame");
262 jBeginDrawingMethod = getMethod("beginDrawing", "()V");
263 jDrawBackgroundMethod = getMethod("drawBackground", "()V");
264 jDrawForegroundMethod = getMethod("drawForeground", "()V");
265 jEndDrawingMethod = getMethod("endDrawing", "()V");
266 }
268 #undef initInit
269 #undef initClassGlobalRef
270 #undef getField
271 #undef getMethod
273 void
274 AndroidGeckoEvent::ReadPointArray(nsTArray<nsIntPoint> &points,
275 JNIEnv *jenv,
276 jfieldID field,
277 int32_t count)
278 {
279 jobjectArray jObjArray = (jobjectArray)jenv->GetObjectField(wrapped_obj, field);
280 for (int32_t i = 0; i < count; i++) {
281 jobject jObj = jenv->GetObjectArrayElement(jObjArray, i);
282 AndroidPoint jpoint(jenv, jObj);
284 nsIntPoint p(jpoint.X(), jpoint.Y());
285 points.AppendElement(p);
286 }
287 }
289 void
290 AndroidGeckoEvent::ReadIntArray(nsTArray<int> &aVals,
291 JNIEnv *jenv,
292 jfieldID field,
293 int32_t count)
294 {
295 jintArray jIntArray = (jintArray)jenv->GetObjectField(wrapped_obj, field);
296 jint *vals = jenv->GetIntArrayElements(jIntArray, nullptr);
297 for (int32_t i = 0; i < count; i++) {
298 aVals.AppendElement(vals[i]);
299 }
300 jenv->ReleaseIntArrayElements(jIntArray, vals, JNI_ABORT);
301 }
303 void
304 AndroidGeckoEvent::ReadFloatArray(nsTArray<float> &aVals,
305 JNIEnv *jenv,
306 jfieldID field,
307 int32_t count)
308 {
309 jfloatArray jFloatArray = (jfloatArray)jenv->GetObjectField(wrapped_obj, field);
310 jfloat *vals = jenv->GetFloatArrayElements(jFloatArray, nullptr);
311 for (int32_t i = 0; i < count; i++) {
312 aVals.AppendElement(vals[i]);
313 }
314 jenv->ReleaseFloatArrayElements(jFloatArray, vals, JNI_ABORT);
315 }
317 void
318 AndroidGeckoEvent::ReadStringArray(nsTArray<nsString> &array,
319 JNIEnv *jenv,
320 jfieldID field)
321 {
322 jarray jArray = (jarray)jenv->GetObjectField(wrapped_obj, field);
323 jsize length = jenv->GetArrayLength(jArray);
324 jobjectArray jStringArray = (jobjectArray)jArray;
325 nsString *strings = array.AppendElements(length);
326 for (jsize i = 0; i < length; ++i) {
327 jstring javastring = (jstring) jenv->GetObjectArrayElement(jStringArray, i);
328 ReadStringFromJString(strings[i], jenv, javastring);
329 }
330 }
332 void
333 AndroidGeckoEvent::ReadRectField(JNIEnv *jenv)
334 {
335 AndroidRect r(jenv, jenv->GetObjectField(wrappedObject(), jRectField));
336 if (!r.isNull()) {
337 mRect.SetRect(r.Left(),
338 r.Top(),
339 r.Width(),
340 r.Height());
341 } else {
342 mRect.SetEmpty();
343 }
344 }
346 void
347 AndroidGeckoEvent::ReadStringFromJString(nsString &aString, JNIEnv *jenv,
348 jstring s)
349 {
350 if (!s) {
351 aString.SetIsVoid(true);
352 return;
353 }
355 int len = jenv->GetStringLength(s);
356 aString.SetLength(len);
357 jenv->GetStringRegion(s, 0, len, reinterpret_cast<jchar*>(aString.BeginWriting()));
358 }
360 void
361 AndroidGeckoEvent::ReadCharactersField(JNIEnv *jenv)
362 {
363 jstring s = (jstring) jenv->GetObjectField(wrapped_obj, jCharactersField);
364 ReadStringFromJString(mCharacters, jenv, s);
365 }
367 void
368 AndroidGeckoEvent::ReadCharactersExtraField(JNIEnv *jenv)
369 {
370 jstring s = (jstring) jenv->GetObjectField(wrapped_obj, jCharactersExtraField);
371 ReadStringFromJString(mCharactersExtra, jenv, s);
372 }
374 void
375 AndroidGeckoEvent::ReadDataField(JNIEnv *jenv)
376 {
377 jstring s = (jstring) jenv->GetObjectField(wrapped_obj, jDataField);
378 ReadStringFromJString(mData, jenv, s);
379 }
381 void
382 AndroidGeckoEvent::UnionRect(nsIntRect const& aRect)
383 {
384 mRect = aRect.Union(mRect);
385 }
387 uint32_t
388 AndroidGeckoEvent::ReadDomKeyLocation(JNIEnv* jenv, jobject jGeckoEventObj)
389 {
390 jobject enumObject = jenv->GetObjectField(jGeckoEventObj,
391 jDomKeyLocationField);
392 MOZ_ASSERT(enumObject);
393 int enumValue = jenv->GetIntField(enumObject, jDomKeyLocationValueField);
394 MOZ_ASSERT(enumValue >= nsIDOMKeyEvent::DOM_KEY_LOCATION_STANDARD &&
395 enumValue <= nsIDOMKeyEvent::DOM_KEY_LOCATION_JOYSTICK);
396 return static_cast<uint32_t>(enumValue);
397 }
399 void
400 AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj)
401 {
402 NS_ASSERTION(!wrapped_obj, "Init called on non-null wrapped_obj!");
404 wrapped_obj = jobj;
406 if (!jobj)
407 return;
409 mAction = jenv->GetIntField(jobj, jActionField);
410 mType = jenv->GetIntField(jobj, jTypeField);
411 mAckNeeded = jenv->GetBooleanField(jobj, jAckNeededField);
413 switch (mType) {
414 case SIZE_CHANGED:
415 ReadPointArray(mPoints, jenv, jPoints, 2);
416 break;
418 case KEY_EVENT:
419 case IME_KEY_EVENT:
420 mTime = jenv->GetLongField(jobj, jTimeField);
421 mMetaState = jenv->GetIntField(jobj, jMetaStateField);
422 mDomKeyLocation = ReadDomKeyLocation(jenv, jobj);
423 mFlags = jenv->GetIntField(jobj, jFlagsField);
424 mKeyCode = jenv->GetIntField(jobj, jKeyCodeField);
425 mUnicodeChar = jenv->GetIntField(jobj, jUnicodeCharField);
426 mBaseUnicodeChar = jenv->GetIntField(jobj, jBaseUnicodeCharField);
427 mDOMPrintableKeyValue =
428 jenv->GetIntField(jobj, jDOMPrintableKeyValueField);
429 mRepeatCount = jenv->GetIntField(jobj, jRepeatCountField);
430 ReadCharactersField(jenv);
431 break;
433 case NATIVE_GESTURE_EVENT:
434 mTime = jenv->GetLongField(jobj, jTimeField);
435 mMetaState = jenv->GetIntField(jobj, jMetaStateField);
436 mCount = jenv->GetIntField(jobj, jCountField);
437 ReadPointArray(mPoints, jenv, jPoints, mCount);
438 mX = jenv->GetDoubleField(jobj, jXField);
440 break;
442 case MOTION_EVENT:
443 mTime = jenv->GetLongField(jobj, jTimeField);
444 mMetaState = jenv->GetIntField(jobj, jMetaStateField);
445 mCount = jenv->GetIntField(jobj, jCountField);
446 mPointerIndex = jenv->GetIntField(jobj, jPointerIndexField);
448 ReadPointArray(mPointRadii, jenv, jPointRadii, mCount);
449 ReadFloatArray(mOrientations, jenv, jOrientations, mCount);
450 ReadFloatArray(mPressures, jenv, jPressures, mCount);
451 ReadPointArray(mPoints, jenv, jPoints, mCount);
452 ReadIntArray(mPointIndicies, jenv, jPointIndicies, mCount);
454 break;
456 case IME_EVENT:
457 mStart = jenv->GetIntField(jobj, jStartField);
458 mEnd = jenv->GetIntField(jobj, jEndField);
460 if (mAction == IME_REPLACE_TEXT) {
461 ReadCharactersField(jenv);
462 } else if (mAction == IME_UPDATE_COMPOSITION ||
463 mAction == IME_ADD_COMPOSITION_RANGE) {
464 mRangeType = jenv->GetIntField(jobj, jRangeTypeField);
465 mRangeStyles = jenv->GetIntField(jobj, jRangeStylesField);
466 mRangeLineStyle =
467 jenv->GetIntField(jobj, jRangeLineStyleField);
468 mRangeBoldLine =
469 jenv->GetBooleanField(jobj, jRangeBoldLineField);
470 mRangeForeColor =
471 jenv->GetIntField(jobj, jRangeForeColorField);
472 mRangeBackColor =
473 jenv->GetIntField(jobj, jRangeBackColorField);
474 mRangeLineColor =
475 jenv->GetIntField(jobj, jRangeLineColorField);
476 }
477 break;
479 case DRAW:
480 ReadRectField(jenv);
481 break;
483 case SENSOR_EVENT:
484 mX = jenv->GetDoubleField(jobj, jXField);
485 mY = jenv->GetDoubleField(jobj, jYField);
486 mZ = jenv->GetDoubleField(jobj, jZField);
487 mFlags = jenv->GetIntField(jobj, jFlagsField);
488 mMetaState = jenv->GetIntField(jobj, jMetaStateField);
489 break;
491 case LOCATION_EVENT: {
492 jobject location = jenv->GetObjectField(jobj, jLocationField);
493 mGeoPosition = AndroidLocation::CreateGeoPosition(jenv, location);
494 break;
495 }
497 case LOAD_URI: {
498 ReadCharactersField(jenv);
499 ReadCharactersExtraField(jenv);
500 break;
501 }
503 case VIEWPORT:
504 case BROADCAST: {
505 ReadCharactersField(jenv);
506 ReadCharactersExtraField(jenv);
507 break;
508 }
510 case NETWORK_CHANGED: {
511 mConnectionType = jenv->GetIntField(jobj, jConnectionTypeField);
512 mIsWifi = jenv->GetBooleanField(jobj, jIsWifiField);
513 mDHCPGateway = jenv->GetIntField(jobj, jDHCPGatewayField);
514 break;
515 }
517 case VISITED: {
518 ReadCharactersField(jenv);
519 break;
520 }
522 case THUMBNAIL: {
523 mMetaState = jenv->GetIntField(jobj, jMetaStateField);
524 ReadPointArray(mPoints, jenv, jPoints, 1);
525 mByteBuffer = new RefCountedJavaObject(jenv, jenv->GetObjectField(jobj, jByteBufferField));
526 break;
527 }
529 case SCREENORIENTATION_CHANGED: {
530 mScreenOrientation = jenv->GetShortField(jobj, jScreenOrientationField);
531 break;
532 }
534 case COMPOSITOR_CREATE: {
535 mWidth = jenv->GetIntField(jobj, jWidthField);
536 mHeight = jenv->GetIntField(jobj, jHeightField);
537 break;
538 }
540 case CALL_OBSERVER: {
541 ReadCharactersField(jenv);
542 ReadCharactersExtraField(jenv);
543 ReadDataField(jenv);
544 break;
545 }
547 case REMOVE_OBSERVER: {
548 ReadCharactersField(jenv);
549 break;
550 }
552 case LOW_MEMORY: {
553 mMetaState = jenv->GetIntField(jobj, jMetaStateField);
554 break;
555 }
557 case NETWORK_LINK_CHANGE: {
558 ReadCharactersField(jenv);
559 break;
560 }
562 case TELEMETRY_HISTOGRAM_ADD: {
563 ReadCharactersField(jenv);
564 mCount = jenv->GetIntField(jobj, jCountField);
565 break;
566 }
568 case TELEMETRY_UI_SESSION_START: {
569 ReadCharactersField(jenv);
570 mTime = jenv->GetLongField(jobj, jTimeField);
571 break;
572 }
574 case TELEMETRY_UI_SESSION_STOP: {
575 ReadCharactersField(jenv);
576 ReadCharactersExtraField(jenv);
577 mTime = jenv->GetLongField(jobj, jTimeField);
578 break;
579 }
581 case TELEMETRY_UI_EVENT: {
582 ReadCharactersField(jenv);
583 ReadCharactersExtraField(jenv);
584 ReadDataField(jenv);
585 mTime = jenv->GetLongField(jobj, jTimeField);
586 break;
587 }
589 case PREFERENCES_OBSERVE:
590 case PREFERENCES_GET: {
591 ReadStringArray(mPrefNames, jenv, jPrefNamesField);
592 mCount = jenv->GetIntField(jobj, jCountField);
593 break;
594 }
596 case PREFERENCES_REMOVE_OBSERVERS: {
597 mCount = jenv->GetIntField(jobj, jCountField);
598 break;
599 }
601 default:
602 break;
603 }
605 #ifdef DEBUG_ANDROID_EVENTS
606 ALOG("AndroidGeckoEvent: %p : %d", (void*)jobj, mType);
607 #endif
608 }
610 void
611 AndroidGeckoEvent::Init(int aType)
612 {
613 mType = aType;
614 mAckNeeded = false;
615 }
617 void
618 AndroidGeckoEvent::Init(AndroidGeckoEvent *aResizeEvent)
619 {
620 NS_ASSERTION(aResizeEvent->Type() == SIZE_CHANGED, "Init called on non-SIZE_CHANGED event");
622 mType = FORCED_RESIZE;
623 mAckNeeded = false;
624 mTime = aResizeEvent->mTime;
625 mPoints = aResizeEvent->mPoints; // x,y coordinates
626 }
628 WidgetTouchEvent
629 AndroidGeckoEvent::MakeTouchEvent(nsIWidget* widget)
630 {
631 int type = NS_EVENT_NULL;
632 int startIndex = 0;
633 int endIndex = Count();
635 switch (Action()) {
636 case AndroidMotionEvent::ACTION_DOWN:
637 case AndroidMotionEvent::ACTION_POINTER_DOWN: {
638 type = NS_TOUCH_START;
639 break;
640 }
641 case AndroidMotionEvent::ACTION_MOVE: {
642 type = NS_TOUCH_MOVE;
643 break;
644 }
645 case AndroidMotionEvent::ACTION_UP:
646 case AndroidMotionEvent::ACTION_POINTER_UP: {
647 type = NS_TOUCH_END;
648 // for pointer-up events we only want the data from
649 // the one pointer that went up
650 startIndex = PointerIndex();
651 endIndex = startIndex + 1;
652 break;
653 }
654 case AndroidMotionEvent::ACTION_OUTSIDE:
655 case AndroidMotionEvent::ACTION_CANCEL: {
656 type = NS_TOUCH_CANCEL;
657 break;
658 }
659 }
661 WidgetTouchEvent event(true, type, widget);
662 if (type == NS_EVENT_NULL) {
663 // An event we don't know about
664 return event;
665 }
667 event.modifiers = DOMModifiers();
668 event.time = Time();
670 const nsIntPoint& offset = widget->WidgetToScreenOffset();
671 event.touches.SetCapacity(endIndex - startIndex);
672 for (int i = startIndex; i < endIndex; i++) {
673 // In this code branch, we are dispatching this event directly
674 // into Gecko (as opposed to going through the AsyncPanZoomController),
675 // and the Points() array has points in CSS pixels, which we need
676 // to convert.
677 CSSToLayoutDeviceScale scale = widget->GetDefaultScale();
678 nsIntPoint pt(
679 (Points()[i].x * scale.scale) - offset.x,
680 (Points()[i].y * scale.scale) - offset.y);
681 nsIntPoint radii(
682 PointRadii()[i].x * scale.scale,
683 PointRadii()[i].y * scale.scale);
684 nsRefPtr<Touch> t = new Touch(PointIndicies()[i],
685 pt,
686 radii,
687 Orientations()[i],
688 Pressures()[i]);
689 event.touches.AppendElement(t);
690 }
692 return event;
693 }
695 MultiTouchInput
696 AndroidGeckoEvent::MakeMultiTouchInput(nsIWidget* widget)
697 {
698 MultiTouchInput::MultiTouchType type = (MultiTouchInput::MultiTouchType)-1;
699 int startIndex = 0;
700 int endIndex = Count();
702 switch (Action()) {
703 case AndroidMotionEvent::ACTION_DOWN:
704 case AndroidMotionEvent::ACTION_POINTER_DOWN: {
705 type = MultiTouchInput::MULTITOUCH_START;
706 break;
707 }
708 case AndroidMotionEvent::ACTION_MOVE: {
709 type = MultiTouchInput::MULTITOUCH_MOVE;
710 break;
711 }
712 case AndroidMotionEvent::ACTION_UP:
713 case AndroidMotionEvent::ACTION_POINTER_UP: {
714 // for pointer-up events we only want the data from
715 // the one pointer that went up
716 startIndex = PointerIndex();
717 endIndex = startIndex + 1;
718 type = MultiTouchInput::MULTITOUCH_END;
719 break;
720 }
721 case AndroidMotionEvent::ACTION_OUTSIDE:
722 case AndroidMotionEvent::ACTION_CANCEL: {
723 type = MultiTouchInput::MULTITOUCH_CANCEL;
724 break;
725 }
726 }
728 MultiTouchInput event(type, Time(), 0);
729 event.modifiers = DOMModifiers();
731 if (type < 0) {
732 // An event we don't know about
733 return event;
734 }
736 const nsIntPoint& offset = widget->WidgetToScreenOffset();
737 event.mTouches.SetCapacity(endIndex - startIndex);
738 for (int i = startIndex; i < endIndex; i++) {
739 nsIntPoint point = Points()[i] - offset;
740 nsIntPoint radius = PointRadii()[i];
741 SingleTouchData data(PointIndicies()[i],
742 ScreenIntPoint::FromUnknownPoint(
743 gfx::IntPoint(point.x, point.y)),
744 ScreenSize::FromUnknownSize(
745 gfx::Size(radius.x, radius.y)),
746 Orientations()[i],
747 Pressures()[i]);
748 event.mTouches.AppendElement(data);
749 }
751 return event;
752 }
754 WidgetMouseEvent
755 AndroidGeckoEvent::MakeMouseEvent(nsIWidget* widget)
756 {
757 uint32_t msg = NS_EVENT_NULL;
758 if (Points().Length() > 0) {
759 switch (Action()) {
760 case AndroidMotionEvent::ACTION_HOVER_MOVE:
761 msg = NS_MOUSE_MOVE;
762 break;
763 case AndroidMotionEvent::ACTION_HOVER_ENTER:
764 msg = NS_MOUSEENTER;
765 break;
766 case AndroidMotionEvent::ACTION_HOVER_EXIT:
767 msg = NS_MOUSELEAVE;
768 break;
769 default:
770 break;
771 }
772 }
774 WidgetMouseEvent event(true, msg, widget,
775 WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal);
777 if (msg == NS_EVENT_NULL) {
778 // unknown type, or no point data. abort
779 return event;
780 }
782 // XXX can we synthesize different buttons?
783 event.button = WidgetMouseEvent::eLeftButton;
784 if (msg != NS_MOUSE_MOVE) {
785 event.clickCount = 1;
786 }
787 event.modifiers = DOMModifiers();
788 event.time = Time();
790 // We are dispatching this event directly into Gecko (as opposed to going
791 // through the AsyncPanZoomController), and the Points() array has points
792 // in CSS pixels, which we need to convert to LayoutDevice pixels.
793 const nsIntPoint& offset = widget->WidgetToScreenOffset();
794 CSSToLayoutDeviceScale scale = widget->GetDefaultScale();
795 event.refPoint = LayoutDeviceIntPoint((Points()[0].x * scale.scale) - offset.x,
796 (Points()[0].y * scale.scale) - offset.y);
798 return event;
799 }
801 Modifiers
802 AndroidGeckoEvent::DOMModifiers() const
803 {
804 Modifiers result = 0;
805 if (mMetaState & AMETA_ALT_MASK) {
806 result |= MODIFIER_ALT;
807 }
808 if (mMetaState & AMETA_SHIFT_MASK) {
809 result |= MODIFIER_SHIFT;
810 }
811 if (mMetaState & AMETA_CTRL_MASK) {
812 result |= MODIFIER_CONTROL;
813 }
814 if (mMetaState & AMETA_META_MASK) {
815 result |= MODIFIER_META;
816 }
817 if (mMetaState & AMETA_FUNCTION_ON) {
818 result |= MODIFIER_FN;
819 }
820 if (mMetaState & AMETA_CAPS_LOCK_ON) {
821 result |= MODIFIER_CAPSLOCK;
822 }
823 if (mMetaState & AMETA_NUM_LOCK_ON) {
824 result |= MODIFIER_NUMLOCK;
825 }
826 if (mMetaState & AMETA_SCROLL_LOCK_ON) {
827 result |= MODIFIER_SCROLLLOCK;
828 }
829 return result;
830 }
832 void
833 AndroidPoint::Init(JNIEnv *jenv, jobject jobj)
834 {
835 if (jobj) {
836 mX = jenv->GetIntField(jobj, jXField);
837 mY = jenv->GetIntField(jobj, jYField);
838 } else {
839 mX = 0;
840 mY = 0;
841 }
842 }
844 void
845 AndroidLayerRendererFrame::Init(JNIEnv *env, jobject jobj)
846 {
847 if (!isNull()) {
848 Dispose(env);
849 }
851 wrapped_obj = env->NewGlobalRef(jobj);
852 }
854 void
855 AndroidLayerRendererFrame::Dispose(JNIEnv *env)
856 {
857 if (isNull()) {
858 return;
859 }
861 env->DeleteGlobalRef(wrapped_obj);
862 wrapped_obj = 0;
863 }
865 NS_IMPL_ISUPPORTS(nsAndroidDisplayport, nsIAndroidDisplayport)
867 bool
868 AndroidLayerRendererFrame::BeginDrawing(AutoLocalJNIFrame *jniFrame)
869 {
870 if (!jniFrame || !jniFrame->GetEnv())
871 return false;
873 jniFrame->GetEnv()->CallVoidMethod(wrapped_obj, jBeginDrawingMethod);
874 if (jniFrame->CheckForException())
875 return false;
877 return true;
878 }
880 bool
881 AndroidLayerRendererFrame::DrawBackground(AutoLocalJNIFrame *jniFrame)
882 {
883 if (!jniFrame || !jniFrame->GetEnv())
884 return false;
886 jniFrame->GetEnv()->CallVoidMethod(wrapped_obj, jDrawBackgroundMethod);
887 if (jniFrame->CheckForException())
888 return false;
890 return true;
891 }
893 bool
894 AndroidLayerRendererFrame::DrawForeground(AutoLocalJNIFrame *jniFrame)
895 {
896 if (!jniFrame || !jniFrame->GetEnv())
897 return false;
899 jniFrame->GetEnv()->CallVoidMethod(wrapped_obj, jDrawForegroundMethod);
900 if (jniFrame->CheckForException())
901 return false;
903 return true;
904 }
906 bool
907 AndroidLayerRendererFrame::EndDrawing(AutoLocalJNIFrame *jniFrame)
908 {
909 if (!jniFrame || !jniFrame->GetEnv())
910 return false;
912 jniFrame->GetEnv()->CallVoidMethod(wrapped_obj, jEndDrawingMethod);
913 if (jniFrame->CheckForException())
914 return false;
916 return true;
917 }
919 void
920 AndroidRect::Init(JNIEnv *jenv, jobject jobj)
921 {
922 NS_ASSERTION(wrapped_obj == nullptr, "Init called on non-null wrapped_obj!");
924 wrapped_obj = jobj;
926 if (jobj) {
927 mTop = jenv->GetIntField(jobj, jTopField);
928 mLeft = jenv->GetIntField(jobj, jLeftField);
929 mRight = jenv->GetIntField(jobj, jRightField);
930 mBottom = jenv->GetIntField(jobj, jBottomField);
931 } else {
932 mTop = 0;
933 mLeft = 0;
934 mRight = 0;
935 mBottom = 0;
936 }
937 }
939 void
940 AndroidRectF::Init(JNIEnv *jenv, jobject jobj)
941 {
942 NS_ASSERTION(wrapped_obj == nullptr, "Init called on non-null wrapped_obj!");
944 wrapped_obj = jobj;
946 if (jobj) {
947 mTop = jenv->GetFloatField(jobj, jTopField);
948 mLeft = jenv->GetFloatField(jobj, jLeftField);
949 mRight = jenv->GetFloatField(jobj, jRightField);
950 mBottom = jenv->GetFloatField(jobj, jBottomField);
951 } else {
952 mTop = 0;
953 mLeft = 0;
954 mRight = 0;
955 mBottom = 0;
956 }
957 }
959 nsJNIString::nsJNIString(jstring jstr, JNIEnv *jenv)
960 {
961 if (!jstr) {
962 SetIsVoid(true);
963 return;
964 }
965 JNIEnv *jni = jenv;
966 if (!jni) {
967 jni = AndroidBridge::GetJNIEnv();
968 }
969 const jchar* jCharPtr = jni->GetStringChars(jstr, nullptr);
971 if (!jCharPtr) {
972 SetIsVoid(true);
973 return;
974 }
976 jsize len = jni->GetStringLength(jstr);
978 if (len <= 0) {
979 SetIsVoid(true);
980 } else {
981 Assign(reinterpret_cast<const char16_t*>(jCharPtr), len);
982 }
983 jni->ReleaseStringChars(jstr, jCharPtr);
984 }