Bug 1232338 - part 2, Fix mouse hover events to have correct refPoint value when C++APZ is enabled r=jchen
authorRandall Barker <rbarker@mozilla.com>
Wed, 17 Feb 2016 13:57:12 -0800
changeset 339596 d297ed97eaa1b1a4f309bbe4daa1df4c64dfcef8
parent 339595 ec3026e8cd6f3af1fb8da5283574c3e8308379f0
child 339597 0cd50254f2286856b5ebb339dc8abce761aca766
push id12762
push userbmo:rail@mozilla.com
push dateFri, 11 Mar 2016 19:47:45 +0000
reviewersjchen
bugs1232338
milestone48.0a1
Bug 1232338 - part 2, Fix mouse hover events to have correct refPoint value when C++APZ is enabled r=jchen
mobile/android/base/java/org/mozilla/gecko/gfx/LayerView.java
mobile/android/base/java/org/mozilla/gecko/gfx/NativePanZoomController.java
widget/android/GeneratedJNINatives.h
widget/android/GeneratedJNIWrappers.cpp
widget/android/GeneratedJNIWrappers.h
widget/android/nsWindow.cpp
--- a/mobile/android/base/java/org/mozilla/gecko/gfx/LayerView.java
+++ b/mobile/android/base/java/org/mozilla/gecko/gfx/LayerView.java
@@ -244,16 +244,26 @@ public class LayerView extends ScrollVie
         // don't send it to gecko.
         if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN &&
             !GeckoAccessibility.isEnabled()) {
             return false;
         }
 
         event.offsetLocation(0, -mSurfaceTranslation);
 
+        if (AppConstants.MOZ_ANDROID_APZ) {
+            if (!mLayerClient.isGeckoReady()) {
+                // If gecko isn't loaded yet, don't try sending events to the
+                // native code because it's just going to crash
+                return true;
+            } else if (mPanZoomController != null && mPanZoomController.onMotionEvent(event)) {
+                return true;
+            }
+        }
+
         return sendEventToGecko(event);
     }
 
     @Override
     public boolean onGenericMotionEvent(MotionEvent event) {
         event.offsetLocation(0, -mSurfaceTranslation);
 
         if (AndroidGamepadManager.handleMotionEvent(event)) {
--- a/mobile/android/base/java/org/mozilla/gecko/gfx/NativePanZoomController.java
+++ b/mobile/android/base/java/org/mozilla/gecko/gfx/NativePanZoomController.java
@@ -40,16 +40,21 @@ class NativePanZoomController extends JN
             float toolMajor[], float toolMinor[]);
 
     @WrapForJNI
     private native boolean handleScrollEvent(
             long time, int metaState,
             float x, float y,
             float hScroll, float vScroll);
 
+    @WrapForJNI
+    private native boolean handleHoverEvent(
+            int action, long time, int metaState,
+            float x, float y);
+
     private boolean handleMotionEvent(MotionEvent event, boolean keepInViewCoordinates) {
         if (mDestroyed) {
             return false;
         }
 
         final int action = event.getActionMasked();
         final int count = event.getPointerCount();
 
@@ -117,16 +122,35 @@ class NativePanZoomController extends JN
 
         final float flipFactor = mNegateWheelScroll ? -1.0f : 1.0f;
         final float hScroll = event.getAxisValue(MotionEvent.AXIS_HSCROLL) * flipFactor * mPointerScrollFactor;
         final float vScroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL) * flipFactor * mPointerScrollFactor;
 
         return handleScrollEvent(event.getEventTime(), event.getMetaState(), x, y, hScroll, vScroll);
     }
 
