Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(607)

Unified Diff: Source/core/input/EventHandler.cpp

Issue 1170513002: Update the mouse events on tapping of gesture across frames (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/core/input/EventHandler.cpp
diff --git a/Source/core/input/EventHandler.cpp b/Source/core/input/EventHandler.cpp
index 2385b4e685d715befd987ef797187d68381080ab..10501de8d7eadc2fb78f985b28404da9a007791e 100644
--- a/Source/core/input/EventHandler.cpp
+++ b/Source/core/input/EventHandler.cpp
@@ -2237,6 +2237,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);
@@ -2838,6 +2842,95 @@ 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* enteredFrameInDocument = indexEnteredFrameChain ? enteredFrameChain[indexEnteredFrameChain-1] : nullptr;
+ // Avoid that unnecessary mouse events are fired on tapping across the frames
mustaq 2015/06/16 14:50:44 Thanks Miyoung, I was thinking about a scenario ex
Miyoung Shin(c) 2015/06/20 21:08:29 The iteration of this loop is to check frames from
mustaq 2015/07/02 20:37:29 Thanks for clarifying, and also for adding the ela
+ // If tapping is moved x1 to x2 , the last frame chains is,
+ // Main frame-> A frame -> B frame -> C frame
+ // and the new frame chains is,
+ // Main frame -> A frame -> D frame -> E frame
+ // |------Main frame--------------------|
+ // | |----------------A---------------| |
+ // | | |-----B-----| |-----D------| | |
+ // | | | |---C---| | | |---E----| | | |
+ // | | | | x1 | | | | x2 | | | |
+ // | | | |-------| | | |--------| | | |
+ // | | |-----------| |------------| | |
+ // | |--------------------------------| |
+ // |------------------------------------|
+ // For mouseout/mouseleave events, we should make the exited frame chain like B frame -> C frame.
+ // For mouseover/mouseenter events, we should make the entered frame chain like D frame -> E frame.
+ // And in main frame and A sub-frame we shouldn't fire any mouse events.
+ 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) {
Miyoung Shin(c) 2015/06/20 21:08:29 After updating the test, I found A sub frame didn'
mustaq 2015/07/02 20:37:29 The change makes sense. But this shouldn't influen
Miyoung Shin(c) 2015/07/05 12:39:33 Yes I got rid of A from list, but A is the parent
mustaq 2015/07/06 17:14:50 I think A shouldn't get any bubbling events from c
+ 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");

Powered by Google App Engine
This is Rietveld 408576698