| Index: Source/core/input/EventHandler.cpp
|
| diff --git a/Source/core/input/EventHandler.cpp b/Source/core/input/EventHandler.cpp
|
| index d16e9e2e4ef679e408209463115845eef5fa68ce..281c51c160717a3e14a079d24aeb21a18b7ff424 100644
|
| --- a/Source/core/input/EventHandler.cpp
|
| +++ b/Source/core/input/EventHandler.cpp
|
| @@ -1852,6 +1852,10 @@ bool EventHandler::handleGestureEvent(const GestureEventWithHitTestResults& targ
|
| // directly to the inner most frame. This matches handleMousePressEvent etc.
|
| ASSERT(!targetedEvent.event().isScrollEvent());
|
|
|
| + // update mouseout/leave/over/enter events before jumping directly to the inner most frame
|
| + if (targetedEvent.event().type() == PlatformEvent::GestureTap)
|
| + updateGestureTargetNodeForMouseEvent(targetedEvent);
|
| +
|
| // Route to the correct frame.
|
| if (LocalFrame* innerFrame = targetedEvent.hitTestResult().innerNodeFrame())
|
| return innerFrame->eventHandler().handleGestureEventInFrame(targetedEvent);
|
| @@ -2481,6 +2485,78 @@ void EventHandler::updateGestureHoverActiveState(const HitTestRequest& request,
|
| m_frame->document()->updateHoverActiveState(request, innerElement);
|
| }
|
|
|
| +// Update the mouseover/mouseenter/mouseout/mouseleave events across all frames for this gesture,
|
| +// before passing the targeted gesture event directly to a hit frame.
|
| +void EventHandler::updateGestureTargetNodeForMouseEvent(const GestureEventWithHitTestResults& targetedEvent)
|
| +{
|
| + ASSERT(m_frame == m_frame->localFrameRoot());
|
| +
|
| + // Behaviour of this function is as follows:
|
| + // - Create the chain of all entered frames.
|
| + // - Compare the last frame chain under the gesture to newly entered frame chain from the main frame one by one.
|
| + // - If the last frame doesn't match with the entered frame, then create the chain of exited frames from the last frame chain.
|
| + // - Dispatch mouseout/mouseleave events of the exited frames from the inside out.
|
| + // - Dispatch mouseover/mouseenter events of the entered frames into the inside.
|
| +
|
| + // Insert the ancestors of the frame having the new target node to the entered frame chain
|
| + WillBeHeapVector<LocalFrame*> enteredFrameChain;
|
| + LocalFrame* enteredFrameInDocument = targetedEvent.hitTestResult().innerNodeFrame();
|
| + while (enteredFrameInDocument) {
|
| + enteredFrameChain.append(enteredFrameInDocument);
|
| + Frame* parentFrame = enteredFrameInDocument->tree().parent();
|
| + enteredFrameInDocument = parentFrame && parentFrame->isLocalFrame() ? toLocalFrame(parentFrame) : nullptr;
|
| + }
|
| +
|
| + size_t indexEnteredFrameChain = enteredFrameChain.size();
|
| + LocalFrame* exitedFrameInDocument = m_frame;
|
| + WillBeHeapVector<LocalFrame*> exitedFrameChain;
|
| + // Insert the frame from the disagreement between last frames and entered frames
|
| + while (exitedFrameInDocument) {
|
| + Node* lastNodeUnderTap = exitedFrameInDocument->eventHandler().m_lastNodeUnderMouse.get();
|
| + if (!lastNodeUnderTap)
|
| + break;
|
| +
|
| + LocalFrame* nextExitedFrameInDocument = nullptr;
|
| + if (lastNodeUnderTap->isFrameOwnerElement()) {
|
| + HTMLFrameOwnerElement* owner = toHTMLFrameOwnerElement(lastNodeUnderTap);
|
| + if (owner->contentFrame() && owner->contentFrame()->isLocalFrame())
|
| + nextExitedFrameInDocument = toLocalFrame(owner->contentFrame());
|
| + }
|
| +
|
| + if (exitedFrameChain.size() > 0) {
|
| + exitedFrameChain.append(exitedFrameInDocument);
|
| + } else {
|
| + LocalFrame* lastEnteredFrameInDocument = indexEnteredFrameChain ? enteredFrameChain[indexEnteredFrameChain-1] : nullptr;
|
| + if (exitedFrameInDocument != lastEnteredFrameInDocument)
|
| + exitedFrameChain.append(exitedFrameInDocument);
|
| + else if (nextExitedFrameInDocument && indexEnteredFrameChain)
|
| + --indexEnteredFrameChain;
|
| + }
|
| + exitedFrameInDocument = nextExitedFrameInDocument;
|
| + }
|
| +
|
| + const PlatformGestureEvent& gestureEvent = targetedEvent.event();
|
| + unsigned modifiers = gestureEvent.modifiers();
|
| + PlatformMouseEvent fakeMouseMove(gestureEvent.position(), gestureEvent.globalPosition(),
|
| + NoButton, PlatformEvent::MouseMoved, /* clickCount */ 0,
|
| + static_cast<PlatformEvent::Modifiers>(modifiers),
|
| + PlatformMouseEvent::FromTouch, gestureEvent.timestamp());
|
| +
|
| + // Update the mouseout/mouseleave event
|
| + size_t indexExitedFrameChain = exitedFrameChain.size();
|
| + while (indexExitedFrameChain) {
|
| + LocalFrame* leaveFrame = exitedFrameChain[--indexExitedFrameChain];
|
| + leaveFrame->eventHandler().updateMouseEventTargetNode(nullptr, fakeMouseMove, true);
|
| + }
|
| +
|
| + // update the mouseover/mouseenter event
|
| + while (indexEnteredFrameChain) {
|
| + Frame* parentFrame = enteredFrameChain[--indexEnteredFrameChain]->tree().parent();
|
| + if (parentFrame && parentFrame->isLocalFrame())
|
| + toLocalFrame(parentFrame)->eventHandler().updateMouseEventTargetNode(toHTMLFrameOwnerElement(enteredFrameChain[indexEnteredFrameChain]->owner()), fakeMouseMove, true);
|
| + }
|
| +}
|
| +
|
| GestureEventWithHitTestResults EventHandler::targetGestureEvent(const PlatformGestureEvent& gestureEvent, bool readOnly)
|
| {
|
| TRACE_EVENT0("input", "EventHandler::targetGestureEvent");
|
|
|