OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserv
ed. | 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserv
ed. |
3 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) | 3 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) |
4 * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies) | 4 * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies) |
5 * | 5 * |
6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
8 * are met: | 8 * are met: |
9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
(...skipping 1428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1439 | 1439 |
1440 // Treat any mouse move events as readonly if the user is currently touching
the screen. | 1440 // Treat any mouse move events as readonly if the user is currently touching
the screen. |
1441 if (m_touchPressed) | 1441 if (m_touchPressed) |
1442 hitType |= HitTestRequest::Active | HitTestRequest::ReadOnly; | 1442 hitType |= HitTestRequest::Active | HitTestRequest::ReadOnly; |
1443 HitTestRequest request(hitType); | 1443 HitTestRequest request(hitType); |
1444 MouseEventWithHitTestResults mev = MouseEventWithHitTestResults(mouseEvent,
HitTestResult(LayoutPoint())); | 1444 MouseEventWithHitTestResults mev = MouseEventWithHitTestResults(mouseEvent,
HitTestResult(LayoutPoint())); |
1445 | 1445 |
1446 // We don't want to do a hit-test in forceLeave scenarios because there migh
t actually be some other frame above this one at the specified co-ordinate. | 1446 // We don't want to do a hit-test in forceLeave scenarios because there migh
t actually be some other frame above this one at the specified co-ordinate. |
1447 // So we must force the hit-test to fail, while still clearing hover/active
state. | 1447 // So we must force the hit-test to fail, while still clearing hover/active
state. |
1448 if (forceLeave) | 1448 if (forceLeave) |
1449 m_frame->document()->updateHoverActiveState(request, 0, &mouseEvent); | 1449 m_frame->document()->updateHoverActiveState(request, 0); |
1450 else | 1450 else |
1451 mev = prepareMouseEvent(request, mouseEvent); | 1451 mev = prepareMouseEvent(request, mouseEvent); |
1452 | 1452 |
1453 if (hoveredNode) | 1453 if (hoveredNode) |
1454 *hoveredNode = mev.hitTestResult(); | 1454 *hoveredNode = mev.hitTestResult(); |
1455 | 1455 |
1456 Scrollbar* scrollbar = nullptr; | 1456 Scrollbar* scrollbar = nullptr; |
1457 | 1457 |
1458 if (m_resizeScrollableArea && m_resizeScrollableArea->inResizeMode()) | 1458 if (m_resizeScrollableArea && m_resizeScrollableArea->inResizeMode()) |
1459 m_resizeScrollableArea->resize(mouseEvent, m_offsetFromResizeCorner); | 1459 m_resizeScrollableArea->resize(mouseEvent, m_offsetFromResizeCorner); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1550 return true; | 1550 return true; |
1551 } | 1551 } |
1552 | 1552 |
1553 if (m_frameSetBeingResized) | 1553 if (m_frameSetBeingResized) |
1554 return !dispatchMouseEvent(EventTypeNames::mouseup, m_frameSetBeingResiz
ed.get(), m_clickCount, mouseEvent, false); | 1554 return !dispatchMouseEvent(EventTypeNames::mouseup, m_frameSetBeingResiz
ed.get(), m_clickCount, mouseEvent, false); |
1555 | 1555 |
1556 if (m_lastScrollbarUnderMouse) { | 1556 if (m_lastScrollbarUnderMouse) { |
1557 invalidateClick(); | 1557 invalidateClick(); |
1558 m_lastScrollbarUnderMouse->mouseUp(mouseEvent); | 1558 m_lastScrollbarUnderMouse->mouseUp(mouseEvent); |
1559 bool setUnder = false; | 1559 bool setUnder = false; |
1560 return !dispatchMouseEvent(EventTypeNames::mouseup, m_lastNodeUnderMouse
.get(), m_clickCount, mouseEvent, setUnder); | 1560 return !dispatchMouseEvent(EventTypeNames::mouseup, m_nodeUnderMouse.get
(), m_clickCount, mouseEvent, setUnder); |
1561 } | 1561 } |
1562 | 1562 |
1563 // Mouse events simulated from touch should not hit-test again. | 1563 // Mouse events simulated from touch should not hit-test again. |
1564 ASSERT(!mouseEvent.fromTouch()); | 1564 ASSERT(!mouseEvent.fromTouch()); |
1565 | 1565 |
1566 HitTestRequest::HitTestRequestType hitType = HitTestRequest::Release; | 1566 HitTestRequest::HitTestRequestType hitType = HitTestRequest::Release; |
1567 HitTestRequest request(hitType); | 1567 HitTestRequest request(hitType); |
1568 MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent); | 1568 MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent); |
1569 LocalFrame* subframe = m_capturingMouseEventsNode.get() ? subframeForTargetN
ode(m_capturingMouseEventsNode.get()) : subframeForHitTestResult(mev); | 1569 LocalFrame* subframe = m_capturingMouseEventsNode.get() ? subframeForTargetN
ode(m_capturingMouseEventsNode.get()) : subframeForHitTestResult(mev); |
1570 if (m_eventHandlerWillResetCapturingMouseEventsNode) | 1570 if (m_eventHandlerWillResetCapturingMouseEventsNode) |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1826 } | 1826 } |
1827 | 1827 |
1828 MouseEventWithHitTestResults EventHandler::prepareMouseEvent(const HitTestReques
t& request, const PlatformMouseEvent& mev) | 1828 MouseEventWithHitTestResults EventHandler::prepareMouseEvent(const HitTestReques
t& request, const PlatformMouseEvent& mev) |
1829 { | 1829 { |
1830 ASSERT(m_frame); | 1830 ASSERT(m_frame); |
1831 ASSERT(m_frame->document()); | 1831 ASSERT(m_frame->document()); |
1832 | 1832 |
1833 return m_frame->document()->prepareMouseEvent(request, contentPointFromRootF
rame(m_frame, mev.position()), mev); | 1833 return m_frame->document()->prepareMouseEvent(request, contentPointFromRootF
rame(m_frame, mev.position()), mev); |
1834 } | 1834 } |
1835 | 1835 |
1836 void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMo
useEvent& mouseEvent, bool fireMouseOverOut) | 1836 void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMo
useEvent& mouseEvent, bool fireMouseEvents) |
1837 { | 1837 { |
1838 Node* result = targetNode; | 1838 Node* result = targetNode; |
1839 | 1839 |
1840 // If we're capturing, we always go right to that node. | 1840 // If we're capturing, we always go right to that node. |
1841 if (m_capturingMouseEventsNode) | 1841 if (m_capturingMouseEventsNode) |
1842 result = m_capturingMouseEventsNode.get(); | 1842 result = m_capturingMouseEventsNode.get(); |
1843 else { | 1843 else { |
1844 // If the target node is a text node, dispatch on the parent node - rdar
://4196646 | 1844 // If the target node is a text node, dispatch on the parent node - rdar
://4196646 |
1845 if (result && result->isTextNode()) | 1845 if (result && result->isTextNode()) |
1846 result = NodeRenderingTraversal::parent(*result); | 1846 result = NodeRenderingTraversal::parent(*result); |
1847 } | 1847 } |
1848 m_nodeUnderMouse = result; | 1848 m_nodeUnderMouse = result; |
1849 | 1849 |
1850 // Fire mouseout/mouseover if the mouse has shifted to a different node. | 1850 if (fireMouseEvents) { |
1851 if (fireMouseOverOut) { | |
1852 DeprecatedPaintLayer* layerForLastNode = layerForNode(m_lastNodeUnderMou
se.get()); | 1851 DeprecatedPaintLayer* layerForLastNode = layerForNode(m_lastNodeUnderMou
se.get()); |
1853 DeprecatedPaintLayer* layerForNodeUnderMouse = layerForNode(m_nodeUnderM
ouse.get()); | 1852 DeprecatedPaintLayer* layerForNodeUnderMouse = layerForNode(m_nodeUnderM
ouse.get()); |
1854 Page* page = m_frame->page(); | 1853 Page* page = m_frame->page(); |
1855 | 1854 |
1856 if (m_lastNodeUnderMouse && (!m_nodeUnderMouse || m_nodeUnderMouse->docu
ment() != m_frame->document())) { | 1855 if (m_lastNodeUnderMouse && (!m_nodeUnderMouse || m_nodeUnderMouse->docu
ment() != m_frame->document())) { |
1857 // The mouse has moved between frames. | 1856 // The mouse has moved between frames. |
1858 if (LocalFrame* frame = m_lastNodeUnderMouse->document().frame()) { | 1857 if (LocalFrame* frame = m_lastNodeUnderMouse->document().frame()) { |
1859 if (FrameView* frameView = frame->view()) | 1858 if (FrameView* frameView = frame->view()) |
1860 frameView->mouseExitedContentArea(); | 1859 frameView->mouseExitedContentArea(); |
1861 } | 1860 } |
(...skipping 13 matching lines...) Expand all Loading... |
1875 // The mouse has moved between layers. | 1874 // The mouse has moved between layers. |
1876 if (ScrollableArea* scrollableAreaForNodeUnderMouse = associatedScro
llableArea(layerForNodeUnderMouse)) | 1875 if (ScrollableArea* scrollableAreaForNodeUnderMouse = associatedScro
llableArea(layerForNodeUnderMouse)) |
1877 scrollableAreaForNodeUnderMouse->mouseEnteredContentArea(); | 1876 scrollableAreaForNodeUnderMouse->mouseEnteredContentArea(); |
1878 } | 1877 } |
1879 | 1878 |
1880 if (m_lastNodeUnderMouse && m_lastNodeUnderMouse->document() != m_frame-
>document()) { | 1879 if (m_lastNodeUnderMouse && m_lastNodeUnderMouse->document() != m_frame-
>document()) { |
1881 m_lastNodeUnderMouse = nullptr; | 1880 m_lastNodeUnderMouse = nullptr; |
1882 m_lastScrollbarUnderMouse = nullptr; | 1881 m_lastScrollbarUnderMouse = nullptr; |
1883 } | 1882 } |
1884 | 1883 |
1885 if (m_lastNodeUnderMouse != m_nodeUnderMouse) { | 1884 if (m_lastNodeUnderMouse != m_nodeUnderMouse) |
1886 // send mouseout event to the old node | 1885 sendMouseEventsForNodeTransition(m_lastNodeUnderMouse.get(), m_nodeU
nderMouse.get(), mouseEvent); |
1887 if (m_lastNodeUnderMouse) | 1886 |
1888 m_lastNodeUnderMouse->dispatchMouseEvent(mouseEvent, EventTypeNa
mes::mouseout, 0, m_nodeUnderMouse.get()); | |
1889 // send mouseover event to the new node | |
1890 if (m_nodeUnderMouse) | |
1891 m_nodeUnderMouse->dispatchMouseEvent(mouseEvent, EventTypeNames:
:mouseover, 0, m_lastNodeUnderMouse.get()); | |
1892 } | |
1893 m_lastNodeUnderMouse = m_nodeUnderMouse; | 1887 m_lastNodeUnderMouse = m_nodeUnderMouse; |
1894 } | 1888 } |
1895 } | 1889 } |
1896 | 1890 |
| 1891 void EventHandler::sendMouseEventsForNodeTransition(Node* exitedNode, Node* ente
redNode, const PlatformMouseEvent& mouseEvent) |
| 1892 { |
| 1893 ASSERT(exitedNode != enteredNode); |
| 1894 |
| 1895 // First, dispatch mouseout and mouseover events (which bubble to ancestors) |
| 1896 if (exitedNode) |
| 1897 exitedNode->dispatchMouseEvent(mouseEvent, EventTypeNames::mouseout, 0,
enteredNode); |
| 1898 if (enteredNode) |
| 1899 enteredNode->dispatchMouseEvent(mouseEvent, EventTypeNames::mouseover, 0
, exitedNode); |
| 1900 |
| 1901 // Then dispatch mouseenter and mouseleave events. These are non-bubbling ev
ents, and they are dispatched if there |
| 1902 // is a capturing event handler on an ancestor or a normal event handler on
the element itself. This special |
| 1903 // handling is necessary to avoid O(n^2) capturing event handler checks. |
| 1904 // |
| 1905 // Note, however, that this optimization can possibly cause some unanswere
d/missing/redundant mouseenter or |
| 1906 // mouseleave events in certain contrived eventhandling scenarios, e.g., whe
n: |
| 1907 // - the mouseleave handler for a node sets the only capturing-mouseleave-li
stener in its ancestor, or |
| 1908 // - DOM mods in any mouseenter/mouseleave handler changes the common ancest
or of exited & entered nodes, etc. |
| 1909 // We think the spec specifies a "frozen" state to avoid such corner cases (
check the discussion on "candidate event |
| 1910 // listeners" at http://www.w3.org/TR/uievents), but our code below preserve
s one such behavior from past only to |
| 1911 // match Firefox and IE behavior. |
| 1912 // |
| 1913 // TODO(mustaq): Confirm spec conformance, double-check with other browsers. |
| 1914 |
| 1915 // Create lists of all exited/entered ancestors. |
| 1916 WillBeHeapVector<RefPtrWillBeMember<Node>, 32> exitedAncestors; |
| 1917 WillBeHeapVector<RefPtrWillBeMember<Node>, 32> enteredAncestors; |
| 1918 for (Node* node = exitedNode; node; node = NodeRenderingTraversal::parent(*n
ode)) { |
| 1919 exitedAncestors.append(node); |
| 1920 } |
| 1921 for (Node* node = enteredNode; node; node = NodeRenderingTraversal::parent(*
node)) { |
| 1922 enteredAncestors.append(node); |
| 1923 } |
| 1924 |
| 1925 size_t numExitedAncestors = exitedAncestors.size(); |
| 1926 size_t numEnteredAncestors = enteredAncestors.size(); |
| 1927 |
| 1928 // Locate the common ancestor in the two lists. Start with the assumption th
at it's off both the lists. |
| 1929 size_t exitedAncestorIndex = numExitedAncestors; |
| 1930 size_t enteredAncestorIndex = numEnteredAncestors; |
| 1931 for (size_t j = 0; j < numExitedAncestors; j++) { |
| 1932 for (size_t i = 0; i < numEnteredAncestors; i++) { |
| 1933 if (exitedAncestors[j] == enteredAncestors[i]) { |
| 1934 exitedAncestorIndex = j; |
| 1935 enteredAncestorIndex = i; |
| 1936 break; |
| 1937 } |
| 1938 } |
| 1939 if (exitedAncestorIndex < numExitedAncestors) |
| 1940 break; |
| 1941 } |
| 1942 |
| 1943 // Determine if there is a capturing mouseleave listener in an ancestor. |
| 1944 bool exitedNodeHasCapturingAncestor = false; |
| 1945 for (size_t j = 0; j < numExitedAncestors; j++) { |
| 1946 if (exitedAncestors[j]->hasCapturingEventListeners(EventTypeNames::mouse
leave)) |
| 1947 exitedNodeHasCapturingAncestor = true; |
| 1948 } |
| 1949 |
| 1950 // Send mouseleave events to appropriate exited ancestors, in child-to-paren
t order. |
| 1951 for (size_t j = 0; j < exitedAncestorIndex; j++) { |
| 1952 if (exitedNodeHasCapturingAncestor || exitedAncestors[j]->hasEventListen
ers(EventTypeNames::mouseleave)) |
| 1953 exitedAncestors[j]->dispatchMouseEvent(mouseEvent, EventTypeNames::m
ouseleave, 0, enteredNode); |
| 1954 } |
| 1955 |
| 1956 // Determine if there is a capturing mouseenter listener in an ancestor. Thi
s must be done /after/ dispatching the |
| 1957 // mouseleave events because the handler for mouseleave might set a capturin
g mouseenter handler. |
| 1958 bool enteredNodeHasCapturingAncestor = false; |
| 1959 for (size_t i = 0; i < numEnteredAncestors; i++) { |
| 1960 if (enteredAncestors[i]->hasCapturingEventListeners(EventTypeNames::mous
eenter)) |
| 1961 enteredNodeHasCapturingAncestor = true; |
| 1962 } |
| 1963 |
| 1964 // Send mouseenter events to appropriate entered ancestors, in parent-to-chi
ld order. |
| 1965 for (size_t i = enteredAncestorIndex; i > 0; i--) { |
| 1966 if (enteredNodeHasCapturingAncestor || enteredAncestors[i-1]->hasEventLi
steners(EventTypeNames::mouseenter)) |
| 1967 enteredAncestors[i-1]->dispatchMouseEvent(mouseEvent, EventTypeNames
::mouseenter, 0, exitedNode); |
| 1968 } |
| 1969 } |
| 1970 |
1897 // The return value means 'continue default handling.' | 1971 // The return value means 'continue default handling.' |
| 1972 // TODO(mustaq): setUnder needs a more informative name. |
1898 bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targe
tNode, int clickCount, const PlatformMouseEvent& mouseEvent, bool setUnder) | 1973 bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targe
tNode, int clickCount, const PlatformMouseEvent& mouseEvent, bool setUnder) |
1899 { | 1974 { |
1900 updateMouseEventTargetNode(targetNode, mouseEvent, setUnder); | 1975 updateMouseEventTargetNode(targetNode, mouseEvent, setUnder); |
1901 return !m_nodeUnderMouse || m_nodeUnderMouse->dispatchMouseEvent(mouseEvent,
eventType, clickCount); | 1976 return !m_nodeUnderMouse || m_nodeUnderMouse->dispatchMouseEvent(mouseEvent,
eventType, clickCount); |
1902 } | 1977 } |
1903 | 1978 |
1904 // The return value means 'swallow event' (was handled), as for other handle* fu
nctions. | 1979 // The return value means 'swallow event' (was handled), as for other handle* fu
nctions. |
1905 bool EventHandler::handleMouseFocus(const MouseEventWithHitTestResults& targeted
Event) | 1980 bool EventHandler::handleMouseFocus(const MouseEventWithHitTestResults& targeted
Event) |
1906 { | 1981 { |
1907 const PlatformMouseEvent& mouseEvent = targetedEvent.event(); | 1982 const PlatformMouseEvent& mouseEvent = targetedEvent.event(); |
(...skipping 2041 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3949 | 4024 |
3950 // If it's in the direction to hide the top controls, only consume when the
frame can also scroll. | 4025 // If it's in the direction to hide the top controls, only consume when the
frame can also scroll. |
3951 if (m_frame->view()->scrollPosition().y() < m_frame->view()->maximumScrollPo
sition().y()) | 4026 if (m_frame->view()->scrollPosition().y() < m_frame->view()->maximumScrollPo
sition().y()) |
3952 return true; | 4027 return true; |
3953 | 4028 |
3954 return false; | 4029 return false; |
3955 } | 4030 } |
3956 | 4031 |
3957 | 4032 |
3958 } // namespace blink | 4033 } // namespace blink |
OLD | NEW |