diff --git a/content/events/src/nsEventStateManager.cpp b/content/events/src/nsEventStateManager.cpp index dcc3678a84a..c4981b1414d 100644 --- a/content/events/src/nsEventStateManager.cpp +++ b/content/events/src/nsEventStateManager.cpp @@ -1525,29 +1525,32 @@ nsEventStateManager::IsRemoteTarget(nsIContent* target) { return false; } -/*static*/ void -nsEventStateManager::MapEventCoordinatesForChildProcess(nsFrameLoader* aFrameLoader, - nsEvent* aEvent) +/*static*/ nsIntPoint +nsEventStateManager::GetChildProcessOffset(nsFrameLoader* aFrameLoader, + const nsEvent& aEvent) { // The "toplevel widget" in child processes is always at position // 0,0. Map the event coordinates to match that. nsIFrame* targetFrame = aFrameLoader->GetPrimaryFrameOfOwningContent(); if (!targetFrame) { - return; + return nsIntPoint(); } nsPresContext* presContext = targetFrame->PresContext(); + // Find out how far we're offset from the nearest widget. + nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(&aEvent, + targetFrame); + return pt.ToNearestPixels(presContext->AppUnitsPerDevPixel()); +} + +/*static*/ void +nsEventStateManager::MapEventCoordinatesForChildProcess( + const nsIntPoint& aOffset, nsEvent* aEvent) +{ if (aEvent->eventStructType != NS_TOUCH_EVENT) { - nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, - targetFrame); - aEvent->refPoint = pt.ToNearestPixels(presContext->AppUnitsPerDevPixel()); + aEvent->refPoint = aOffset; } else { aEvent->refPoint = nsIntPoint(); - // Find out how far we're offset from the nearest widget. - nsPoint offset = - nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, targetFrame); - nsIntPoint intOffset = - offset.ToNearestPixels(presContext->AppUnitsPerDevPixel()); nsTouchEvent* touchEvent = static_cast(aEvent); // Then offset all the touch points by that distance, to put them // in the space where top-left is 0,0. @@ -1555,12 +1558,20 @@ nsEventStateManager::MapEventCoordinatesForChildProcess(nsFrameLoader* aFrameLoa for (uint32_t i = 0; i < touches.Length(); ++i) { nsIDOMTouch* touch = touches[i]; if (touch) { - touch->mRefPoint += intOffset; + touch->mRefPoint += aOffset; } } } } +/*static*/ void +nsEventStateManager::MapEventCoordinatesForChildProcess(nsFrameLoader* aFrameLoader, + nsEvent* aEvent) +{ + nsIntPoint offset = GetChildProcessOffset(aFrameLoader, *aEvent); + MapEventCoordinatesForChildProcess(offset, aEvent); +} + bool CrossProcessSafeEvent(const nsEvent& aEvent) { diff --git a/content/events/src/nsEventStateManager.h b/content/events/src/nsEventStateManager.h index ca1aa5c2328..3ef3be16be4 100644 --- a/content/events/src/nsEventStateManager.h +++ b/content/events/src/nsEventStateManager.h @@ -192,10 +192,15 @@ public: static void SetFullScreenState(mozilla::dom::Element* aElement, bool aIsFullScreen); static bool IsRemoteTarget(nsIContent* aTarget); + static nsIntPoint GetChildProcessOffset(nsFrameLoader* aFrameLoader, + const nsEvent& aEvent); static void MapEventCoordinatesForChildProcess(nsFrameLoader* aFrameLoader, nsEvent* aEvent); + static void MapEventCoordinatesForChildProcess(const nsIntPoint& aOffset, + nsEvent* aEvent); + // Holds the point in screen coords that a mouse event was dispatched to, // before we went into pointer lock mode. This is constantly updated while // the pointer is not locked, but we don't update it while the pointer is diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index fba3b45d570..a665a0d028e 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -636,6 +636,18 @@ bool TabParent::SendRealTouchEvent(nsTouchEvent& event) return false; } if (event.message == NS_TOUCH_START) { + // Adjust the widget coordinates to be relative to our frame. + nsRefPtr frameLoader = GetFrameLoader(); + if (!frameLoader) { + // No frame anymore? + sEventCapturer = nullptr; + return false; + } + + mChildProcessOffsetAtTouchStart = + nsEventStateManager::GetChildProcessOffset(frameLoader, + event); + MOZ_ASSERT((!sEventCapturer && mEventCaptureDepth == 0) || (sEventCapturer == this && mEventCaptureDepth > 0)); // We want to capture all remaining touch events in this series @@ -693,16 +705,8 @@ TabParent::TryCapture(const nsGUIEvent& aEvent) return false; } - // Adjust the widget coordinates to be relative to our frame. - nsRefPtr frameLoader = GetFrameLoader(); - - if (!frameLoader) { - // No frame anymore? - sEventCapturer = nullptr; - return false; - } - - nsEventStateManager::MapEventCoordinatesForChildProcess(frameLoader, &event); + nsEventStateManager::MapEventCoordinatesForChildProcess( + mChildProcessOffsetAtTouchStart, &event); SendRealTouchEvent(event); return true; diff --git a/dom/ipc/TabParent.h b/dom/ipc/TabParent.h index 7d1a567b55b..3d641c0aa7d 100644 --- a/dom/ipc/TabParent.h +++ b/dom/ipc/TabParent.h @@ -313,6 +313,11 @@ private: // dispatch to content. void MaybeForwardEventToRenderFrame(const nsInputEvent& aEvent, nsInputEvent* aOutEvent); + // The offset for the child process which is sampled at touch start. This + // means that the touch events are relative to where the frame was at the + // start of the touch. We need to look for a better solution to this + // problem see bug 872911. + nsIntPoint mChildProcessOffsetAtTouchStart; // When true, we've initiated normal shutdown and notified our // managing PContent. bool mMarkedDestroying;