+    private boolean handleHoverEvent(MotionEvent event) {
+        if (mDestroyed) {
+            return false;
+        }
+
+        final int count = event.getPointerCount();
+
+        if (count <= 0) {
+            return false;
+        }
+
+        final MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords();
+        event.getPointerCoords(0, coords);
+        final float x = coords.x;
+        final float y = coords.y;
+
+        return handleHoverEvent(event.getActionMasked(), event.getEventTime(), event.getMetaState(), x, y);
+    }
+
 
     NativePanZoomController(PanZoomTarget target, View view) {
         mTarget = target;
         mView = (LayerView) view;
 
         String[] prefs = { "ui.scrolling.negate_wheel_scroll" };
         mPrefsObserver = new PrefsHelper.PrefHandlerBase() {
             @Override public void prefValue(String pref, boolean value) {
@@ -151,19 +175,23 @@ class NativePanZoomController extends JN
     }
 
     @Override
     public boolean onMotionEvent(MotionEvent event) {
         final int action = event.getActionMasked();
         if (action == MotionEvent.ACTION_SCROLL && event.getDownTime() >= mLastDownTime) {
             mLastDownTime = event.getDownTime();
             return handleScrollEvent(event);
+        } else if ((action == MotionEvent.ACTION_HOVER_MOVE) ||
+                   (action == MotionEvent.ACTION_HOVER_ENTER) ||
+                   (action == MotionEvent.ACTION_HOVER_EXIT)) {
+            return handleHoverEvent(event);
+        } else {
+            return false;
         }
-
-        return false;
     }
 
     @Override
     public boolean onKeyEvent(KeyEvent event) {
         // FIXME implement this
         return false;
     }
 
--- a/widget/android/GeneratedJNINatives.h
+++ b/widget/android/GeneratedJNINatives.h
@@ -289,16 +289,20 @@ public:
         mozilla::jni::MakeNativeMethod<NativePanZoomController::AdjustScrollForSurfaceShift_t>(
                 mozilla::jni::NativeStub<NativePanZoomController::AdjustScrollForSurfaceShift_t, Impl>
                 ::template Wrap<&Impl::AdjustScrollForSurfaceShift>),
 
         mozilla::jni::MakeNativeMethod<NativePanZoomController::DisposeNative_t>(
                 mozilla::jni::NativeStub<NativePanZoomController::DisposeNative_t, Impl>
                 ::template Wrap<&Impl::DisposeNative>),
 
+        mozilla::jni::MakeNativeMethod<NativePanZoomController::HandleHoverEvent_t>(
+                mozilla::jni::NativeStub<NativePanZoomController::HandleHoverEvent_t, Impl>
+                ::template Wrap<&Impl::HandleHoverEvent>),
+
         mozilla::jni::MakeNativeMethod<NativePanZoomController::HandleMotionEvent_t>(
                 mozilla::jni::NativeStub<NativePanZoomController::HandleMotionEvent_t, Impl>
                 ::template Wrap<&Impl::HandleMotionEvent>),
 
         mozilla::jni::MakeNativeMethod<NativePanZoomController::HandleScrollEvent_t>(
                 mozilla::jni::NativeStub<NativePanZoomController::HandleScrollEvent_t, Impl>
                 ::template Wrap<&Impl::HandleScrollEvent>),
 
--- a/widget/android/GeneratedJNIWrappers.cpp
+++ b/widget/android/GeneratedJNIWrappers.cpp
@@ -1533,16 +1533,19 @@ constexpr char NativePanZoomController::
 auto NativePanZoomController::Destroy() const -> void
 {
     return mozilla::jni::Method<Destroy_t>::Call(NativePanZoomController::mCtx, nullptr);
 }
 
 constexpr char NativePanZoomController::DisposeNative_t::name[];
 constexpr char NativePanZoomController::DisposeNative_t::signature[];
 
+constexpr char NativePanZoomController::HandleHoverEvent_t::name[];
+constexpr char NativePanZoomController::HandleHoverEvent_t::signature[];
+
 constexpr char NativePanZoomController::HandleMotionEvent_t::name[];
 constexpr char NativePanZoomController::HandleMotionEvent_t::signature[];
 
 constexpr char NativePanZoomController::HandleScrollEvent_t::name[];
 constexpr char NativePanZoomController::HandleScrollEvent_t::signature[];
 
 constexpr char NativePanZoomController::AbortAnimation_t::name[];
 constexpr char NativePanZoomController::AbortAnimation_t::signature[];
--- a/widget/android/GeneratedJNIWrappers.h
+++ b/widget/android/GeneratedJNIWrappers.h
@@ -3620,16 +3620,34 @@ public:
         static constexpr char name[] = "disposeNative";
         static constexpr char signature[] =
                 "()V";
         static const bool isStatic = false;
         static const mozilla::jni::ExceptionMode exceptionMode =
                 mozilla::jni::ExceptionMode::ABORT;
     };
 
+    struct HandleHoverEvent_t {
+        typedef NativePanZoomController Owner;
+        typedef bool ReturnType;
+        typedef bool SetterType;
+        typedef mozilla::jni::Args<
+                int32_t,
+                int64_t,
+                int32_t,
+                float,
+                float> Args;
+        static constexpr char name[] = "handleHoverEvent";
+        static constexpr char signature[] =
+                "(IJIFF)Z";
+        static const bool isStatic = false;
+        static const mozilla::jni::ExceptionMode exceptionMode =
+                mozilla::jni::ExceptionMode::ABORT;
+    };
+
     struct HandleMotionEvent_t {
         typedef NativePanZoomController Owner;
         typedef bool ReturnType;
         typedef bool SetterType;
         typedef mozilla::jni::Args<
                 int32_t,
                 int32_t,
                 int64_t,
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -576,16 +576,88 @@ public:
             WidgetWheelEvent wheelEvent = input.ToWidgetWheelEvent(window);
             window->ProcessUntransformedAPZEvent(&wheelEvent, guid,
                                                  blockId, status);
         });
 
         return true;
     }
 
