Chromium Code Reviews| Index: Source/core/page/EventHandler.cpp |
| diff --git a/Source/core/page/EventHandler.cpp b/Source/core/page/EventHandler.cpp |
| index 17680fb568c943022b1296e3bf08c7893a8f51ad..272fc6b4ababe33022b14ecf0cb224e31e62f5ad 100644 |
| --- a/Source/core/page/EventHandler.cpp |
| +++ b/Source/core/page/EventHandler.cpp |
| @@ -2261,6 +2261,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); |
| @@ -2862,6 +2866,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().lastNodeUnderMouse(); |
| + 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* enteredFrameInDocument = indexEnteredFrameChain ? enteredFrameChain[indexEnteredFrameChain-1] : nullptr; |
|
mustaq
2015/06/08 17:24:24
Could you please add a comment explaining the logi
Miyoung Shin(c)
2015/06/10 12:10:05
I tried to remain the comment in more detail at th
|
| + if (exitedFrameInDocument != enteredFrameInDocument) |
| + 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* exitedFrameInDocument = exitedFrameChain[--indexExitedFrameChain]; |
| + exitedFrameInDocument->eventHandler().updateMouseEventTargetNode(nullptr, fakeMouseMove, true); |
| + } |
| + |
| + // update the mouseover/mouseenter event |
| + while (indexEnteredFrameChain > 1) { |
| + LocalFrame* enteredFrameInDocument = enteredFrameChain[--indexEnteredFrameChain]; |
| + Node* enteredFrameNode = enteredFrameChain[indexEnteredFrameChain-1]->deprecatedLocalOwner(); |
| + enteredFrameInDocument->eventHandler().updateMouseEventTargetNode(enteredFrameNode, fakeMouseMove, true); |
| + } |
| +} |
| + |
| GestureEventWithHitTestResults EventHandler::targetGestureEvent(const PlatformGestureEvent& gestureEvent, bool readOnly) |
| { |
| TRACE_EVENT0("input", "EventHandler::targetGestureEvent"); |