Bug 969512 - Don't use NS_MOUSEENTER/LEAVE in widget level code. r=kats r=yzen
authorEitan Isaacson <eitan@monotonous.org>
Tue, 23 Sep 2014 12:09:22 -0700
changeset 230119 84b81989aa76f18e117609e0c47c0810661b9f44
parent 229945 78697eff20f3f85ffbff59de63e41ac654c44326
child 230120 b0b831a03d9caa85efec5b5e592b533036f4b106
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats, yzen
bugs969512
milestone35.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 969512 - Don't use NS_MOUSEENTER/LEAVE in widget level code. r=kats r=yzen Make accessibility explore by touch hover events touch events.
accessible/jsat/AccessFu.jsm
accessible/jsat/Gestures.jsm
accessible/jsat/PointerAdapter.jsm
accessible/jsat/content-script.js
mobile/android/base/GeckoEvent.java
widget/android/AndroidJavaWrappers.cpp
widget/android/AndroidJavaWrappers.h
--- a/accessible/jsat/AccessFu.jsm
+++ b/accessible/jsat/AccessFu.jsm
@@ -659,17 +659,17 @@ var Input = {
       case 'dwell1':
       case 'explore1':
         this.moveToPoint('Simple', aGesture.touches[0].x,
           aGesture.touches[0].y);
         break;
       case 'doubletap1':
         this.activateCurrent();
         break;
-      case 'doubletaphold1':
+      case 'taphold1':
         this.sendContextMenuMessage();
         break;
       case 'swiperight1':
         this.moveCursor('moveNext', 'Simple', 'gestures');
         break;
       case 'swipeleft1':
         this.moveCursor('movePrevious', 'Simple', 'gesture');
         break;
--- a/accessible/jsat/Gestures.jsm
+++ b/accessible/jsat/Gestures.jsm
@@ -755,35 +755,16 @@ AndroidTap.prototype.pointerup = functio
     this._threeFingerSwipeTimer = setTimeout(() => {
       delete this._threeFingerSwipeTimer;
       TapGesture.prototype.pointerup.call(this, aPoints);
     }, ANDROID_TRIPLE_SWIPE_DELAY);
   }
 };
 
 /**
- * Reject an android tap gesture.
- * @param  {?Function} aRejectTo An optional next gesture constructor.
- * @return {Object} structure that looks like {
- *   id: gesture_id, // Current AndroidTap gesture id.
- *   gestureType: next_gesture // Optional
- * }
- */
-AndroidTap.prototype._handleReject = function AndroidTap__handleReject(aRejectTo) {
-  let keys = Object.keys(this.points);
-  if (aRejectTo === Swipe && keys.length === 1) {
-    let key = keys[0];
-    let point = this.points[key];
-    // Two finger swipe is translated into single swipe.
-    this.points[key + '-copy'] = point;
-  }
-  return TapGesture.prototype._handleReject.call(this, aRejectTo);
-};
-
-/**
  * Double Tap gesture.
  * @param {Number} aTimeStamp An original pointer event's timeStamp that started
  * the gesture resolution sequence.
  * @param {Object} aPoints An existing set of points (from previous events).
  * @param {?String} aLastEvent Last pointer event type.
  */
 function DoubleTap(aTimeStamp, aPoints, aLastEvent) {
   TapGesture.call(this, aTimeStamp, aPoints, aLastEvent, TapHold);
--- a/accessible/jsat/PointerAdapter.jsm
+++ b/accessible/jsat/PointerAdapter.jsm
@@ -35,39 +35,27 @@ let PointerRelay = { // jshint ignore:li
    * |true| are used for compiling high-level gesture events. Entries with a
    * value of |false| are cancelled and do not propogate to content.
    */
   get _eventsOfInterest() {
     delete this._eventsOfInterest;
 
     switch (Utils.widgetToolkit) {
       case 'gonk':
+      case 'android':
         this._eventsOfInterest = {
           'touchstart' : true,
           'touchmove' : true,
           'touchend' : true,
           'mousedown' : false,
           'mousemove' : false,
           'mouseup': false,
           'click': false };
         break;
 
-      case 'android':
-        this._eventsOfInterest = {
-          'touchstart' : true,
-          'touchmove' : true,
-          'touchend' : true,
-          'mousemove' : true,
-          'mouseenter' : true,
-          'mouseleave' : true,
-          'mousedown' : false,
-          'mouseup': false,
-          'click': false };
-        break;
-
       default:
         // Desktop.
         this._eventsOfInterest = {
           'mousemove' : true,
           'mousedown' : true,
           'mouseup': true,
           'click': false
         };
@@ -80,22 +68,20 @@ let PointerRelay = { // jshint ignore:li
     }
 
     return this._eventsOfInterest;
   },
 
   _eventMap: {
     'touchstart' : 'pointerdown',
     'mousedown' : 'pointerdown',
-    'mouseenter' : 'pointerdown',
     'touchmove' : 'pointermove',
     'mousemove' : 'pointermove',
     'touchend' : 'pointerup',
-    'mouseup': 'pointerup',
-    'mouseleave': 'pointerup'
+    'mouseup': 'pointerup'
   },
 
   start: function PointerRelay_start(aOnPointerEvent) {
     Logger.debug('PointerRelay.start');
     this.onPointerEvent = aOnPointerEvent;
     for (let eventType in this._eventsOfInterest) {
       Utils.win.addEventListener(eventType, this, true, true);
     }
@@ -124,16 +110,26 @@ let PointerRelay = { // jshint ignore:li
 
     let changedTouches = aEvent.changedTouches || [{
       identifier: MOUSE_ID,
       screenX: aEvent.screenX,
       screenY: aEvent.screenY,
       target: aEvent.target
     }];
 
+    if (Utils.widgetToolkit === 'android' &&
+      changedTouches.length === 1 && changedTouches[0].identifier === 1) {
+      changedTouches = [{
+        identifier: 0,
+        screenX: changedTouches[0].screenX + 5,
+        screenY: changedTouches[0].screenY + 5,
+        target: changedTouches[0].target
+      }, changedTouches[0]];
+    }
+
     if (changedTouches.length === 1 &&
         changedTouches[0].identifier === SYNTH_ID) {
       return;
     }
 
     aEvent.preventDefault();
     aEvent.stopImmediatePropagation();
 
--- a/accessible/jsat/content-script.js
+++ b/accessible/jsat/content-script.js
@@ -82,17 +82,16 @@ function presentCaretChange(aText, aOldO
 
 function scroll(aMessage) {
   let position = Utils.getVirtualCursor(content.document).position;
   if (!forwardToChild(aMessage, scroll, position)) {
     sendAsyncMessage('AccessFu:DoScroll',
                      { bounds: Utils.getBounds(position, true),
                        page: aMessage.json.page,
                        horizontal: aMessage.json.horizontal });
-    sendScrollCoordinates(position);
   }
 }
 
 function adjustRange(aMessage) {
   function sendUpDownKey(aAccessible) {
     let acc = Utils.getEmbeddedControl(aAccessible) || aAccessible;
     let elem = acc.DOMNode;
     if (elem) {
--- a/mobile/android/base/GeckoEvent.java
+++ b/mobile/android/base/GeckoEvent.java
@@ -187,16 +187,17 @@ public class GeckoEvent {
     private int mAction;
     private boolean mAckNeeded;
     private long mTime;
     private Point[] mPoints;
     private int[] mPointIndicies;
     private int mPointerIndex; // index of the point that has changed
     private float[] mOrientations;
     private float[] mPressures;
+    private int[] mToolTypes;
     private Point[] mPointRadii;
     private Rect mRect;
     private double mX;
     private double mY;
     private double mZ;
 
     private int mMetaState;
     private int mFlags;
@@ -444,30 +445,32 @@ public class GeckoEvent {
             case MotionEvent.ACTION_HOVER_ENTER:
             case MotionEvent.ACTION_HOVER_MOVE:
             case MotionEvent.ACTION_HOVER_EXIT: {
                 mCount = m.getPointerCount();
                 mPoints = new Point[mCount];
                 mPointIndicies = new int[mCount];
                 mOrientations = new float[mCount];
                 mPressures = new float[mCount];
+                mToolTypes = new int[mCount];
                 mPointRadii = new Point[mCount];
                 mPointerIndex = m.getActionIndex();
                 for (int i = 0; i < mCount; i++) {
                     addMotionPoint(i, i, m, keepInViewCoordinates);
                 }
                 break;
             }
             default: {
                 mCount = 0;
                 mPointerIndex = -1;
                 mPoints = new Point[mCount];
                 mPointIndicies = new int[mCount];
                 mOrientations = new float[mCount];
                 mPressures = new float[mCount];
+                mToolTypes = new int[mCount];
                 mPointRadii = new Point[mCount];
             }
         }
     }
 
     private void addMotionPoint(int index, int eventIndex, MotionEvent event, boolean keepInViewCoordinates) {
         try {
             PointF geckoPoint = new PointF(event.getX(eventIndex), event.getY(eventIndex));
@@ -504,16 +507,19 @@ public class GeckoEvent {
             if (!keepInViewCoordinates) {
                 // If we are converting to gecko CSS pixels, then we should adjust the
                 // radii as well
                 float zoom = GeckoAppShell.getLayerView().getViewportMetrics().zoomFactor;
                 mPointRadii[index].x /= zoom;
                 mPointRadii[index].y /= zoom;
             }
             mPressures[index] = event.getPressure(eventIndex);
+            if (Versions.feature14Plus) {
+                mToolTypes[index] = event.getToolType(index);
+            }
         } catch (Exception ex) {
             Log.e(LOGTAG, "Error creating motion point " + index, ex);
             mPointRadii[index] = new Point(0, 0);
             mPoints[index] = new Point(0, 0);
         }
     }
 
     private static int HalSensorAccuracyFor(int androidAccuracy) {
--- a/widget/android/AndroidJavaWrappers.cpp
+++ b/widget/android/AndroidJavaWrappers.cpp
@@ -19,16 +19,17 @@ using namespace mozilla::widget::android
 jclass AndroidGeckoEvent::jGeckoEventClass = 0;
 jfieldID AndroidGeckoEvent::jActionField = 0;
 jfieldID AndroidGeckoEvent::jTypeField = 0;
 jfieldID AndroidGeckoEvent::jAckNeededField = 0;
 jfieldID AndroidGeckoEvent::jTimeField = 0;
 jfieldID AndroidGeckoEvent::jPoints = 0;
 jfieldID AndroidGeckoEvent::jPointIndicies = 0;
 jfieldID AndroidGeckoEvent::jPressures = 0;
+jfieldID AndroidGeckoEvent::jToolTypes = 0;
 jfieldID AndroidGeckoEvent::jPointRadii = 0;
 jfieldID AndroidGeckoEvent::jOrientations = 0;
 jfieldID AndroidGeckoEvent::jXField = 0;
 jfieldID AndroidGeckoEvent::jYField = 0;
 jfieldID AndroidGeckoEvent::jZField = 0;
 jfieldID AndroidGeckoEvent::jDistanceField = 0;
 jfieldID AndroidGeckoEvent::jRectField = 0;
 jfieldID AndroidGeckoEvent::jNativeWindowField = 0;
@@ -133,16 +134,17 @@ AndroidGeckoEvent::InitGeckoEventClass(J
     jActionField = getField("mAction", "I");
     jTypeField = getField("mType", "I");
     jAckNeededField = getField("mAckNeeded", "Z");
     jTimeField = getField("mTime", "J");
     jPoints = getField("mPoints", "[Landroid/graphics/Point;");
     jPointIndicies = getField("mPointIndicies", "[I");
     jOrientations = getField("mOrientations", "[F");
     jPressures = getField("mPressures", "[F");
+    jToolTypes = getField("mToolTypes", "[I");
     jPointRadii = getField("mPointRadii", "[Landroid/graphics/Point;");
     jXField = getField("mX", "D");
     jYField = getField("mY", "D");
     jZField = getField("mZ", "D");
     jRectField = getField("mRect", "Landroid/graphics/Rect;");
 
     jCharactersField = getField("mCharacters", "Ljava/lang/String;");
     jCharactersExtraField = getField("mCharactersExtra", "Ljava/lang/String;");
@@ -458,16 +460,17 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jo
             mTime = jenv->GetLongField(jobj, jTimeField);
             mMetaState = jenv->GetIntField(jobj, jMetaStateField);
             mCount = jenv->GetIntField(jobj, jCountField);
             mPointerIndex = jenv->GetIntField(jobj, jPointerIndexField);
 
             ReadPointArray(mPointRadii, jenv, jPointRadii, mCount);
             ReadFloatArray(mOrientations, jenv, jOrientations, mCount);
             ReadFloatArray(mPressures, jenv, jPressures, mCount);
+            ReadIntArray(mToolTypes, jenv, jToolTypes, mCount);
             ReadPointArray(mPoints, jenv, jPoints, mCount);
             ReadIntArray(mPointIndicies, jenv, jPointIndicies, mCount);
 
             break;
 
         case IME_EVENT:
             mStart = jenv->GetIntField(jobj, jStartField);
             mEnd = jenv->GetIntField(jobj, jEndField);
@@ -684,25 +687,40 @@ AndroidGeckoEvent::MakeTouchEvent(nsIWid
         return mApzInput.ToWidgetTouchEvent(widget);
     }
 
     int type = NS_EVENT_NULL;
     int startIndex = 0;
     int endIndex = Count();
 
     switch (Action()) {
+        case AndroidMotionEvent::ACTION_HOVER_ENTER: {
+            if (ToolTypes()[0] == AndroidMotionEvent::TOOL_TYPE_MOUSE) {
+                break;
+            }
+        }
         case AndroidMotionEvent::ACTION_DOWN:
         case AndroidMotionEvent::ACTION_POINTER_DOWN: {
             type = NS_TOUCH_START;
             break;
         }
+        case AndroidMotionEvent::ACTION_HOVER_MOVE: {
+            if (ToolTypes()[0] == AndroidMotionEvent::TOOL_TYPE_MOUSE) {
+                break;
+            }
+        }
         case AndroidMotionEvent::ACTION_MOVE: {
             type = NS_TOUCH_MOVE;
             break;
         }
+        case AndroidMotionEvent::ACTION_HOVER_EXIT: {
+            if (ToolTypes()[0] == AndroidMotionEvent::TOOL_TYPE_MOUSE) {
+                break;
+            }
+        }
         case AndroidMotionEvent::ACTION_UP:
         case AndroidMotionEvent::ACTION_POINTER_UP: {
             type = NS_TOUCH_END;
             // for pointer-up events we only want the data from
             // the one pointer that went up
             startIndex = PointerIndex();
             endIndex = startIndex + 1;
             break;
@@ -812,20 +830,20 @@ AndroidGeckoEvent::MakeMouseEvent(nsIWid
 {
     uint32_t msg = NS_EVENT_NULL;
     if (Points().Length() > 0) {
         switch (Action()) {
             case AndroidMotionEvent::ACTION_HOVER_MOVE:
                 msg = NS_MOUSE_MOVE;
                 break;
             case AndroidMotionEvent::ACTION_HOVER_ENTER:
-                msg = NS_MOUSEENTER;
+                msg = NS_MOUSE_ENTER;
                 break;
             case AndroidMotionEvent::ACTION_HOVER_EXIT:
-                msg = NS_MOUSELEAVE;
+                msg = NS_MOUSE_EXIT;
                 break;
             default:
                 break;
         }
     }
 
     WidgetMouseEvent event(true, msg, widget,
                            WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal);
--- a/widget/android/AndroidJavaWrappers.h
+++ b/widget/android/AndroidJavaWrappers.h
@@ -404,16 +404,21 @@ public:
         EDGE_BOTTOM = 0x00000002,
         EDGE_LEFT = 0x00000004,
         EDGE_RIGHT = 0x00000008,
         SAMPLE_X = 0,
         SAMPLE_Y = 1,
         SAMPLE_PRESSURE = 2,
         SAMPLE_SIZE = 3,
         NUM_SAMPLE_DATA = 4,
+        TOOL_TYPE_UNKNOWN = 0,
+        TOOL_TYPE_FINGER = 1,
+        TOOL_TYPE_STYLUS = 2,
+        TOOL_TYPE_MOUSE = 3,
+        TOOL_TYPE_ERASER = 4,
         dummy_java_enum_list_end
     };
 };
 
 class AndroidLocation : public WrappedJavaObject
 {
 public:
     static void InitLocationClass(JNIEnv *jEnv);
@@ -492,16 +497,17 @@ public:
 
     int Action() { return mAction; }
     int Type() { return mType; }
     bool AckNeeded() { return mAckNeeded; }
     int64_t Time() { return mTime; }
     const nsTArray<nsIntPoint>& Points() { return mPoints; }
     const nsTArray<int>& PointIndicies() { return mPointIndicies; }
     const nsTArray<float>& Pressures() { return mPressures; }
+    const nsTArray<int>& ToolTypes() { return mToolTypes; }
     const nsTArray<float>& Orientations() { return mOrientations; }
     const nsTArray<nsIntPoint>& PointRadii() { return mPointRadii; }
     const nsTArray<nsString>& PrefNames() { return mPrefNames; }
     double X() { return mX; }
     double Y() { return mY; }
     double Z() { return mZ; }
     const nsIntRect& Rect() { return mRect; }
     nsAString& Characters() { return mCharacters; }
@@ -559,16 +565,17 @@ protected:
     int mType;
     bool mAckNeeded;
     int64_t mTime;
     nsTArray<nsIntPoint> mPoints;
     nsTArray<nsIntPoint> mPointRadii;
     nsTArray<int> mPointIndicies;
     nsTArray<float> mOrientations;
     nsTArray<float> mPressures;
+    nsTArray<int> mToolTypes;
     nsIntRect mRect;
     int mFlags, mMetaState;
     uint32_t mDomKeyLocation;
     int mKeyCode, mScanCode;
     int mUnicodeChar, mBaseUnicodeChar, mDOMPrintableKeyValue;
     int mRepeatCount;
     int mCount;
     int mStart, mEnd;
@@ -622,16 +629,17 @@ protected:
     static jfieldID jActionField;
     static jfieldID jTypeField;
     static jfieldID jAckNeededField;
     static jfieldID jTimeField;
     static jfieldID jPoints;
     static jfieldID jPointIndicies;
     static jfieldID jOrientations;
     static jfieldID jPressures;
+    static jfieldID jToolTypes;
     static jfieldID jPointRadii;
     static jfieldID jXField;
     static jfieldID jYField;
     static jfieldID jZField;
     static jfieldID jDistanceField;
     static jfieldID jRectField;
     static jfieldID jNativeWindowField;