+    bool HandleHoverEvent(int32_t aAction, int64_t aTime, int32_t aMetaState,
+                          float aX, float aY)
+    {
+        MOZ_ASSERT(AndroidBridge::IsJavaUiThread());
+
+        MutexAutoLock lock(mWindowLock);
+        if (!mWindow) {
+            // We already shut down.
+            return false;
+        }
+
+        RefPtr<APZCTreeManager> controller = mWindow->mAPZC;
+        if (!controller) {
+            return false;
+        }
+
+        MouseInput::MouseType type = MouseInput::MOUSE_NONE;
+        switch (aAction) {
+            case AndroidMotionEvent::ACTION_HOVER_MOVE:
+                type = MouseInput::MOUSE_MOVE;
+                break;
+            case AndroidMotionEvent::ACTION_HOVER_ENTER:
+                type = MouseInput::MOUSE_WIDGET_ENTER;
+                break;
+            case AndroidMotionEvent::ACTION_HOVER_EXIT:
+                type = MouseInput::MOUSE_WIDGET_EXIT;
+                break;
+            default:
+                break;
+        }
+
+        if (type == MouseInput::MOUSE_NONE) {
+            return false;
+        }
+
+        ScreenIntPoint offset = ViewAs<ScreenPixel>(mWindow->WidgetToScreenOffset(), PixelCastJustification::LayoutDeviceIsScreenForBounds);
+        ScreenPoint origin = ScreenPoint(aX, aY) - offset;
+
+        MouseInput input(type, MouseInput::NONE, 0, origin, aTime, TimeStamp(), GetModifiers(aMetaState));
+
+        ScrollableLayerGuid guid;
+        uint64_t blockId;
+        nsEventStatus status = controller->ReceiveInputEvent(input, &guid, &blockId);
+
+        if (status == nsEventStatus_eConsumeNoDefault) {
+            return true;
+        }
+
+        NativePanZoomController::GlobalRef npzc = mNPZC;
+        nsAppShell::PostEvent([npzc, input, guid, blockId, status] {
+            MOZ_ASSERT(NS_IsMainThread());
+
+            JNIEnv* const env = jni::GetGeckoThreadEnv();
+            NPZCSupport* npzcSupport = GetNative(
+                    NativePanZoomController::LocalRef(env, npzc));
+
+            if (!npzcSupport || !npzcSupport->mWindow) {
+                // We already shut down.
+                env->ExceptionClear();
+                return;
+            }
+
+            nsWindow* const window = npzcSupport->mWindow;
+            window->UserActivity();
+            WidgetMouseEvent mouseEvent = input.ToWidgetMouseEvent(window);
+            window->ProcessUntransformedAPZEvent(&mouseEvent, guid,
+                                                 blockId, status);
+        });
+
+        return true;
+    }
+
     bool HandleMotionEvent(const NativePanZoomController::LocalRef& aInstance,
                            int32_t aAction, int32_t aActionIndex,
                            int64_t aTime, int32_t aMetaState,
                            jni::IntArray::Param aPointerId,
                            jni::FloatArray::Param aX,
                            jni::FloatArray::Param aY,
                            jni::FloatArray::Param aOrientation,
                            jni::FloatArray::Param aPressure,