michael@0: /* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "AndroidJavaWrappers.h" michael@0: #include "AndroidBridge.h" michael@0: #include "AndroidBridgeUtilities.h" michael@0: #include "nsIDOMKeyEvent.h" michael@0: #include "nsIWidget.h" michael@0: #include "mozilla/BasicEvents.h" michael@0: #include "mozilla/TouchEvents.h" michael@0: michael@0: using namespace mozilla; michael@0: using namespace mozilla::dom; michael@0: using namespace mozilla::widget::android; michael@0: michael@0: jclass AndroidGeckoEvent::jGeckoEventClass = 0; michael@0: jfieldID AndroidGeckoEvent::jActionField = 0; michael@0: jfieldID AndroidGeckoEvent::jTypeField = 0; michael@0: jfieldID AndroidGeckoEvent::jAckNeededField = 0; michael@0: jfieldID AndroidGeckoEvent::jTimeField = 0; michael@0: jfieldID AndroidGeckoEvent::jPoints = 0; michael@0: jfieldID AndroidGeckoEvent::jPointIndicies = 0; michael@0: jfieldID AndroidGeckoEvent::jPressures = 0; michael@0: jfieldID AndroidGeckoEvent::jPointRadii = 0; michael@0: jfieldID AndroidGeckoEvent::jOrientations = 0; michael@0: jfieldID AndroidGeckoEvent::jXField = 0; michael@0: jfieldID AndroidGeckoEvent::jYField = 0; michael@0: jfieldID AndroidGeckoEvent::jZField = 0; michael@0: jfieldID AndroidGeckoEvent::jDistanceField = 0; michael@0: jfieldID AndroidGeckoEvent::jRectField = 0; michael@0: jfieldID AndroidGeckoEvent::jNativeWindowField = 0; michael@0: michael@0: jfieldID AndroidGeckoEvent::jCharactersField = 0; michael@0: jfieldID AndroidGeckoEvent::jCharactersExtraField = 0; michael@0: jfieldID AndroidGeckoEvent::jDataField = 0; michael@0: jfieldID AndroidGeckoEvent::jDOMPrintableKeyValueField = 0; michael@0: jfieldID AndroidGeckoEvent::jKeyCodeField = 0; michael@0: jfieldID AndroidGeckoEvent::jMetaStateField = 0; michael@0: jfieldID AndroidGeckoEvent::jDomKeyLocationField = 0; michael@0: jfieldID AndroidGeckoEvent::jFlagsField = 0; michael@0: jfieldID AndroidGeckoEvent::jUnicodeCharField = 0; michael@0: jfieldID AndroidGeckoEvent::jBaseUnicodeCharField = 0; michael@0: jfieldID AndroidGeckoEvent::jRepeatCountField = 0; michael@0: jfieldID AndroidGeckoEvent::jCountField = 0; michael@0: jfieldID AndroidGeckoEvent::jStartField = 0; michael@0: jfieldID AndroidGeckoEvent::jEndField = 0; michael@0: jfieldID AndroidGeckoEvent::jPointerIndexField = 0; michael@0: jfieldID AndroidGeckoEvent::jRangeTypeField = 0; michael@0: jfieldID AndroidGeckoEvent::jRangeStylesField = 0; michael@0: jfieldID AndroidGeckoEvent::jRangeLineStyleField = 0; michael@0: jfieldID AndroidGeckoEvent::jRangeBoldLineField = 0; michael@0: jfieldID AndroidGeckoEvent::jRangeForeColorField = 0; michael@0: jfieldID AndroidGeckoEvent::jRangeBackColorField = 0; michael@0: jfieldID AndroidGeckoEvent::jRangeLineColorField = 0; michael@0: jfieldID AndroidGeckoEvent::jLocationField = 0; michael@0: jfieldID AndroidGeckoEvent::jConnectionTypeField = 0; michael@0: jfieldID AndroidGeckoEvent::jIsWifiField = 0; michael@0: jfieldID AndroidGeckoEvent::jDHCPGatewayField = 0; michael@0: jfieldID AndroidGeckoEvent::jScreenOrientationField = 0; michael@0: jfieldID AndroidGeckoEvent::jByteBufferField = 0; michael@0: jfieldID AndroidGeckoEvent::jWidthField = 0; michael@0: jfieldID AndroidGeckoEvent::jHeightField = 0; michael@0: jfieldID AndroidGeckoEvent::jPrefNamesField = 0; michael@0: michael@0: jclass AndroidGeckoEvent::jDomKeyLocationClass = 0; michael@0: jfieldID AndroidGeckoEvent::jDomKeyLocationValueField = 0; michael@0: michael@0: jclass AndroidPoint::jPointClass = 0; michael@0: jfieldID AndroidPoint::jXField = 0; michael@0: jfieldID AndroidPoint::jYField = 0; michael@0: michael@0: jclass AndroidRect::jRectClass = 0; michael@0: jfieldID AndroidRect::jBottomField = 0; michael@0: jfieldID AndroidRect::jLeftField = 0; michael@0: jfieldID AndroidRect::jRightField = 0; michael@0: jfieldID AndroidRect::jTopField = 0; michael@0: michael@0: jclass AndroidRectF::jRectClass = 0; michael@0: jfieldID AndroidRectF::jBottomField = 0; michael@0: jfieldID AndroidRectF::jLeftField = 0; michael@0: jfieldID AndroidRectF::jRightField = 0; michael@0: jfieldID AndroidRectF::jTopField = 0; michael@0: michael@0: jclass AndroidLocation::jLocationClass = 0; michael@0: jmethodID AndroidLocation::jGetLatitudeMethod = 0; michael@0: jmethodID AndroidLocation::jGetLongitudeMethod = 0; michael@0: jmethodID AndroidLocation::jGetAltitudeMethod = 0; michael@0: jmethodID AndroidLocation::jGetAccuracyMethod = 0; michael@0: jmethodID AndroidLocation::jGetBearingMethod = 0; michael@0: jmethodID AndroidLocation::jGetSpeedMethod = 0; michael@0: jmethodID AndroidLocation::jGetTimeMethod = 0; michael@0: michael@0: jclass AndroidLayerRendererFrame::jLayerRendererFrameClass = 0; michael@0: jmethodID AndroidLayerRendererFrame::jBeginDrawingMethod = 0; michael@0: jmethodID AndroidLayerRendererFrame::jDrawBackgroundMethod = 0; michael@0: jmethodID AndroidLayerRendererFrame::jDrawForegroundMethod = 0; michael@0: jmethodID AndroidLayerRendererFrame::jEndDrawingMethod = 0; michael@0: michael@0: RefCountedJavaObject::~RefCountedJavaObject() { michael@0: if (mObject) michael@0: GetJNIForThread()->DeleteGlobalRef(mObject); michael@0: mObject = nullptr; michael@0: } michael@0: michael@0: void michael@0: mozilla::InitAndroidJavaWrappers(JNIEnv *jEnv) michael@0: { michael@0: AndroidGeckoEvent::InitGeckoEventClass(jEnv); michael@0: AndroidPoint::InitPointClass(jEnv); michael@0: AndroidLocation::InitLocationClass(jEnv); michael@0: AndroidRect::InitRectClass(jEnv); michael@0: AndroidRectF::InitRectFClass(jEnv); michael@0: AndroidLayerRendererFrame::InitLayerRendererFrameClass(jEnv); michael@0: InitStubs(jEnv); michael@0: } michael@0: michael@0: void michael@0: AndroidGeckoEvent::InitGeckoEventClass(JNIEnv *jEnv) michael@0: { michael@0: initInit(); michael@0: michael@0: jGeckoEventClass = getClassGlobalRef("org/mozilla/gecko/GeckoEvent"); michael@0: michael@0: jActionField = getField("mAction", "I"); michael@0: jTypeField = getField("mType", "I"); michael@0: jAckNeededField = getField("mAckNeeded", "Z"); michael@0: jTimeField = getField("mTime", "J"); michael@0: jPoints = getField("mPoints", "[Landroid/graphics/Point;"); michael@0: jPointIndicies = getField("mPointIndicies", "[I"); michael@0: jOrientations = getField("mOrientations", "[F"); michael@0: jPressures = getField("mPressures", "[F"); michael@0: jPointRadii = getField("mPointRadii", "[Landroid/graphics/Point;"); michael@0: jXField = getField("mX", "D"); michael@0: jYField = getField("mY", "D"); michael@0: jZField = getField("mZ", "D"); michael@0: jRectField = getField("mRect", "Landroid/graphics/Rect;"); michael@0: michael@0: jCharactersField = getField("mCharacters", "Ljava/lang/String;"); michael@0: jCharactersExtraField = getField("mCharactersExtra", "Ljava/lang/String;"); michael@0: jDataField = getField("mData", "Ljava/lang/String;"); michael@0: jKeyCodeField = getField("mKeyCode", "I"); michael@0: jMetaStateField = getField("mMetaState", "I"); michael@0: jDomKeyLocationField = getField("mDomKeyLocation", "Lorg/mozilla/gecko/GeckoEvent$DomKeyLocation;"); michael@0: jFlagsField = getField("mFlags", "I"); michael@0: jUnicodeCharField = getField("mUnicodeChar", "I"); michael@0: jBaseUnicodeCharField = getField("mBaseUnicodeChar", "I"); michael@0: jDOMPrintableKeyValueField = getField("mDOMPrintableKeyValue", "I"); michael@0: jRepeatCountField = getField("mRepeatCount", "I"); michael@0: jCountField = getField("mCount", "I"); michael@0: jStartField = getField("mStart", "I"); michael@0: jEndField = getField("mEnd", "I"); michael@0: jPointerIndexField = getField("mPointerIndex", "I"); michael@0: jRangeTypeField = getField("mRangeType", "I"); michael@0: jRangeStylesField = getField("mRangeStyles", "I"); michael@0: jRangeLineStyleField = getField("mRangeLineStyle", "I"); michael@0: jRangeBoldLineField = getField("mRangeBoldLine", "Z"); michael@0: jRangeForeColorField = getField("mRangeForeColor", "I"); michael@0: jRangeBackColorField = getField("mRangeBackColor", "I"); michael@0: jRangeLineColorField = getField("mRangeLineColor", "I"); michael@0: jLocationField = getField("mLocation", "Landroid/location/Location;"); michael@0: jConnectionTypeField = getField("mConnectionType", "I"); michael@0: jIsWifiField = getField("mIsWifi", "Z"); michael@0: jDHCPGatewayField = getField("mDHCPGateway", "I"); michael@0: jScreenOrientationField = getField("mScreenOrientation", "S"); michael@0: jByteBufferField = getField("mBuffer", "Ljava/nio/ByteBuffer;"); michael@0: jWidthField = getField("mWidth", "I"); michael@0: jHeightField = getField("mHeight", "I"); michael@0: jPrefNamesField = getField("mPrefNames", "[Ljava/lang/String;"); michael@0: michael@0: // Init GeckoEvent.DomKeyLocation enum michael@0: jDomKeyLocationClass = getClassGlobalRef("org/mozilla/gecko/GeckoEvent$DomKeyLocation"); michael@0: jDomKeyLocationValueField = getField("value", "I"); michael@0: } michael@0: michael@0: void michael@0: AndroidLocation::InitLocationClass(JNIEnv *jEnv) michael@0: { michael@0: initInit(); michael@0: michael@0: jLocationClass = getClassGlobalRef("android/location/Location"); michael@0: jGetLatitudeMethod = getMethod("getLatitude", "()D"); michael@0: jGetLongitudeMethod = getMethod("getLongitude", "()D"); michael@0: jGetAltitudeMethod = getMethod("getAltitude", "()D"); michael@0: jGetAccuracyMethod = getMethod("getAccuracy", "()F"); michael@0: jGetBearingMethod = getMethod("getBearing", "()F"); michael@0: jGetSpeedMethod = getMethod("getSpeed", "()F"); michael@0: jGetTimeMethod = getMethod("getTime", "()J"); michael@0: } michael@0: michael@0: nsGeoPosition* michael@0: AndroidLocation::CreateGeoPosition(JNIEnv *jenv, jobject jobj) michael@0: { michael@0: AutoLocalJNIFrame jniFrame(jenv); michael@0: michael@0: double latitude = jenv->CallDoubleMethod(jobj, jGetLatitudeMethod); michael@0: if (jniFrame.CheckForException()) return nullptr; michael@0: double longitude = jenv->CallDoubleMethod(jobj, jGetLongitudeMethod); michael@0: if (jniFrame.CheckForException()) return nullptr; michael@0: double altitude = jenv->CallDoubleMethod(jobj, jGetAltitudeMethod); michael@0: if (jniFrame.CheckForException()) return nullptr; michael@0: float accuracy = jenv->CallFloatMethod (jobj, jGetAccuracyMethod); michael@0: if (jniFrame.CheckForException()) return nullptr; michael@0: float bearing = jenv->CallFloatMethod (jobj, jGetBearingMethod); michael@0: if (jniFrame.CheckForException()) return nullptr; michael@0: float speed = jenv->CallFloatMethod (jobj, jGetSpeedMethod); michael@0: if (jniFrame.CheckForException()) return nullptr; michael@0: long long time = jenv->CallLongMethod (jobj, jGetTimeMethod); michael@0: if (jniFrame.CheckForException()) return nullptr; michael@0: michael@0: return new nsGeoPosition(latitude, longitude, michael@0: altitude, accuracy, michael@0: accuracy, bearing, michael@0: speed, time); michael@0: } michael@0: michael@0: void michael@0: AndroidPoint::InitPointClass(JNIEnv *jEnv) michael@0: { michael@0: initInit(); michael@0: michael@0: jPointClass = getClassGlobalRef("android/graphics/Point"); michael@0: michael@0: jXField = getField("x", "I"); michael@0: jYField = getField("y", "I"); michael@0: } michael@0: michael@0: void michael@0: AndroidRect::InitRectClass(JNIEnv *jEnv) michael@0: { michael@0: initInit(); michael@0: michael@0: jRectClass = getClassGlobalRef("android/graphics/Rect"); michael@0: michael@0: jBottomField = getField("bottom", "I"); michael@0: jLeftField = getField("left", "I"); michael@0: jTopField = getField("top", "I"); michael@0: jRightField = getField("right", "I"); michael@0: } michael@0: michael@0: void michael@0: AndroidRectF::InitRectFClass(JNIEnv *jEnv) michael@0: { michael@0: initInit(); michael@0: michael@0: jRectClass = getClassGlobalRef("android/graphics/RectF"); michael@0: michael@0: jBottomField = getField("bottom", "F"); michael@0: jLeftField = getField("left", "F"); michael@0: jTopField = getField("top", "F"); michael@0: jRightField = getField("right", "F"); michael@0: } michael@0: michael@0: void michael@0: AndroidLayerRendererFrame::InitLayerRendererFrameClass(JNIEnv *jEnv) michael@0: { michael@0: initInit(); michael@0: michael@0: jLayerRendererFrameClass = getClassGlobalRef("org/mozilla/gecko/gfx/LayerRenderer$Frame"); michael@0: michael@0: jBeginDrawingMethod = getMethod("beginDrawing", "()V"); michael@0: jDrawBackgroundMethod = getMethod("drawBackground", "()V"); michael@0: jDrawForegroundMethod = getMethod("drawForeground", "()V"); michael@0: jEndDrawingMethod = getMethod("endDrawing", "()V"); michael@0: } michael@0: michael@0: #undef initInit michael@0: #undef initClassGlobalRef michael@0: #undef getField michael@0: #undef getMethod michael@0: michael@0: void michael@0: AndroidGeckoEvent::ReadPointArray(nsTArray &points, michael@0: JNIEnv *jenv, michael@0: jfieldID field, michael@0: int32_t count) michael@0: { michael@0: jobjectArray jObjArray = (jobjectArray)jenv->GetObjectField(wrapped_obj, field); michael@0: for (int32_t i = 0; i < count; i++) { michael@0: jobject jObj = jenv->GetObjectArrayElement(jObjArray, i); michael@0: AndroidPoint jpoint(jenv, jObj); michael@0: michael@0: nsIntPoint p(jpoint.X(), jpoint.Y()); michael@0: points.AppendElement(p); michael@0: } michael@0: } michael@0: michael@0: void michael@0: AndroidGeckoEvent::ReadIntArray(nsTArray &aVals, michael@0: JNIEnv *jenv, michael@0: jfieldID field, michael@0: int32_t count) michael@0: { michael@0: jintArray jIntArray = (jintArray)jenv->GetObjectField(wrapped_obj, field); michael@0: jint *vals = jenv->GetIntArrayElements(jIntArray, nullptr); michael@0: for (int32_t i = 0; i < count; i++) { michael@0: aVals.AppendElement(vals[i]); michael@0: } michael@0: jenv->ReleaseIntArrayElements(jIntArray, vals, JNI_ABORT); michael@0: } michael@0: michael@0: void michael@0: AndroidGeckoEvent::ReadFloatArray(nsTArray &aVals, michael@0: JNIEnv *jenv, michael@0: jfieldID field, michael@0: int32_t count) michael@0: { michael@0: jfloatArray jFloatArray = (jfloatArray)jenv->GetObjectField(wrapped_obj, field); michael@0: jfloat *vals = jenv->GetFloatArrayElements(jFloatArray, nullptr); michael@0: for (int32_t i = 0; i < count; i++) { michael@0: aVals.AppendElement(vals[i]); michael@0: } michael@0: jenv->ReleaseFloatArrayElements(jFloatArray, vals, JNI_ABORT); michael@0: } michael@0: michael@0: void michael@0: AndroidGeckoEvent::ReadStringArray(nsTArray &array, michael@0: JNIEnv *jenv, michael@0: jfieldID field) michael@0: { michael@0: jarray jArray = (jarray)jenv->GetObjectField(wrapped_obj, field); michael@0: jsize length = jenv->GetArrayLength(jArray); michael@0: jobjectArray jStringArray = (jobjectArray)jArray; michael@0: nsString *strings = array.AppendElements(length); michael@0: for (jsize i = 0; i < length; ++i) { michael@0: jstring javastring = (jstring) jenv->GetObjectArrayElement(jStringArray, i); michael@0: ReadStringFromJString(strings[i], jenv, javastring); michael@0: } michael@0: } michael@0: michael@0: void michael@0: AndroidGeckoEvent::ReadRectField(JNIEnv *jenv) michael@0: { michael@0: AndroidRect r(jenv, jenv->GetObjectField(wrappedObject(), jRectField)); michael@0: if (!r.isNull()) { michael@0: mRect.SetRect(r.Left(), michael@0: r.Top(), michael@0: r.Width(), michael@0: r.Height()); michael@0: } else { michael@0: mRect.SetEmpty(); michael@0: } michael@0: } michael@0: michael@0: void michael@0: AndroidGeckoEvent::ReadStringFromJString(nsString &aString, JNIEnv *jenv, michael@0: jstring s) michael@0: { michael@0: if (!s) { michael@0: aString.SetIsVoid(true); michael@0: return; michael@0: } michael@0: michael@0: int len = jenv->GetStringLength(s); michael@0: aString.SetLength(len); michael@0: jenv->GetStringRegion(s, 0, len, reinterpret_cast(aString.BeginWriting())); michael@0: } michael@0: michael@0: void michael@0: AndroidGeckoEvent::ReadCharactersField(JNIEnv *jenv) michael@0: { michael@0: jstring s = (jstring) jenv->GetObjectField(wrapped_obj, jCharactersField); michael@0: ReadStringFromJString(mCharacters, jenv, s); michael@0: } michael@0: michael@0: void michael@0: AndroidGeckoEvent::ReadCharactersExtraField(JNIEnv *jenv) michael@0: { michael@0: jstring s = (jstring) jenv->GetObjectField(wrapped_obj, jCharactersExtraField); michael@0: ReadStringFromJString(mCharactersExtra, jenv, s); michael@0: } michael@0: michael@0: void michael@0: AndroidGeckoEvent::ReadDataField(JNIEnv *jenv) michael@0: { michael@0: jstring s = (jstring) jenv->GetObjectField(wrapped_obj, jDataField); michael@0: ReadStringFromJString(mData, jenv, s); michael@0: } michael@0: michael@0: void michael@0: AndroidGeckoEvent::UnionRect(nsIntRect const& aRect) michael@0: { michael@0: mRect = aRect.Union(mRect); michael@0: } michael@0: michael@0: uint32_t michael@0: AndroidGeckoEvent::ReadDomKeyLocation(JNIEnv* jenv, jobject jGeckoEventObj) michael@0: { michael@0: jobject enumObject = jenv->GetObjectField(jGeckoEventObj, michael@0: jDomKeyLocationField); michael@0: MOZ_ASSERT(enumObject); michael@0: int enumValue = jenv->GetIntField(enumObject, jDomKeyLocationValueField); michael@0: MOZ_ASSERT(enumValue >= nsIDOMKeyEvent::DOM_KEY_LOCATION_STANDARD && michael@0: enumValue <= nsIDOMKeyEvent::DOM_KEY_LOCATION_JOYSTICK); michael@0: return static_cast(enumValue); michael@0: } michael@0: michael@0: void michael@0: AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj) michael@0: { michael@0: NS_ASSERTION(!wrapped_obj, "Init called on non-null wrapped_obj!"); michael@0: michael@0: wrapped_obj = jobj; michael@0: michael@0: if (!jobj) michael@0: return; michael@0: michael@0: mAction = jenv->GetIntField(jobj, jActionField); michael@0: mType = jenv->GetIntField(jobj, jTypeField); michael@0: mAckNeeded = jenv->GetBooleanField(jobj, jAckNeededField); michael@0: michael@0: switch (mType) { michael@0: case SIZE_CHANGED: michael@0: ReadPointArray(mPoints, jenv, jPoints, 2); michael@0: break; michael@0: michael@0: case KEY_EVENT: michael@0: case IME_KEY_EVENT: michael@0: mTime = jenv->GetLongField(jobj, jTimeField); michael@0: mMetaState = jenv->GetIntField(jobj, jMetaStateField); michael@0: mDomKeyLocation = ReadDomKeyLocation(jenv, jobj); michael@0: mFlags = jenv->GetIntField(jobj, jFlagsField); michael@0: mKeyCode = jenv->GetIntField(jobj, jKeyCodeField); michael@0: mUnicodeChar = jenv->GetIntField(jobj, jUnicodeCharField); michael@0: mBaseUnicodeChar = jenv->GetIntField(jobj, jBaseUnicodeCharField); michael@0: mDOMPrintableKeyValue = michael@0: jenv->GetIntField(jobj, jDOMPrintableKeyValueField); michael@0: mRepeatCount = jenv->GetIntField(jobj, jRepeatCountField); michael@0: ReadCharactersField(jenv); michael@0: break; michael@0: michael@0: case NATIVE_GESTURE_EVENT: michael@0: mTime = jenv->GetLongField(jobj, jTimeField); michael@0: mMetaState = jenv->GetIntField(jobj, jMetaStateField); michael@0: mCount = jenv->GetIntField(jobj, jCountField); michael@0: ReadPointArray(mPoints, jenv, jPoints, mCount); michael@0: mX = jenv->GetDoubleField(jobj, jXField); michael@0: michael@0: break; michael@0: michael@0: case MOTION_EVENT: michael@0: mTime = jenv->GetLongField(jobj, jTimeField); michael@0: mMetaState = jenv->GetIntField(jobj, jMetaStateField); michael@0: mCount = jenv->GetIntField(jobj, jCountField); michael@0: mPointerIndex = jenv->GetIntField(jobj, jPointerIndexField); michael@0: michael@0: ReadPointArray(mPointRadii, jenv, jPointRadii, mCount); michael@0: ReadFloatArray(mOrientations, jenv, jOrientations, mCount); michael@0: ReadFloatArray(mPressures, jenv, jPressures, mCount); michael@0: ReadPointArray(mPoints, jenv, jPoints, mCount); michael@0: ReadIntArray(mPointIndicies, jenv, jPointIndicies, mCount); michael@0: michael@0: break; michael@0: michael@0: case IME_EVENT: michael@0: mStart = jenv->GetIntField(jobj, jStartField); michael@0: mEnd = jenv->GetIntField(jobj, jEndField); michael@0: michael@0: if (mAction == IME_REPLACE_TEXT) { michael@0: ReadCharactersField(jenv); michael@0: } else if (mAction == IME_UPDATE_COMPOSITION || michael@0: mAction == IME_ADD_COMPOSITION_RANGE) { michael@0: mRangeType = jenv->GetIntField(jobj, jRangeTypeField); michael@0: mRangeStyles = jenv->GetIntField(jobj, jRangeStylesField); michael@0: mRangeLineStyle = michael@0: jenv->GetIntField(jobj, jRangeLineStyleField); michael@0: mRangeBoldLine = michael@0: jenv->GetBooleanField(jobj, jRangeBoldLineField); michael@0: mRangeForeColor = michael@0: jenv->GetIntField(jobj, jRangeForeColorField); michael@0: mRangeBackColor = michael@0: jenv->GetIntField(jobj, jRangeBackColorField); michael@0: mRangeLineColor = michael@0: jenv->GetIntField(jobj, jRangeLineColorField); michael@0: } michael@0: break; michael@0: michael@0: case DRAW: michael@0: ReadRectField(jenv); michael@0: break; michael@0: michael@0: case SENSOR_EVENT: michael@0: mX = jenv->GetDoubleField(jobj, jXField); michael@0: mY = jenv->GetDoubleField(jobj, jYField); michael@0: mZ = jenv->GetDoubleField(jobj, jZField); michael@0: mFlags = jenv->GetIntField(jobj, jFlagsField); michael@0: mMetaState = jenv->GetIntField(jobj, jMetaStateField); michael@0: break; michael@0: michael@0: case LOCATION_EVENT: { michael@0: jobject location = jenv->GetObjectField(jobj, jLocationField); michael@0: mGeoPosition = AndroidLocation::CreateGeoPosition(jenv, location); michael@0: break; michael@0: } michael@0: michael@0: case LOAD_URI: { michael@0: ReadCharactersField(jenv); michael@0: ReadCharactersExtraField(jenv); michael@0: break; michael@0: } michael@0: michael@0: case VIEWPORT: michael@0: case BROADCAST: { michael@0: ReadCharactersField(jenv); michael@0: ReadCharactersExtraField(jenv); michael@0: break; michael@0: } michael@0: michael@0: case NETWORK_CHANGED: { michael@0: mConnectionType = jenv->GetIntField(jobj, jConnectionTypeField); michael@0: mIsWifi = jenv->GetBooleanField(jobj, jIsWifiField); michael@0: mDHCPGateway = jenv->GetIntField(jobj, jDHCPGatewayField); michael@0: break; michael@0: } michael@0: michael@0: case VISITED: { michael@0: ReadCharactersField(jenv); michael@0: break; michael@0: } michael@0: michael@0: case THUMBNAIL: { michael@0: mMetaState = jenv->GetIntField(jobj, jMetaStateField); michael@0: ReadPointArray(mPoints, jenv, jPoints, 1); michael@0: mByteBuffer = new RefCountedJavaObject(jenv, jenv->GetObjectField(jobj, jByteBufferField)); michael@0: break; michael@0: } michael@0: michael@0: case SCREENORIENTATION_CHANGED: { michael@0: mScreenOrientation = jenv->GetShortField(jobj, jScreenOrientationField); michael@0: break; michael@0: } michael@0: michael@0: case COMPOSITOR_CREATE: { michael@0: mWidth = jenv->GetIntField(jobj, jWidthField); michael@0: mHeight = jenv->GetIntField(jobj, jHeightField); michael@0: break; michael@0: } michael@0: michael@0: case CALL_OBSERVER: { michael@0: ReadCharactersField(jenv); michael@0: ReadCharactersExtraField(jenv); michael@0: ReadDataField(jenv); michael@0: break; michael@0: } michael@0: michael@0: case REMOVE_OBSERVER: { michael@0: ReadCharactersField(jenv); michael@0: break; michael@0: } michael@0: michael@0: case LOW_MEMORY: { michael@0: mMetaState = jenv->GetIntField(jobj, jMetaStateField); michael@0: break; michael@0: } michael@0: michael@0: case NETWORK_LINK_CHANGE: { michael@0: ReadCharactersField(jenv); michael@0: break; michael@0: } michael@0: michael@0: case TELEMETRY_HISTOGRAM_ADD: { michael@0: ReadCharactersField(jenv); michael@0: mCount = jenv->GetIntField(jobj, jCountField); michael@0: break; michael@0: } michael@0: michael@0: case TELEMETRY_UI_SESSION_START: { michael@0: ReadCharactersField(jenv); michael@0: mTime = jenv->GetLongField(jobj, jTimeField); michael@0: break; michael@0: } michael@0: michael@0: case TELEMETRY_UI_SESSION_STOP: { michael@0: ReadCharactersField(jenv); michael@0: ReadCharactersExtraField(jenv); michael@0: mTime = jenv->GetLongField(jobj, jTimeField); michael@0: break; michael@0: } michael@0: michael@0: case TELEMETRY_UI_EVENT: { michael@0: ReadCharactersField(jenv); michael@0: ReadCharactersExtraField(jenv); michael@0: ReadDataField(jenv); michael@0: mTime = jenv->GetLongField(jobj, jTimeField); michael@0: break; michael@0: } michael@0: michael@0: case PREFERENCES_OBSERVE: michael@0: case PREFERENCES_GET: { michael@0: ReadStringArray(mPrefNames, jenv, jPrefNamesField); michael@0: mCount = jenv->GetIntField(jobj, jCountField); michael@0: break; michael@0: } michael@0: michael@0: case PREFERENCES_REMOVE_OBSERVERS: { michael@0: mCount = jenv->GetIntField(jobj, jCountField); michael@0: break; michael@0: } michael@0: michael@0: default: michael@0: break; michael@0: } michael@0: michael@0: #ifdef DEBUG_ANDROID_EVENTS michael@0: ALOG("AndroidGeckoEvent: %p : %d", (void*)jobj, mType); michael@0: #endif michael@0: } michael@0: michael@0: void michael@0: AndroidGeckoEvent::Init(int aType) michael@0: { michael@0: mType = aType; michael@0: mAckNeeded = false; michael@0: } michael@0: michael@0: void michael@0: AndroidGeckoEvent::Init(AndroidGeckoEvent *aResizeEvent) michael@0: { michael@0: NS_ASSERTION(aResizeEvent->Type() == SIZE_CHANGED, "Init called on non-SIZE_CHANGED event"); michael@0: michael@0: mType = FORCED_RESIZE; michael@0: mAckNeeded = false; michael@0: mTime = aResizeEvent->mTime; michael@0: mPoints = aResizeEvent->mPoints; // x,y coordinates michael@0: } michael@0: michael@0: WidgetTouchEvent michael@0: AndroidGeckoEvent::MakeTouchEvent(nsIWidget* widget) michael@0: { michael@0: int type = NS_EVENT_NULL; michael@0: int startIndex = 0; michael@0: int endIndex = Count(); michael@0: michael@0: switch (Action()) { michael@0: case AndroidMotionEvent::ACTION_DOWN: michael@0: case AndroidMotionEvent::ACTION_POINTER_DOWN: { michael@0: type = NS_TOUCH_START; michael@0: break; michael@0: } michael@0: case AndroidMotionEvent::ACTION_MOVE: { michael@0: type = NS_TOUCH_MOVE; michael@0: break; michael@0: } michael@0: case AndroidMotionEvent::ACTION_UP: michael@0: case AndroidMotionEvent::ACTION_POINTER_UP: { michael@0: type = NS_TOUCH_END; michael@0: // for pointer-up events we only want the data from michael@0: // the one pointer that went up michael@0: startIndex = PointerIndex(); michael@0: endIndex = startIndex + 1; michael@0: break; michael@0: } michael@0: case AndroidMotionEvent::ACTION_OUTSIDE: michael@0: case AndroidMotionEvent::ACTION_CANCEL: { michael@0: type = NS_TOUCH_CANCEL; michael@0: break; michael@0: } michael@0: } michael@0: michael@0: WidgetTouchEvent event(true, type, widget); michael@0: if (type == NS_EVENT_NULL) { michael@0: // An event we don't know about michael@0: return event; michael@0: } michael@0: michael@0: event.modifiers = DOMModifiers(); michael@0: event.time = Time(); michael@0: michael@0: const nsIntPoint& offset = widget->WidgetToScreenOffset(); michael@0: event.touches.SetCapacity(endIndex - startIndex); michael@0: for (int i = startIndex; i < endIndex; i++) { michael@0: // In this code branch, we are dispatching this event directly michael@0: // into Gecko (as opposed to going through the AsyncPanZoomController), michael@0: // and the Points() array has points in CSS pixels, which we need michael@0: // to convert. michael@0: CSSToLayoutDeviceScale scale = widget->GetDefaultScale(); michael@0: nsIntPoint pt( michael@0: (Points()[i].x * scale.scale) - offset.x, michael@0: (Points()[i].y * scale.scale) - offset.y); michael@0: nsIntPoint radii( michael@0: PointRadii()[i].x * scale.scale, michael@0: PointRadii()[i].y * scale.scale); michael@0: nsRefPtr t = new Touch(PointIndicies()[i], michael@0: pt, michael@0: radii, michael@0: Orientations()[i], michael@0: Pressures()[i]); michael@0: event.touches.AppendElement(t); michael@0: } michael@0: michael@0: return event; michael@0: } michael@0: michael@0: MultiTouchInput michael@0: AndroidGeckoEvent::MakeMultiTouchInput(nsIWidget* widget) michael@0: { michael@0: MultiTouchInput::MultiTouchType type = (MultiTouchInput::MultiTouchType)-1; michael@0: int startIndex = 0; michael@0: int endIndex = Count(); michael@0: michael@0: switch (Action()) { michael@0: case AndroidMotionEvent::ACTION_DOWN: michael@0: case AndroidMotionEvent::ACTION_POINTER_DOWN: { michael@0: type = MultiTouchInput::MULTITOUCH_START; michael@0: break; michael@0: } michael@0: case AndroidMotionEvent::ACTION_MOVE: { michael@0: type = MultiTouchInput::MULTITOUCH_MOVE; michael@0: break; michael@0: } michael@0: case AndroidMotionEvent::ACTION_UP: michael@0: case AndroidMotionEvent::ACTION_POINTER_UP: { michael@0: // for pointer-up events we only want the data from michael@0: // the one pointer that went up michael@0: startIndex = PointerIndex(); michael@0: endIndex = startIndex + 1; michael@0: type = MultiTouchInput::MULTITOUCH_END; michael@0: break; michael@0: } michael@0: case AndroidMotionEvent::ACTION_OUTSIDE: michael@0: case AndroidMotionEvent::ACTION_CANCEL: { michael@0: type = MultiTouchInput::MULTITOUCH_CANCEL; michael@0: break; michael@0: } michael@0: } michael@0: michael@0: MultiTouchInput event(type, Time(), 0); michael@0: event.modifiers = DOMModifiers(); michael@0: michael@0: if (type < 0) { michael@0: // An event we don't know about michael@0: return event; michael@0: } michael@0: michael@0: const nsIntPoint& offset = widget->WidgetToScreenOffset(); michael@0: event.mTouches.SetCapacity(endIndex - startIndex); michael@0: for (int i = startIndex; i < endIndex; i++) { michael@0: nsIntPoint point = Points()[i] - offset; michael@0: nsIntPoint radius = PointRadii()[i]; michael@0: SingleTouchData data(PointIndicies()[i], michael@0: ScreenIntPoint::FromUnknownPoint( michael@0: gfx::IntPoint(point.x, point.y)), michael@0: ScreenSize::FromUnknownSize( michael@0: gfx::Size(radius.x, radius.y)), michael@0: Orientations()[i], michael@0: Pressures()[i]); michael@0: event.mTouches.AppendElement(data); michael@0: } michael@0: michael@0: return event; michael@0: } michael@0: michael@0: WidgetMouseEvent michael@0: AndroidGeckoEvent::MakeMouseEvent(nsIWidget* widget) michael@0: { michael@0: uint32_t msg = NS_EVENT_NULL; michael@0: if (Points().Length() > 0) { michael@0: switch (Action()) { michael@0: case AndroidMotionEvent::ACTION_HOVER_MOVE: michael@0: msg = NS_MOUSE_MOVE; michael@0: break; michael@0: case AndroidMotionEvent::ACTION_HOVER_ENTER: michael@0: msg = NS_MOUSEENTER; michael@0: break; michael@0: case AndroidMotionEvent::ACTION_HOVER_EXIT: michael@0: msg = NS_MOUSELEAVE; michael@0: break; michael@0: default: michael@0: break; michael@0: } michael@0: } michael@0: michael@0: WidgetMouseEvent event(true, msg, widget, michael@0: WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal); michael@0: michael@0: if (msg == NS_EVENT_NULL) { michael@0: // unknown type, or no point data. abort michael@0: return event; michael@0: } michael@0: michael@0: // XXX can we synthesize different buttons? michael@0: event.button = WidgetMouseEvent::eLeftButton; michael@0: if (msg != NS_MOUSE_MOVE) { michael@0: event.clickCount = 1; michael@0: } michael@0: event.modifiers = DOMModifiers(); michael@0: event.time = Time(); michael@0: michael@0: // We are dispatching this event directly into Gecko (as opposed to going michael@0: // through the AsyncPanZoomController), and the Points() array has points michael@0: // in CSS pixels, which we need to convert to LayoutDevice pixels. michael@0: const nsIntPoint& offset = widget->WidgetToScreenOffset(); michael@0: CSSToLayoutDeviceScale scale = widget->GetDefaultScale(); michael@0: event.refPoint = LayoutDeviceIntPoint((Points()[0].x * scale.scale) - offset.x, michael@0: (Points()[0].y * scale.scale) - offset.y); michael@0: michael@0: return event; michael@0: } michael@0: michael@0: Modifiers michael@0: AndroidGeckoEvent::DOMModifiers() const michael@0: { michael@0: Modifiers result = 0; michael@0: if (mMetaState & AMETA_ALT_MASK) { michael@0: result |= MODIFIER_ALT; michael@0: } michael@0: if (mMetaState & AMETA_SHIFT_MASK) { michael@0: result |= MODIFIER_SHIFT; michael@0: } michael@0: if (mMetaState & AMETA_CTRL_MASK) { michael@0: result |= MODIFIER_CONTROL; michael@0: } michael@0: if (mMetaState & AMETA_META_MASK) { michael@0: result |= MODIFIER_META; michael@0: } michael@0: if (mMetaState & AMETA_FUNCTION_ON) { michael@0: result |= MODIFIER_FN; michael@0: } michael@0: if (mMetaState & AMETA_CAPS_LOCK_ON) { michael@0: result |= MODIFIER_CAPSLOCK; michael@0: } michael@0: if (mMetaState & AMETA_NUM_LOCK_ON) { michael@0: result |= MODIFIER_NUMLOCK; michael@0: } michael@0: if (mMetaState & AMETA_SCROLL_LOCK_ON) { michael@0: result |= MODIFIER_SCROLLLOCK; michael@0: } michael@0: return result; michael@0: } michael@0: michael@0: void michael@0: AndroidPoint::Init(JNIEnv *jenv, jobject jobj) michael@0: { michael@0: if (jobj) { michael@0: mX = jenv->GetIntField(jobj, jXField); michael@0: mY = jenv->GetIntField(jobj, jYField); michael@0: } else { michael@0: mX = 0; michael@0: mY = 0; michael@0: } michael@0: } michael@0: michael@0: void michael@0: AndroidLayerRendererFrame::Init(JNIEnv *env, jobject jobj) michael@0: { michael@0: if (!isNull()) { michael@0: Dispose(env); michael@0: } michael@0: michael@0: wrapped_obj = env->NewGlobalRef(jobj); michael@0: } michael@0: michael@0: void michael@0: AndroidLayerRendererFrame::Dispose(JNIEnv *env) michael@0: { michael@0: if (isNull()) { michael@0: return; michael@0: } michael@0: michael@0: env->DeleteGlobalRef(wrapped_obj); michael@0: wrapped_obj = 0; michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS(nsAndroidDisplayport, nsIAndroidDisplayport) michael@0: michael@0: bool michael@0: AndroidLayerRendererFrame::BeginDrawing(AutoLocalJNIFrame *jniFrame) michael@0: { michael@0: if (!jniFrame || !jniFrame->GetEnv()) michael@0: return false; michael@0: michael@0: jniFrame->GetEnv()->CallVoidMethod(wrapped_obj, jBeginDrawingMethod); michael@0: if (jniFrame->CheckForException()) michael@0: return false; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: AndroidLayerRendererFrame::DrawBackground(AutoLocalJNIFrame *jniFrame) michael@0: { michael@0: if (!jniFrame || !jniFrame->GetEnv()) michael@0: return false; michael@0: michael@0: jniFrame->GetEnv()->CallVoidMethod(wrapped_obj, jDrawBackgroundMethod); michael@0: if (jniFrame->CheckForException()) michael@0: return false; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: AndroidLayerRendererFrame::DrawForeground(AutoLocalJNIFrame *jniFrame) michael@0: { michael@0: if (!jniFrame || !jniFrame->GetEnv()) michael@0: return false; michael@0: michael@0: jniFrame->GetEnv()->CallVoidMethod(wrapped_obj, jDrawForegroundMethod); michael@0: if (jniFrame->CheckForException()) michael@0: return false; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: AndroidLayerRendererFrame::EndDrawing(AutoLocalJNIFrame *jniFrame) michael@0: { michael@0: if (!jniFrame || !jniFrame->GetEnv()) michael@0: return false; michael@0: michael@0: jniFrame->GetEnv()->CallVoidMethod(wrapped_obj, jEndDrawingMethod); michael@0: if (jniFrame->CheckForException()) michael@0: return false; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: void michael@0: AndroidRect::Init(JNIEnv *jenv, jobject jobj) michael@0: { michael@0: NS_ASSERTION(wrapped_obj == nullptr, "Init called on non-null wrapped_obj!"); michael@0: michael@0: wrapped_obj = jobj; michael@0: michael@0: if (jobj) { michael@0: mTop = jenv->GetIntField(jobj, jTopField); michael@0: mLeft = jenv->GetIntField(jobj, jLeftField); michael@0: mRight = jenv->GetIntField(jobj, jRightField); michael@0: mBottom = jenv->GetIntField(jobj, jBottomField); michael@0: } else { michael@0: mTop = 0; michael@0: mLeft = 0; michael@0: mRight = 0; michael@0: mBottom = 0; michael@0: } michael@0: } michael@0: michael@0: void michael@0: AndroidRectF::Init(JNIEnv *jenv, jobject jobj) michael@0: { michael@0: NS_ASSERTION(wrapped_obj == nullptr, "Init called on non-null wrapped_obj!"); michael@0: michael@0: wrapped_obj = jobj; michael@0: michael@0: if (jobj) { michael@0: mTop = jenv->GetFloatField(jobj, jTopField); michael@0: mLeft = jenv->GetFloatField(jobj, jLeftField); michael@0: mRight = jenv->GetFloatField(jobj, jRightField); michael@0: mBottom = jenv->GetFloatField(jobj, jBottomField); michael@0: } else { michael@0: mTop = 0; michael@0: mLeft = 0; michael@0: mRight = 0; michael@0: mBottom = 0; michael@0: } michael@0: } michael@0: michael@0: nsJNIString::nsJNIString(jstring jstr, JNIEnv *jenv) michael@0: { michael@0: if (!jstr) { michael@0: SetIsVoid(true); michael@0: return; michael@0: } michael@0: JNIEnv *jni = jenv; michael@0: if (!jni) { michael@0: jni = AndroidBridge::GetJNIEnv(); michael@0: } michael@0: const jchar* jCharPtr = jni->GetStringChars(jstr, nullptr); michael@0: michael@0: if (!jCharPtr) { michael@0: SetIsVoid(true); michael@0: return; michael@0: } michael@0: michael@0: jsize len = jni->GetStringLength(jstr); michael@0: michael@0: if (len <= 0) { michael@0: SetIsVoid(true); michael@0: } else { michael@0: Assign(reinterpret_cast(jCharPtr), len); michael@0: } michael@0: jni->ReleaseStringChars(jstr, jCharPtr); michael@0: }